You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

260 lines
7.7 KiB

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;
initial begin
addr = 0;
wr_data = 0;
wr_en = 0;
spi_tx_pin = 0;
end
zutils_signal_filter #(
.FILTER_COUNT(5)
) 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
//
zutils_edge_detecter cs_edge_detecter (
.clk(clk),
.rst_n(rst_n),
.in_signal(spi_cs_pin_after_filter),
.in_signal_falling_edge(spi_cs_negedge_tri)
);
zutils_edge_detecter clk_edge_detecter (
.clk(clk),
.rst_n(rst_n),
.in_signal(spi_clk_pin_after_filter),
.in_signal_rising_edge(spi_clk_posedge_tri),
.in_signal_falling_edge(spi_clk_negedge_tri)
);
/*******************************************************************************
* SPI数据解析,及其部分状态更新 *
*******************************************************************************/
//
//
//
// cs : ----______________________________________________
// clk : ----------____----____----____----____----____----
// bitcnt : 0 1 2 ... 7 0
// rx : . . . . .
// tx : <======><======><======><======><======>
// valid : .
// byte_cnt: 0 1
//
wire [31:0] spi_clk_cnt;
wire [31:0] spi_byte_cnt;
wire [ 7:0] bit_cnt;
zutils_clk_parser clk_parser (
.clk (clk),
.rst_n(rst_n),
.cs_signal_in (spi_cs_pin_after_filter),
.clk_signal_in(spi_clk_pin_after_filter),
.clk_start_signal(spi_clk_start_signal),
.clk_mid_signal(spi_clk_mid_signal),
.clk_end_signal(spi_clk_end_signal),
.clk_cnt(spi_clk_cnt), //[31:0]
.byte_cnt(spi_byte_cnt), //[31:0]
.clk_bit_cnt(bit_cnt) //[7:0]
);
//
// 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
//
// 当 上升沿触发时,接收1bit数据
// 当 bit_cnt == 7时 接收完一byte数据
//
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 || spi_cs_pin_after_filter) begin
spi_rx_1byte_data <= 0;
spi_rx_1byte_data_valid <= 0;
end else begin
if (spi_clk_mid_signal) begin
spi_rx_1byte_data[bit_cnt] <= spi_rx_pin_after_filter;
if (bit_cnt == 7) spi_rx_1byte_data_valid <= 1;
end else begin
spi_rx_1byte_data_valid <= 0;
end
end
end
/*******************************************************************************
* 缓存接收到的数据 *
*******************************************************************************/
reg [7:0] spi_rx_data_cache[0:7];
genvar i;
always @(posedge clk or negedge rst_n) begin
if (!rst_n || spi_cs_pin_after_filter) begin
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 && spi_byte_cnt <= 7) begin
spi_rx_data_cache[spi_byte_cnt] <= spi_rx_1byte_data;
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 || spi_cs_pin_after_filter) begin
wr_en <= 0;
has_trigger_wr_en <= 0;
end else begin
if (!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