Created
March 23, 2024 13:39
-
-
Save nickfox-taterli/fe3713455b0ba55c73b63d45512f2bd9 to your computer and use it in GitHub Desktop.
spi slave at tang nano 20k
This file contains 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 top( | |
input wire clk_i, | |
input wire rst_i, | |
input wire sdi_csn_i, | |
input wire sdi_clk_i, | |
input wire sdi_dat_i, | |
output wire sdi_dat_o, | |
output wire [5:0] led | |
); | |
assign rstn_i = !rst_i; | |
// 滤波计数器 | |
reg [3:0] filter_sck_i; | |
reg [3:0] filter_csn_i; | |
reg [3:0] filter_sdi_i; | |
assign real_sck_i = (filter_sck_i == 4'b1111) ? 1'b1 : | |
(filter_sck_i == 4'b0000) ? 1'b0 : | |
real_sck_i; | |
assign real_csn_i = (filter_csn_i == 4'b1111) ? 1'b1 : | |
(filter_csn_i == 4'b0000) ? 1'b0 : | |
sdi_csn_i; | |
assign real_dat_i = (filter_sdi_i == 4'b1111) ? 1'b1 : | |
(filter_sdi_i == 4'b0000) ? 1'b0 : | |
sdi_dat_i; | |
always @(posedge clk_i or negedge rstn_i) begin | |
if(!rstn_i) begin | |
filter_sck_i = 3'b0; | |
filter_csn_i = 3'b1111; | |
filter_sdi_i = 3'b0; | |
end else begin | |
filter_sck_i <= {filter_sck_i[2:0],sdi_clk_i}; | |
filter_csn_i <= {filter_csn_i[2:0],sdi_csn_i}; | |
filter_sdi_i <= {filter_sdi_i[2:0],sdi_dat_i}; | |
end | |
end | |
reg [2:0] sync_sck_ff; | |
reg [1:0] sync_csn_ff; | |
reg [1:0] sync_sdi_ff; | |
// SCK 边缘采集 | |
assign sync_sck = sync_sck_ff[1] ^ sync_sck_ff[2]; | |
assign sync_csn = sync_csn_ff[1]; | |
assign sync_sdi = sync_sdi_ff[1]; | |
// 跨时钟域处理 | |
always @(posedge clk_i or negedge rstn_i) begin | |
if(!rstn_i) begin | |
sync_sck_ff <= 1'b0; | |
sync_csn_ff <= 1'b0; | |
sync_sdi_ff <= 1'b0; | |
end else begin | |
sync_sck_ff <= {sync_sck_ff[1:0],real_sck_i}; | |
sync_csn_ff <= {sync_csn_ff[0],real_csn_i}; | |
sync_sdi_ff <= {sync_sdi_ff[0],real_dat_i}; | |
end | |
end | |
reg [1:0] serial_state; | |
reg [3:0] serial_cnt; | |
reg [7:0] serial_sreg; | |
reg serial_sdi_ff; | |
reg serial_start; | |
reg serial_done; | |
assign sdi_dat_o = serial_sreg[7]; | |
always @(posedge clk_i or negedge rstn_i) begin | |
if(!rstn_i) begin | |
serial_start <= 1'b0; | |
serial_done <= 1'b0; | |
serial_state <= 3'b0; | |
serial_cnt <= 4'b0; | |
serial_sreg <= 8'b0; | |
serial_sdi_ff <= 1'b0; | |
end | |
else begin | |
serial_start <= 1'b0; | |
serial_done <= 1'b0; | |
case (serial_state) | |
2'b00:begin | |
serial_cnt <= 4'b0; | |
serial_sreg <= 8'h00; | |
if(!sync_csn) begin | |
serial_start <= 1'b1; | |
serial_state[1:0] <= 2'b10; | |
end | |
end | |
2'b10:begin | |
serial_sdi_ff <= sync_sdi; | |
if(sync_csn) begin | |
serial_state[1:0] <= 2'b00; | |
end | |
else if (sync_sck) begin | |
serial_cnt <= serial_cnt + 1'b1; | |
serial_state[1:0] <= 2'b11; | |
end | |
end | |
2'b11:begin | |
if(sync_csn) begin | |
serial_state[1:0] <= 2'b00; | |
end | |
else if(sync_sck) begin | |
serial_sreg <= {serial_sreg[6:0],serial_sdi_ff}; | |
if(serial_cnt[3] == 1'b1) begin | |
serial_done <= 1'b1; | |
serial_state[1:0] <= 2'b00; | |
end | |
else begin | |
serial_state[1:0] <= 2'b10; | |
end | |
end | |
end | |
default begin | |
serial_state[1:0] <= 2'b00; | |
end | |
endcase | |
end | |
end | |
reg [7:0] led_reg; | |
assign led = ~led_reg[5:0]; | |
always @(posedge clk_i or negedge rstn_i) begin | |
if(!rstn_i) begin | |
led_reg[7:0] = 8'b0; | |
end | |
else if(serial_done) | |
begin | |
led_reg[7:0] = serial_sreg[7:0]; | |
end | |
end | |
endmodule | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment