293 lines
12 KiB
Coq
293 lines
12 KiB
Coq
|
//+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
|
||
|
|
||
|
|