123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242 |
- /*
- * Reads SPI flash module
- * Enables quad spi mode with coninous mode on
- * Reads instructions of 32 bits
- */
- module SPIreader (
- input clk, reset,
- output cs,
- input [23:0] address,
- output [31:0] instr,
- input start,
- output reg initDone = 1'b0,
- output reg recvDone = 1'b0,
- output write,
- output spi_clk,
- output io0_out, io1_out, io2_out, io3_out, //d, q wp, hold
- input io0_in, io1_in, io2_in, io3_in //d, q wp, hold
- );
- wire [23:0] a = {address, 2'b0};
- reg clkDiv = 1'b0;
- reg [7:0] b0 = 8'd0;
- reg [7:0] b1 = 8'd0;
- reg [7:0] b2 = 8'd0;
- reg [7:0] b3 = 8'd0;
- reg [6:0] counter = 7'd0;
- reg [2:0] phase = 3'd0;
- wire rising = clkDiv == 1'b1;
- wire falling = clkDiv == 1'b0;
- assign spi_clk = rising;
- /*
- 0 = initial wait (goto 5)
- 1 = send quad fast read opcode (goto 3)
- 2 = idle - ready to read
- 3 = send address, continuous mode bits and dummy bits
- 4 = receive 32 bits (goto 2)
- 5 = reset continuous mode
- 6 = wait after reset (goto 1)
- */
- //COMMANDS
- wire [7:0] opcode = 8'hEB;
- wire [11:0] addr_io0 = {a[20], a[16], a[12], a[8], a[4], a[0], 2'b00, 4'b0000};
- wire [11:0] addr_io1 = {a[21], a[17], a[13], a[9], a[5], a[1], 2'b10, 4'b0000};
- wire [11:0] addr_io2 = {a[22], a[18], a[14], a[10], a[6], a[2], 2'b00, 4'b0000};
- wire [11:0] addr_io3 = {a[23], a[19], a[15], a[11], a[7], a[3], 2'b00, 4'b0000};
- assign write = (phase == 5) ? 1'b1 :
- (phase == 1) ? 1'b1 :
- (phase == 3) ? 1'b1 :
- 1'b0;
- assign cs = (phase == 1) ? 1'b0 :
- (phase == 3) ? 1'b0 :
- (phase == 4) ? 1'b0 :
- (phase == 5) ? 1'b0 :
- 1'b1;
- //d
- assign io0_out = (phase == 5) ? 1'b1 :
- (phase == 1) ? opcode[7-counter] :
- (phase == 3) ? addr_io0[11-counter] :
- 1'b0;
- //q
- assign io1_out = (phase == 1) ? 1'b1 :
- (phase == 3) ? addr_io1[11-counter] :
- 1'b0;
- //wp
- assign io2_out = (phase == 1) ? 1'b1 :
- (phase == 3) ? addr_io2[11-counter] :
- 1'b0;
- //hold
- assign io3_out = (phase == 1) ? 1'b1 :
- (phase == 3) ? addr_io3[11-counter] :
- 1'b0;
- //mapping read data to instruction
- assign instr = {
- b3[7], b2[7], b1[7], b0[7], b3[6], b2[6], b1[6], b0[6],
- b3[5], b2[5], b1[5], b0[5], b3[4], b2[4], b1[4], b0[4],
- b3[3], b2[3], b1[3], b0[3], b3[2], b2[2], b1[2], b0[2],
- b3[1], b2[1], b1[1], b0[1], b3[0], b2[0], b1[0], b0[0]
- };
- always @(posedge clk)
- begin
- if (reset)
- begin
- phase <= 3'd0;
- counter <= 7'd0;
- initDone <= 1'd0;
- clkDiv <= 1'b0;
- b0 <= 8'd0;
- b1 <= 8'd0;
- b2 <= 8'd0;
- b3 <= 8'd0;
- recvDone <= 1'b0;
- end
- else
- begin
- clkDiv <= clkDiv + 1'b1;
- if (rising)
- begin
- case (phase)
- //initial state,
- 3'd0:
- begin
- if (counter == 7'd3)
- begin
- counter <= 7'd0;
- phase <= 5;
- end
- else begin
- counter <= counter + 1'b1;
- end
- end
- //send quad fast read opcode
- 3'd1:
- begin
- if (counter == 7'd7)
- begin
- counter <= 7'd0;
- phase <= 3;
- end
- else begin
- counter <= counter + 1'b1;
- end
- end
- //idle - ready to read when triggered (after some instruction delay)
- 3'd2:
- begin
- recvDone <= 1'b0;
- if (counter == 7'd4) //could be 3, but one extra cycle delay to wait for start from MU to go low
- begin
- initDone <= 1'b1;
- if (start)
- begin
- counter <= 7'd0;
- phase <= 3'd3;
- end
- end
- else begin
- counter <= counter + 1'b1;
- end
- end
- //send address, continuous mode bits and dummy bits
- 3'd3:
- begin
- if (counter == 7'd11)
- begin
- counter <= 7'd0;
- phase <= 3'd4;
- end
- else begin
- counter <= counter + 1'b1;
- end
- end
- //receive 32 bits
- 3'd4:
- begin
- if (counter == 7'd7)
- begin
- counter <= 7'd0;
- phase <= 3'd7;
- end
- else begin
- counter <= counter + 1'b1;
- end
- end
- //reset
- 3'd5:
- begin
- if (counter == 7)
- begin
- counter <= 7'd0;
- phase <= 3'd6;
- end
- else begin
- counter <= counter + 1'b1;
- end
- end
- //wait after reset
- 3'd6:
- begin
- if (counter == 7'd3)
- begin
- counter <= 7'd0;
- phase <= 3'd1;
- end
- else begin
- counter <= counter + 1'b1;
- end
- end
- // recvDone
- 3'd7:
- begin
- recvDone <= 1'b1;
- phase <= 3'd2;
- end
- default:
- begin
- phase <= 3'd0;
- end
- endcase
- end
- if (falling)
- begin
- if (phase == 3'd4)
- begin
- b0[7-counter] <= io0_in;
- b1[7-counter] <= io1_in;
- b2[7-counter] <= io2_in;
- b3[7-counter] <= io3_in;
- end
- end
- end
- end
- endmodule
|