forked from p_lusterinc_xsync/xsync_fpge
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.
312 lines
9.2 KiB
312 lines
9.2 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;
|
|
|
|
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
|