|
|
module spi_reg_reader ( input clk, //clock input input rst_n, //asynchronous reset input, low active
//regbus interface output reg [31:0] addr, output reg [31:0] wr_data, output reg wr_en, input wire [31:0] rd_data, //received serial data // input wire spi_cs_pin, // input wire spi_clk_pin, // input wire spi_rx_pin, // output reg spi_tx_pin );
parameter STATE_IDLE = 0; parameter STATE_RECEIVE_ADD = 1; parameter STATE_READ_REG = 2; parameter STATE_TRANSMIT_DATA = 3; parameter STATE_RECEIVE_DATA = 4; parameter STATE_WRITE_REG = 5; parameter ADDRESS_WIDTH_BYTE_NUM = 2;
zutils_signal_filter #(.FILTER_COUNT(2)) cs_filter ( .clk(clk), .rst_n(rst_n), .in(spi_cs_pin), .out(spi_cs_pin_after_filter) );
zutils_signal_filter #(.FILTER_COUNT(2)) clk_filter ( .clk(clk), .rst_n(rst_n), .in(spi_clk_pin), .out(spi_clk_pin_after_filter) );
zutils_signal_filter #(.FILTER_COUNT(2)) spi_rx_filter ( .clk(clk), .rst_n(rst_n), .in(spi_rx_pin), .out(spi_rx_pin_after_filter) );
// // 捕获SPI_CS的下降沿 和 SPI_CLK的上升沿 // detect: // spi_cs_negedge_tri // spi_clk_posedge_tri //
reg spi_cs_last_state = 0; reg spi_clk_last_state = 0; assign spi_clk_posedge_tri = spi_clk_pin_after_filter & ~spi_clk_last_state; assign spi_clk_negedge_tri = ~spi_clk_pin_after_filter & spi_clk_last_state; always @(posedge clk or negedge rst_n) begin if (!rst_n) begin spi_cs_last_state <= 1; spi_clk_last_state <= 1; end else begin spi_cs_last_state <= spi_cs_pin_after_filter; spi_clk_last_state <= spi_clk_pin_after_filter; end end
/******************************************************************************* * SPI数据解析,及其部分状态更新 * *******************************************************************************/
// // // // cs : ----______________________________________________ // clk : ----------____----____----____----____----____---- // bitcnt : 0 1 2 ... 7 0 // rx : . . . . . // tx : <======><======><======><======><======> // valid : . // byte_cnt: 0 1 //
reg [7:0] bit_cnt = 0; reg first_edge = 1; // first_edge 状态更新 // 1:在spi_cs下降沿时候更新为0 // 2:复位时候更新为1 // bit_cnt 状态更新 // 1:在spi_clk下降沿时候更新 // 2:first_edge == 1时候更新 // always @(posedge clk or negedge rst_n) begin if (!rst_n) begin bit_cnt <= 0; first_edge <= 1; end else begin if (spi_cs_pin_after_filter) begin bit_cnt <= 0; first_edge <= 1; end else begin if (spi_clk_negedge_tri) begin
if (first_edge) begin bit_cnt <= 0; first_edge <= 0; end else begin if (bit_cnt == 7) bit_cnt <= 0; else bit_cnt <= bit_cnt + 1; end end end end end
// // byte_cnt // 1:在spi_clk下降沿时候更新 // 2:在bit_cnt == 7时候更新 // reg [7:0] spi_byte_cnt = 0; //byte_cnt always @(posedge clk or negedge rst_n) begin if (!rst_n) begin spi_byte_cnt <= 0; end else begin if (spi_cs_pin_after_filter) begin spi_byte_cnt <= 0; end else begin if (spi_clk_negedge_tri && bit_cnt == 7) begin spi_byte_cnt <= spi_byte_cnt + 1; end end end end
// // spi_tx_1byte_data 发送 // reg [7:0] spi_tx_1byte_data = 0; always @(*) begin
spi_tx_pin <= spi_tx_1byte_data[bit_cnt]; end
// // spi_rx_1byte_data // spi_rx_1byte_data_valid // reg [7:0] spi_rx_1byte_data = 0; reg spi_rx_1byte_data_valid = 0; always @(posedge clk or negedge rst_n) begin if (!rst_n) begin spi_rx_1byte_data <= 0; spi_rx_1byte_data_valid <= 0; end else begin if (spi_cs_pin_after_filter) begin spi_rx_1byte_data <= 0; spi_rx_1byte_data_valid <= 0; end else begin
if (spi_clk_posedge_tri) begin spi_rx_1byte_data[bit_cnt] <= spi_rx_pin_after_filter; end
if (spi_clk_negedge_tri && bit_cnt == 7) spi_rx_1byte_data_valid <= 1; else spi_rx_1byte_data_valid <= 0;
end end end
/******************************************************************************* * 缓存接收到的数据 * *******************************************************************************/
reg [7:0] spi_rx_data_cache [0:4+4-1]; reg [7:0] rx_byte_count = 0; genvar i;
always @(posedge clk or negedge rst_n) begin if (!rst_n) begin rx_byte_count <= 0; spi_rx_data_cache[0] <= 0; spi_rx_data_cache[1] <= 0; spi_rx_data_cache[2] <= 0; spi_rx_data_cache[3] <= 0; spi_rx_data_cache[4] <= 0; spi_rx_data_cache[5] <= 0; spi_rx_data_cache[6] <= 0; spi_rx_data_cache[7] <= 0;
end else begin if (spi_cs_pin_after_filter) begin // 失能状态 rx_byte_count <= 0; spi_rx_data_cache[0] <= 0; spi_rx_data_cache[1] <= 0; spi_rx_data_cache[2] <= 0; spi_rx_data_cache[3] <= 0; spi_rx_data_cache[4] <= 0; spi_rx_data_cache[5] <= 0; spi_rx_data_cache[6] <= 0; spi_rx_data_cache[7] <= 0; end else begin // 选中状态 if (spi_rx_1byte_data_valid) begin rx_byte_count <= rx_byte_count + 1; if (rx_byte_count < ADDRESS_WIDTH_BYTE_NUM + 4) begin spi_rx_data_cache[rx_byte_count] <= spi_rx_1byte_data; end end end end end
/******************************************************************************* * 自动设置SPI需要发送的数据 spi_tx_1byte_data * *******************************************************************************/ always @(*) begin
case (spi_byte_cnt) ADDRESS_WIDTH_BYTE_NUM + 0: spi_tx_1byte_data <= rd_data[7:0]; ADDRESS_WIDTH_BYTE_NUM + 1: spi_tx_1byte_data <= rd_data[15:8]; ADDRESS_WIDTH_BYTE_NUM + 2: spi_tx_1byte_data <= rd_data[23:16]; ADDRESS_WIDTH_BYTE_NUM + 3: spi_tx_1byte_data <= rd_data[31:24]; default: spi_tx_1byte_data <= 0; endcase end
/******************************************************************************* * 自动设置addr数值 * *******************************************************************************/ always @(*) begin
case (ADDRESS_WIDTH_BYTE_NUM) 0: begin addr[7:0] <= 0; addr[15:8] <= 0; addr[23:16] <= 0; addr[31:24] <= 0; end 1: begin addr[7:0] <= {1'b0, spi_rx_data_cache[0][6:0]}; addr[15:8] <= 0; addr[23:16] <= 0; addr[31:24] <= 0; end 2: begin addr[7:0] <= spi_rx_data_cache[0][7:0]; addr[15:8] <= {1'b0, spi_rx_data_cache[1][6:0]}; addr[23:16] <= 0; addr[31:24] <= 0; end 3: begin addr[7:0] <= spi_rx_data_cache[0][7:0]; addr[15:8] <= spi_rx_data_cache[1][7:0]; addr[23:16] <= {1'b0, spi_rx_data_cache[2][6:0]}; addr[31:24] <= 0; end 4: begin addr[7:0] <= spi_rx_data_cache[0][7:0]; addr[15:8] <= spi_rx_data_cache[1][7:0]; addr[23:16] <= spi_rx_data_cache[2][7:0]; addr[31:24] <= {1'b0, spi_rx_data_cache[3][6:0]}; end endcase end
/******************************************************************************* * wr_data * *******************************************************************************/ always @(*) begin
wr_data[7:0] <= spi_rx_data_cache[ADDRESS_WIDTH_BYTE_NUM]; wr_data[15:8] <= spi_rx_data_cache[ADDRESS_WIDTH_BYTE_NUM+1]; wr_data[23:16] <= spi_rx_data_cache[ADDRESS_WIDTH_BYTE_NUM+2]; wr_data[31:24] <= spi_rx_data_cache[ADDRESS_WIDTH_BYTE_NUM+3]; end
/******************************************************************************* * wr_en * *******************************************************************************/ reg has_trigger_wr_en = 0; always @(posedge clk or negedge rst_n) begin if (!rst_n) begin wr_en <= 0; has_trigger_wr_en <= 0; end else begin if (spi_cs_pin_after_filter) begin wr_en <= 0; has_trigger_wr_en <= 0; end else if (!spi_cs_pin_after_filter && // !has_trigger_wr_en && // spi_byte_cnt == ADDRESS_WIDTH_BYTE_NUM + 4 && // spi_rx_data_cache[ADDRESS_WIDTH_BYTE_NUM-1][7]) begin wr_en <= 1; has_trigger_wr_en <= 1; end else begin wr_en <= 0; end end end
endmodule
|