SPI_Test/rtl/spi/spi_sys_20240624.v

293 lines
12 KiB
Coq
Raw Normal View History

2024-06-25 16:41:01 +08:00
//+FHDR--------------------------------------------------------------------------------------------------------
// Company:
//-----------------------------------------------------------------------------------------------------------------
// File Name : spi_sys.v
// Department :
// Author : PWY
// Author's Tel :
//-----------------------------------------------------------------------------------------------------------------
// Relese History
// Version Date Author Description
// 0.1 2024-04-13 PWY SPI BUS for System
// 0.2 2024-06-24 PWY {spi_dout[31:0],1'b0} -> {spi_dout[30:0],1'b0}
//-----------------------------------------------------------------------------------------------------------------
// Keywords :
//
//-----------------------------------------------------------------------------------------------------------------
// Parameter
//
//-----------------------------------------------------------------------------------------------------------------
// Purpose :
//
//-----------------------------------------------------------------------------------------------------------------
// Target Device:
// Tool versions:
//-----------------------------------------------------------------------------------------------------------------
// Reuse Issues
// Reset Strategy:
// Clock Domains:
// Critical Timing:
// Asynchronous I/F:
// Synthesizable (y/n):
// Other:
//-FHDR--------------------------------------------------------------------------------------------------------
//-----------------------------Spi Frame-------------------------------------------------------------------------------------
////MSB------------->>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>..............................................>>>>>>>>------->LSB
///|<-----------MSB 32 bits------------------->||<---------Second 32-bit---->||<-------x 32-bit---->||<-------n 32-bit---->|
// +-----++----------------------++------------++-----++---------------------++---------------------++---------------------+
// | 31 || 30:6 || 5:1 || 0 || 31:0 || ...... || 31:0 |
// +-----++----------------------++------------++-----++---------------------++---------------------++---------------------+
// +-----++----------------------++------------++-----++---------------------++---------------------++---------------------+
// | wnr || addr[24:0] || CHIPID ||resv || data[31:0] || ...... || data[31:0] |
// +-----++----------------------++------------++-----++---------------------++---------------------++---------------------+
//-----------------------------Spi Frame-------------------------------------------------------------------------------------
module spi_sys (
//system port
input clk // System Main Clock
,input rst_n // Spi Reset active low
//cfg ID
,input [4 :0] cfgid //ID number for the entire chip
//spi port
,input sclk // Spi Clock
,input csn // Spi Chip Select active low
,input mosi // Spi Mosi
,output miso // Spi Miso
,output oen // Spi Miso output enable
,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 IDLE = 2'b00,
RECVCMD = 2'b01,
WRITE = 2'b10,
READ = 2'b11;
//-----------------------------------------------------------------------
//SPI module reset processing
//-----------------------------------------------------------------------
//spi_rstn
//wire spi_rstn;
//assign spi_rstn = rst_n & (~csn);
//////////////////////////////////////////////////////////////////////////
//capture the sck
//////////////////////////////////////////////////////////////////////////
wire [2:0] sclk_reg;
//sync sclk to the main clock using a 3-bits shift register
sirv_gnrl_dffrs #(3) sclk_reg_dffrs ({sclk_reg[1:0],sclk}, sclk_reg, clk, rst_n);
//sclk's rising edges
wire sclk_p = (sclk_reg[2:1] == 2'b01);
//sclk's falling edges
//assign sclk_n = (sclk_reg[2:1] == 2'b10);
//////////////////////////////////////////////////////////////////////////
//capture the csn
//////////////////////////////////////////////////////////////////////////
wire [2:0] csn_reg;
//sync csn to the main clock using a 2-bits shift register
sirv_gnrl_dffrs #(3) csn_reg_dffrs ({csn_reg[1:0],csn}, csn_reg, clk, rst_n);
// csn is active low
wire csn_active = ~csn_reg[1];
//csn's rising edges
wire csn_p = (csn_reg[2:1] == 2'b01);
//csn's falling edges
wire csn_n = (csn_reg[2:1] == 2'b10);
//////////////////////////////////////////////////////////////////////////
//capture the mosi
//////////////////////////////////////////////////////////////////////////
wire [1:0] mosi_reg;
//sync mosi to the main clock using a 2-bits shift register
sirv_gnrl_dffr #(2) mosi_reg_dffr ({mosi_reg[0],mosi}, mosi_reg, clk, rst_n);
//mosi_data
wire mosi_data = mosi_reg[1];
//////////////////////////////////////////////////////////////////////////
//cnt
//////////////////////////////////////////////////////////////////////////
wire [4:0] cnt_c;
//add_cnt
assign add_cnt = sclk_p && csn_active;
//end_cnt
assign end_cnt = (add_cnt && (cnt_c == 5'd31)) | csn_p;
wire [4:0] cnt_n = end_cnt ? 5'h0 :
add_cnt ? cnt_c + 5'b1 :
cnt_c ;
sirv_gnrl_dffr #(5) cnt_c_dffr (cnt_n, cnt_c, clk, rst_n);
///////////////////////////////////////////////////////////////////////
//SPI data sample
///////////////////////////////////////////////////////////////////////
generate
genvar i;
wire [31:0] recv_vld ;
wire [31:0] spi_din ;
for(i=0;i<32;i=i+1) begin: spi_sys_recv
assign recv_vld[i] = add_cnt & (cnt_c == i );
sirv_gnrl_dfflr #(1) spi_din_dfflr (recv_vld[i], mosi_data, spi_din[31-i], clk, rst_n);
end
endgenerate
wire [1:0] state_c;
wire [1:0] state_n;
///////////////////////////////////////////////////////////////////////
//init_addr capture
///////////////////////////////////////////////////////////////////////
wire [24:0] initaddr;
wire initaddr_vld = (state_c == RECVCMD ) & add_cnt && (cnt_c == 5'd26);
wire [1:0] initaddr_vld_r;
sirv_gnrl_dffr #(2) initaddr_vld_r_dffr ({initaddr_vld_r[0],initaddr_vld}, initaddr_vld_r, clk, rst_n);
sirv_gnrl_dfflr #(25) initaddr_dfflr (initaddr_vld_r[0], spi_din[30:6], initaddr, clk, rst_n);
///////////////////////////////////////////////////////////////////////
//CMD capture
///////////////////////////////////////////////////////////////////////
wire cmd ;
sirv_gnrl_dfflr #(1) cmd_dfflr ( initaddr_vld_r[0], spi_din[31], cmd, clk, rst_n);
///////////////////////////////////////////////////////////////////////
//CHIPID capture
///////////////////////////////////////////////////////////////////////
wire [4:0] chipid;
wire [1:0] chipid_vld_r;
wire chipid_vld = (state_c == RECVCMD ) & add_cnt & (cnt_c == 5'd30);
//register cmd_vld to align it with cmd
sirv_gnrl_dffr #(2) chipid_vld_r_dffr ({chipid_vld_r[0],chipid_vld}, chipid_vld_r, clk, rst_n);
sirv_gnrl_dfflr #(5) chipid_dfflr (chipid_vld_r[0], spi_din[5:1], chipid, clk, rst_n);
///////////////////////////////////////////////////////////////////////
//ID matching determination
///////////////////////////////////////////////////////////////////////
wire chipid_match = (chipid == cfgid);
wire chipid_dismatch = (chipid != cfgid);
///////////////////////////////////////////////////////////////////////
//SPI Module State Machine
///////////////////////////////////////////////////////////////////////
//Generating jump conditions for state machines
wire ilde2recvcmd = (state_c == IDLE ) && csn_active && csn_n ;
wire recvcmd2ilde = (state_c == RECVCMD ) && chipid_dismatch & end_cnt;
wire recvcmd2write = (state_c == RECVCMD ) && chipid_match && ~cmd & end_cnt;
wire recvcmd2read = (state_c == RECVCMD ) && chipid_match && cmd & end_cnt;
wire write2idle = (state_c == WRITE ) && csn_p;
wire read2idle = (state_c == READ ) && csn_p;
//The first section of the state machine
//state_c
sirv_gnrl_dffr #(2) state_c_dffr (state_n, state_c, clk, rst_n);
//state_n
assign state_n = ((state_c == IDLE ) && ilde2recvcmd ) ? RECVCMD :
((state_c == RECVCMD ) && recvcmd2ilde ) ? IDLE :
((state_c == RECVCMD ) && recvcmd2write ) ? WRITE :
((state_c == RECVCMD ) && recvcmd2read ) ? READ :
((state_c == WRITE ) && write2idle ) ? IDLE :
((state_c == READ ) && read2idle ) ? IDLE :
state_c ;
///////////////////////////////////////////////////////////////////////////////////////////////////////
//Address generation for read and write operations
//The address to be used for updating in the next
//27 clock cycles in the read-write state
///////////////////////////////////////////////////////////////////////////////////////////////////////
wire second_falling;
wire second_falling_w = (state_c == WRITE);
sirv_gnrl_dfflr #(1) second_falling_dfflr (end_cnt ,second_falling_w, second_falling, clk, rst_n);
wire addr_update = ((state_c == READ) | ((state_c == WRITE) & second_falling)) & add_cnt & (cnt_c == 5'd27);
wire [24:0] addr_c;
wire [24:0] addr_n = ilde2recvcmd ? 25'd0 :
initaddr_vld_r[1] ? initaddr :
addr_update ? addr_c + 25'd4 :
addr_c ;
sirv_gnrl_dffr #(25) addr_c_dffr (addr_n, addr_c, clk, rst_n);
assign addr = addr_c;
///////////////////////////////////////////////////////////////////////////////////////////////////////
//Write data and write signals generation
///////////////////////////////////////////////////////////////////////////////////////////////////////
wire wren_r;
wire wren_w = (state_c == WRITE) & add_cnt & (cnt_c == 5'd31);
//wdata
sirv_gnrl_dfflr #(32) wrdata_dfflr (wren_r, spi_din[31:0], wrdata, clk, rst_n);
//wren_r
sirv_gnrl_dffr #(1) wren_r_dffr (wren_w, wren_r, clk, rst_n);
//wren
sirv_gnrl_dffr #(1) wren_dffr (wren_r, wren, clk, rst_n);
///////////////////////////////////////////////////////////////////////////////////////////////////////
//read signals generation
///////////////////////////////////////////////////////////////////////////////////////////////////////
wire rden_w = cmd & add_cnt & (cnt_c == 5'd28);
sirv_gnrl_dffr #(1) rden_dffr (rden_w, rden, clk, rst_n);
//Read data register
wire rddata_vld = cmd & add_cnt & (cnt_c == 5'd30);
wire [31:0] rddata_reg;
sirv_gnrl_dfflr #(32) rddata_reg_dfflr (rddata_vld, rddata[31:0], rddata_reg, clk, rst_n);
///////////////////////////////////////////////////////////////////////////////////////////////////////
//SPI send data update
///////////////////////////////////////////////////////////////////////////////////////////////////////
wire [31:0] spi_dout ;
wire update_flag = cmd & add_cnt & (cnt_c == 5'd31);
wire [31:0] rddata_sr = update_flag ? rddata_reg[31:0] :
((state_c == READ) & add_cnt) ? {spi_dout[30:0],1'b0} : //M 2024-06-24
spi_dout ;
sirv_gnrl_dffr #(32) spi_dout_dffr (rddata_sr, spi_dout, clk, rst_n);
///////////////////////////////////////////////////////////////////////////////////////////////////////
//SPI send data
///////////////////////////////////////////////////////////////////////////////////////////////////////
assign miso = spi_dout[31];
///////////////////////////////////////////////////////////////////////////////////////////////////////
//SPI output enable
///////////////////////////////////////////////////////////////////////////////////////////////////////
sirv_gnrl_dffrs #(1) oen_dffr (~(state_c == READ), oen, clk, rst_n);
endmodule