Skip to content

Instantly share code, notes, and snippets.

@nickfox-taterli
Created March 23, 2024 13:39
Show Gist options
  • Save nickfox-taterli/fe3713455b0ba55c73b63d45512f2bd9 to your computer and use it in GitHub Desktop.
Save nickfox-taterli/fe3713455b0ba55c73b63d45512f2bd9 to your computer and use it in GitHub Desktop.
spi slave at tang nano 20k
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