diff --git a/src/spi_core.v b/src/spi_core.v new file mode 100644 index 0000000..1f4b9a1 --- /dev/null +++ b/src/spi_core.v @@ -0,0 +1,125 @@ + +module spi_core( + input clk, rst, + + input sck, sdi, sdo, ncs, + + output reg cs_rising, + output reg cs_falling, + output reg data[15:0], + output reg data_valid +); + +reg data_release_flag_sysclk; + +reg [15:0] rxbuf_sck; +reg [15:0] data_reg_sck; +reg data_good_flag_sck; +always @(posedge sck or posedge ncs) begin + if (ncs) begin /* asynchronous reset */ + data_reg_sck <= 16'h0001; + data_good_flag_sck <= 0; + + end else begin + if (data_reg_sck[15]) begin + rxbuf_sck <= {data_reg_sck[14:0], sdi}; + data_reg_sck <= 16'h0001; + data_good_flag_sck <= 1; + + end else begin + data_reg_sck <= {data_reg_sck[14:0], sdi}; + end + end +end + +reg cs_rising_sysclk; +reg cs_falling_sysclk; +reg last_cs_sysclk; +reg [1:0] data_good_flag_sysclk; +always @(posedge clk) begin + if (rst) begin + last_cs_sysclk <= cs; + cs_rising <= 0; + cs_falling <= 0; + data_valid <= 0; + data <= 0; + data_release_flag_sysclk <= 0; + data_good_flag_sysclk <= 0; + + end else begin + data_good_flag_sysclk <= {data-good_flag_sysclk[0], data_good_flag_sck}; + + if (last_cs_sysclk = 0 && cs == 1) begin + cs_rising <= 1; + cs_falling <= 0; + end else begin if (last_cs_sysclk = 1 && cs == 0) begin + cs_rising <= 0; + cs_falling <= 1; + end + + if (!last_cs_sysclk && data_good_flag_sysclk[0] && data_good_flag_sysclk[1]) begin + data <= rxbuf_sck; + data_release_flag_sysclk <= 1; + end + end +end + +endmodule + +module cdc_reg ( + input in_clk, in_rst, + input [WORDSIZE-1:0] in_data, + input in_data_valid, + + input out_clk, out_rst, + output reg [WORDSIZE-1:0] out_data, + output reg out_data_valid, +); + +parameter WORDSIZE = 16; + +reg [2:0] wr_flags_in; +reg [WORDSIZE-1:0] reg_in [0:2]; +always @(posedge in_clk, posedge in_rst) begin + if (in_rst) begin + wr_flags_in <= 3'b000; + regs_in[0] <= 0; + regs_in[1] <= 0; + regs_in[2] <= 0; + + end else begin + case (regs_in) + 3'b001: begin regs_in[1] <= in_data; wr_flags_in <= 3'b010; end + 3'b010: begin regs_in[2] <= in_data; wr_flags_in <= 3'b100; end + 3'b100, 3'b000: begin regs_in[0] <= in_data; wr_flags_in <= 3'b001; end + endcase + end +end + +reg [2:0] wr_flags_out [0:1]; +always @(posedge out_clk) begin + if (out_rst) begin + wr_flags_out[0] <= 3'b000; + wr_flags_out[1] <= 3'b000; + + end else begin + wr_flags_out[0] <= wr_flags_in; + wr_flags_out[1] <= wr_flags_out[0]; + out_data_valid <= 0; + + if (wr_flags_out[0][0] && !wr_flags_out[1][0]) begin + out_data <= regs_in[0]; + out_data_valid <= 1; + + end else if (wr_flags_out[0][1] && !wr_flags_out[1][1]) begin + out_data <= regs_in[1]; + out_data_valid <= 1; + + end else if (wr_flags_out[0][2] && !wr_flags_out[1][2]) begin + out_data <= regs_in[2]; + out_data_valid <= 1; + end + end +end + +endmodule \ No newline at end of file diff --git a/test_bench/spi_core_tb.v b/test_bench/spi_core_tb.v new file mode 100644 index 0000000..e69de29