Last active
November 13, 2018 01:21
-
-
Save buttercutter/04cc7eebc739fb21ba33c00a7ee589b6 to your computer and use it in GitHub Desktop.
SPI flash controller for Winbond W25Q32 flash
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module SPI(clk, reset, data_valid, data_MOSI, data_ready, data_MISO, MISO, MOSI, clk_flash, CS_flash); | |
parameter MOSI_DATA_BITWIDTH = 8 + 24 + 256*8; // for page_program(02h) | |
parameter MISO_DATA_BITWIDTH = 8; | |
localparam INSTRUCTION_READ_DATA = 3; // Read Data (03h) instruction | |
input clk, reset; | |
input data_valid; | |
input [$clog2(MOSI_DATA_BITWIDTH)-1:0] data_MOSI; // data going into the slave (SPI flash) | |
output reg data_ready; | |
output reg [MISO_DATA_BITWIDTH-1:0] data_MISO; // data originating from slave (SPI flash) | |
input MISO; | |
output reg MOSI; | |
output clk_flash; | |
output reg CS_flash; | |
//output CS_flash = (reset) ? 1 : (in_index == 1 || out_index == 1) ? 0 : 1; | |
reg [($clog2(MISO_DATA_BITWIDTH)-1):0] in_index; | |
reg [($clog2(MOSI_DATA_BITWIDTH)-1):0] out_index; | |
assign clk_flash = clk; | |
always @(posedge clk) | |
begin | |
if(reset) begin | |
CS_flash <= 1; | |
end | |
else begin // 0 during SPI flash transaction, 1 during idling | |
if(data_valid) CS_flash <= 0; // CS is asserted low for writing of instruction and/or address to SPI slave (flash) | |
if((in_index == MISO_DATA_BITWIDTH) || ((out_index == MOSI_DATA_BITWIDTH + 1) && !read_en)) CS_flash <= 1; // SPI transaction finishes | |
end | |
end | |
always @(posedge clk) | |
begin | |
if(reset) begin | |
MOSI <= 1; | |
out_index <= 0; | |
end | |
else if(!CS_flash && (out_index <= MOSI_DATA_BITWIDTH)) begin // send data to slave (SPI flash) during the transaction | |
MOSI <= data_MOSI[out_index]; | |
out_index <= out_index + 1'b1; | |
end | |
else out_index <= 0; // for next SPI transaction | |
end | |
reg read_en; // for Read Data (03h) instruction, slave will send out the data to master immediately after the 24-bit address, no waiting cycles are needed | |
always @(negedge clk) | |
begin | |
if(reset) begin | |
read_en <= 0; | |
end | |
else if((data_MOSI == INSTRUCTION_READ_DATA) && (out_index == MOSI_DATA_BITWIDTH)) begin | |
read_en <= 1; | |
end | |
else read_en <= 0; // for next SPI transaction | |
end | |
always @(negedge clk) // this SPI flash sends out its data on the falling edge, so this flash controller has to follow SPI flash spec | |
begin | |
if(reset) begin | |
data_ready <= 0; | |
data_MISO <= 0; // all zeroes | |
in_index <= 0; // the shift register 'data_MISO' stores the data starting from LSB | |
end | |
else begin | |
if(in_index == MISO_DATA_BITWIDTH) begin | |
data_ready <= 1; // data reading from slave is complete or finished now | |
in_index <= 0; // for next SPI transaction | |
end | |
else begin | |
data_ready <= 0; | |
if(CS_flash && read_en && !data_ready) begin // read data from slave (SPI flash) during the transaction | |
data_MISO[in_index] <= MISO; | |
in_index <= in_index + 1'b1; | |
end | |
end | |
end | |
end | |
endmodule |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment