SPI_Test/tb/testbench/rtl/spi_to_sram.v

519 lines
14 KiB
Coq
Raw Normal View History

2024-06-25 16:41:01 +08:00
//+FHDR--------------------------------------------------------------------------------------------------------
// Company:
//-----------------------------------------------------------------------------------------------------------------
// File Name : spi_to_sram_v1.2.v
// Department :
// Author : ZYZ
// Author's Tel :
//-----------------------------------------------------------------------------------------------------------------
// Relese History
// Version Date Author Description
// 1.2 2024-04-02 ZYZ
//-----------------------------------------------------------------------------------------------------------------
// Keywords : 1.replace stream mode of send 32bit data 16 times
// 2.wrdata_reg address is no longer related to csn_active
//-----------------------------------------------------------------------------------------------------------------
// Parameter
//
//-----------------------------------------------------------------------------------------------------------------
// Purpose :
//
//-----------------------------------------------------------------------------------------------------------------
// Target Device:
// Tool versions:
//-----------------------------------------------------------------------------------------------------------------
// Reuse Issues
// Reset Strategy:
// Clock Domains:
// Critical Timing:
// Asynchronous I/F:
// Synthesizable (y/n):
// Other:
//-FHDR--------------------------------------------------------------------------------------------------------
module spi_to_sram (
//system port
input clk // System Main Clock
,input spi_rstn // Spi Reset active low
//spi port
,input sclk // Spi Clock
,input csn // Spi Chip Select active low
,input mosi // Spi Mosi
,output miso // Spi Miso
,output miso_oen // Spi Miso output enable
,output error_check // spi form check
,output [31:0] wrdata //write data to sram
,output [24:0] addr //sram address
,output wren //write enable sram
,output rden //rden enable sram
,input [31:0] rddata //read data from sram
);
localparam L = 1'b0,
H = 1'b1;
//3-bits shift register for sclk's rising & falling edges
reg [2 :0] sclk_reg;
wire sclk_p;
wire sclk_n;
//3-bits shift register for csn
reg [4 :0] csn_reg;
wire csn_active;
//2-bits shift register for mosi
reg [1 :0] mosi_reg;
wire mosi_data;
//cmd_reg--> 0:write,1:read
reg cmd_reg;
//rxs_reg
reg rxs_reg;
//addr_reg--> initial address
reg [24 :0] addr_reg;
//rxd_reg --> recive data
reg [31 :0] rxd_reg;
//rx;
reg [9 :0] rxcnt;
wire add_rxcnt;
wire end_rxcnt;
wire wr_times;
reg recv_start;
reg wren_reg;
reg wren_reg_1;
reg [31 :0] wrdata_reg;
//send data
reg [31 :0] txd_reg;
//tx;
reg [9 :0] txcnt;
wire add_txcnt;
wire end_txcnt;
reg trans_start;
//read write address
reg [24:0] rwaddr_reg;
reg address_start;
wire add_addr_wr;
wire add_addr_rd;
//read rddata to txd_reg
reg rd_times;
//read sram
wire rd_sram; //foreread
//output enable
reg miso_reg;
reg miso_oen_reg;
//data form check
reg error_check_reg ;
reg [9:0] frame_len;
//////////////////////////////////////////////////////////////////////////
//capture the sck
//////////////////////////////////////////////////////////////////////////
//sync sclk to the main clock using a 3-bits shift register
always @(posedge clk or negedge spi_rstn) begin
if(spi_rstn == L) begin
sclk_reg <= 3'b000;
end
else begin
sclk_reg <= {sclk_reg[1:0],sclk};
end
end
//sclk's rising edges
assign sclk_p = (sclk_reg[2:1] == 2'b01);
//sclk's falling edges
assign sclk_n = (sclk_reg[2:1] == 2'b10);
//////////////////////////////////////////////////////////////////////////
//capture the csn
//////////////////////////////////////////////////////////////////////////
//sync csn to the main clock using a 3-bits shift register
always @(posedge clk or negedge spi_rstn) begin
if(spi_rstn == L) begin
csn_reg <= 5'b11111;
end
else begin
csn_reg <= {csn_reg[3:0],csn};
end
end
// csn is active low
assign csn_active = ~csn_reg[1];
//////////////////////////////////////////////////////////////////////////
//capture the mosi
//////////////////////////////////////////////////////////////////////////
//sync mosi to the main clock using a 2-bits shift register
always @(posedge clk or negedge spi_rstn) begin
if(spi_rstn == L) begin
mosi_reg <= 2'b00;
end
else begin
mosi_reg <= {mosi_reg[0],mosi};
end
end
//mosi_data
assign mosi_data = mosi_reg[1];
//////////////////////////////////////////////////////////////////////////
//rxcnt
//////////////////////////////////////////////////////////////////////////
always @(posedge clk or negedge spi_rstn) begin
if(spi_rstn == L) begin
rxcnt <= 10'd0;
end
else if(end_rxcnt) begin
rxcnt <= 10'd0;
end
else if (add_rxcnt)begin
rxcnt <= rxcnt + 1'b1;
end
else begin
rxcnt <= rxcnt;
end
end
//add_rxcnt
assign add_rxcnt = sclk_p && csn_active;
assign end_rxcnt = add_rxcnt & (rxcnt == frame_len - 1'b1);
assign wr_times = add_rxcnt & (rxcnt[4:0] == 5'd31) & ~cmd_reg;
//////////////////////////////////////////////////////////////////////////
//cmd_reg
//////////////////////////////////////////////////////////////////////////
always @(posedge clk or negedge spi_rstn) begin
if(spi_rstn == L) begin
cmd_reg <= 1'b0;
end
else if(add_rxcnt && rxcnt == 10'd0 ) begin
cmd_reg <= mosi_data;
end
else begin
cmd_reg <= cmd_reg;
end
end
//////////////////////////////////////////////////////////////////////////
//rxs_reg
//////////////////////////////////////////////////////////////////////////
always @(posedge clk or negedge spi_rstn) begin
if(spi_rstn == L ) begin
rxs_reg <= 1'b0;
end
else if(add_rxcnt && rxcnt == 10'd1) begin
rxs_reg <= mosi_data;
end
else begin
rxs_reg <= rxs_reg;
end
end
//////////////////////////////////////////////////////////////////////////
//addr_reg
//////////////////////////////////////////////////////////////////////////
always @(posedge clk or negedge spi_rstn) begin
if(spi_rstn == L ) begin
addr_reg <= 25'd0;
end
else if(add_rxcnt && rxcnt <= 10'd26 ) begin
addr_reg <= {addr_reg[23:0],mosi_data};
end
else begin
addr_reg <= addr_reg;
end
end
//////////////////////////////////////////////////////////////////////////
//rxd_reg
//////////////////////////////////////////////////////////////////////////
always @(posedge clk or negedge spi_rstn) begin
if(spi_rstn == L) begin
rxd_reg <= 32'd0;
end
else if(add_rxcnt) begin
rxd_reg <= {rxd_reg[30:0],mosi_data};
end
else begin
rxd_reg <= rxd_reg;
end
end
//////////////////////////////////////////////////////////////////////////
//frame_len
//////////////////////////////////////////////////////////////////////////
always @(posedge clk or negedge spi_rstn) begin
if(spi_rstn == L) begin
frame_len <= 10'd0;
end
else if(add_rxcnt && rxcnt == 10'd2) begin
if(rxs_reg) begin
frame_len <= 10'd544;
end
else begin
frame_len <= 10'd64;
end
end
else begin
frame_len <= frame_len;
end
end
//////////////////////////////////////////////////////////////////////////
//recv_start
//////////////////////////////////////////////////////////////////////////
always @(posedge clk or negedge spi_rstn) begin
if(spi_rstn == L) begin
recv_start <= 1'b0;
end
else if(~csn_active )begin
recv_start <= 1'b0;
end
else if(wr_times)begin
recv_start <= 1'b1;
end
else begin
recv_start <= recv_start;
end
end
//////////////////////////////////////////////////////////////////////////
//wren_reg
//////////////////////////////////////////////////////////////////////////
always @(posedge clk or negedge spi_rstn) begin
if(spi_rstn == L) begin
wren_reg <= 1'b0;
end
else begin
wren_reg <= recv_start & wr_times ;
wren_reg_1 <= wren_reg;
end
end
//////////////////////////////////////////////////////////////////////////
//wrdata_reg
//////////////////////////////////////////////////////////////////////////
always @(posedge clk or negedge spi_rstn) begin
if(spi_rstn == L) begin
wrdata_reg <= 32'b0;
end
else if(wren_reg)begin
wrdata_reg <= rxd_reg;
end
end
//////////////////////////////////////////////////////////////////////////
//txcnt
//////////////////////////////////////////////////////////////////////////
always @(posedge clk or negedge spi_rstn) begin
if(spi_rstn == L) begin
txcnt <= 10'd0;
end
else if(end_txcnt) begin
txcnt <= 10'd0;
end
else if (add_txcnt)begin
txcnt <= txcnt + 1'b1;
end
else begin
txcnt <= txcnt;
end
end
//add_txcnt
assign add_txcnt = sclk_n && csn_active;
//end_txcnt
assign end_txcnt = add_txcnt && (txcnt == frame_len - 1'b1) ;
//////////////////////////////////////////////////////////////////////////
//rd_times
//////////////////////////////////////////////////////////////////////////
always@(*)begin
if(rxs_reg)begin
rd_times = add_txcnt & (txcnt[4:0] == 5'd31)& (txcnt != 10'd543) & cmd_reg;
end
else begin
rd_times = add_txcnt & (txcnt[4:0] == 5'd31)& (txcnt != 10'd63) & cmd_reg;
end
end
//rd_sram foreread
//assign rd_sram = (rd_times) | (add_txcnt & (txcnt[9:0] == 5'd30) & cmd_reg) ;
assign rd_sram = rd_times & cmd_reg;
//////////////////////////////////////////////////////////////////////////
//trans_start
//////////////////////////////////////////////////////////////////////////
always @(posedge clk or negedge spi_rstn) begin
if(spi_rstn == L) begin
trans_start <= 1'b0;
end
else if(rd_times)begin
trans_start <= 1'b1;
end
else if(~csn_active)begin
trans_start <= 1'b0;
end
else begin
trans_start <= trans_start;
end
end
//////////////////////////////////////////////////////////////////////////
//txd_reg
//////////////////////////////////////////////////////////////////////////
reg [2:0] rd_times_r;
always @(posedge clk or negedge spi_rstn) begin
if(spi_rstn == L) begin
rd_times_r <= 3'b0;
end
else begin
rd_times_r <= {rd_times_r[1:0],rd_times};
end
end
always @(posedge clk or negedge spi_rstn) begin
if(spi_rstn == L) begin
txd_reg <= 32'h0;
end
else if(rd_times_r[2]) begin
txd_reg <= rddata;
end
else if(add_txcnt && trans_start && txcnt[4:0]!=5'd31) begin
txd_reg <= {txd_reg[30:0],1'b0};
end
else begin
txd_reg <= txd_reg;
end
end
//////////////////////////////////////////////////////////////////////////
//address_start
//////////////////////////////////////////////////////////////////////////
always @(posedge clk or negedge spi_rstn) begin
if(spi_rstn == L) begin
address_start <= 1'b0;
end
else if(txcnt == 10'd29)begin
address_start <= 1'b1;
end
else if(~csn_active)begin
address_start <= 1'b0;
end
else begin
address_start <= address_start;
end
end
//////////////////////////////////////////////////////////////////////////
//rwaddr_reg
//////////////////////////////////////////////////////////////////////////
always @(posedge clk or negedge spi_rstn) begin
if(spi_rstn == L) begin
rwaddr_reg <= 25'b0;
end
else if(address_start)begin
if(add_addr_wr)begin
rwaddr_reg <= rwaddr_reg + 3'd4;
end
else if(add_addr_rd)begin
rwaddr_reg <= rwaddr_reg + 3'd4;
end
else begin
rwaddr_reg <= rwaddr_reg;
end
end
else begin
rwaddr_reg <= addr_reg;
end
end
assign add_addr_wr = rxs_reg & wren_reg_1 ;
assign add_addr_rd = rxs_reg & rd_sram ;
//////////////////////////////////////////////////////////////////////////
//miso_reg
//////////////////////////////////////////////////////////////////////////
always @(posedge clk or negedge spi_rstn) begin
if(spi_rstn == L) begin
miso_reg <= 1'b0;
end
else begin
miso_reg <= txd_reg[31];
end
end
//////////////////////////////////////////////////////////////////////////
//miso_oen_reg
//////////////////////////////////////////////////////////////////////////
always @(posedge clk or negedge spi_rstn) begin
if(spi_rstn == L) begin
miso_oen_reg <= 1'b1;
end
else begin
miso_oen_reg <= ~(trans_start & cmd_reg);
end
end
//////////////////////////////////////////////////////////////////////////
//error_check
//////////////////////////////////////////////////////////////////////////
always @(posedge clk or negedge spi_rstn) begin
if(spi_rstn == L) begin
error_check_reg <= 1'b0;
end
else if( (rxcnt != 0 || txcnt != 0)&&(~csn_active) )begin
error_check_reg <= 1'b1;
end
end
//////////////////////////////////////////////////////////////////////////
//Outputs signals
//////////////////////////////////////////////////////////////////////////
//wren
assign wren = wren_reg_1 ;
//wrdata
assign wrdata = wrdata_reg;
//rden
assign rden = rd_sram ;
//addr
assign addr = rwaddr_reg;
//miso
assign miso = miso_reg;
//miso_oen
assign miso_oen = miso_oen_reg;
//error_check
assign error_check = error_check_reg;
endmodule