SPI_Test/rtl/spi/spi_pll.v

234 lines
8.9 KiB
Verilog

//+FHDR--------------------------------------------------------------------------------------------------------
// Company:
//-----------------------------------------------------------------------------------------------------------------
// File Name : spi_pll.v
// Department :
// Author : PWY
// Author's Tel :
//-----------------------------------------------------------------------------------------------------------------
// Relese History
// Version Date Author Description
// 0.1 2024-04-10 PWY Dedicated SPI interface for phase-locked loops (PLLs)
// 0.2 2024-04-11 PWY Alter frame format
//-----------------------------------------------------------------------------------------------------------------
// 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-------------------------------------------------------------------------------------
`timescale 1ns/1ps
module spi_pll (
//reset active low
input rst_n
//cfg ID
,input [4 :0] cfgid //ID number for the entire chip
//SPI interface
,input csn
,input sclk
,input mosi
,output miso
,output oen
//SPI Select signal
,output sel
//regfile interface
,output [31 :0] wrdata
,output wren
,output [7 :0] rwaddr
,output rden
,input [31 :0] rddata
);
wire sel_w ;
wire wnr ;
wire [4 :0] addr_m5b ;
wire [7 :0] addr_l8b ;
wire [4 :0] chipid ;
wire data_valid ;
//wire [31:0] rddata ;//////////////////////////////////////
//reg rden_reg ;//////////////////////////////////////
//spi_rstn
wire spi_rstn = rst_n & (~csn);
//////////////////////////////////////////////////////////////////////////
//bit count
//////////////////////////////////////////////////////////////////////////
wire [4:0] bit_cnt;
//add_cnt
wire add_cnt = ~csn;
//end_cnt
wire end_cnt = add_cnt & (bit_cnt == 5'd31);
wire [4:0] cnt_n = end_cnt ? 5'd0 :
add_cnt ? bit_cnt + 5'b1 :
bit_cnt ;
sirv_gnrl_dffr #(5) bit_cnt_dffr (cnt_n, bit_cnt, sclk, spi_rstn);
///////////////////////////////////////////////////////////////////////////////
//Determine whether the current input is an SPI command or data
//Detect the falling edge on the most significant bit of the counter.
//If a falling edge occurs, it indicates that the SPI frame has
//entered the data transmission phase.
///////////////////////////////////////////////////////////////////////////////
wire bit_cnt_r;
wire bit_cnt_falling = bit_cnt_r & ~bit_cnt[4];
sirv_gnrl_dffr #(1) bit_cnt_r_dffr (bit_cnt[4], bit_cnt_r, sclk, spi_rstn);
//cmd_or_data:"High" represents data, "low" represents commands
wire cmd_or_data;
sirv_gnrl_dfflr #(1) cmd_or_data_dfflr (bit_cnt_falling, 1'b1, cmd_or_data, sclk, spi_rstn);
wire second_falling;
sirv_gnrl_dfflr #(1) second_falling_dfflr (bit_cnt_falling & cmd_or_data, 1'b1, second_falling, sclk, spi_rstn);
///////////////////////////////////////////////////////////////////////
//SPI data sample (Load mosi data)
///////////////////////////////////////////////////////////////////////
generate
genvar i;
wire [31:0] recv_vld ;
wire [31:0] mosi_reg ;
for(i=0;i<32;i=i+1) begin: spi_pll_recv
assign recv_vld[i] = add_cnt & (bit_cnt == i );
sirv_gnrl_dfflr #(1) spi_din_dfflr (recv_vld[i], mosi, mosi_reg[31-i], sclk, spi_rstn);
end
endgenerate
//addr valid
wire addr_vaild = ~cmd_or_data & add_cnt & (bit_cnt == 5'd26);
//CMD Update
sirv_gnrl_dfflr #(1) wnr_dfflr (addr_vaild, mosi_reg[31], wnr, sclk, spi_rstn);
//addr_m5b Update
sirv_gnrl_dfflr #(5) addr_m5b_dfflr (addr_vaild, mosi_reg[30:26], addr_m5b, sclk, spi_rstn);
//addr_l8b Update
sirv_gnrl_dfflr #(8) addr_l8b_dfflr (addr_vaild, mosi_reg[13:6], addr_l8b, sclk, spi_rstn);
//chipid Valid
wire chipid_vld = ~cmd_or_data & add_cnt & (bit_cnt == 5'd31);
//chipid Update
sirv_gnrl_dfflr #(5) chipid_dfflr (chipid_vld, mosi_reg[5:1], chipid, sclk, spi_rstn);
//sel_w
assign sel_w = (addr_m5b == 5'b11111) & (chipid == cfgid);
//recv data valid
assign data_valid = cmd_or_data & (bit_cnt == 5'd31);
//assign data_valid = cmd_or_data & (bit_cnt == 5'd31);///////20240514
//wren
assign wren = data_valid & sel_w & ~wnr;
//rden
//assign rden = add_cnt & (bit_cnt == 5'd30);/////////////////////////
//assign rden = add_cnt & (bit_cnt == 5'd30) & sel_w;/////////////////////////20240514
assign rden = add_cnt & (bit_cnt == 5'd30) & wnr;/////////////////////////20240604
wire rddata_update;
sirv_gnrl_dffr #(1) rddata_update_dffr (rden, rddata_update, sclk, spi_rstn);
//wrdata
assign wrdata = {mosi_reg[31:1],mosi};
///////////////////////////////////////////////////////////////////////////////////////////////////////
//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 addr_update = ((wnr & cmd_or_data) | second_falling) & add_cnt & (bit_cnt == 5'd29);
//wire addr_update = cmd_or_data & add_cnt & (bit_cnt == 5'd27);
wire [7:0] addr_c;
wire [7:0] addr_n = ~cmd_or_data ? addr_l8b :
addr_update ? addr_c + 8'd4 :
addr_c ;
sirv_gnrl_dffr #(8) addr_c_dffr (addr_n, addr_c, sclk, spi_rstn);
assign rwaddr = addr_c;
//sel
assign sel = sel_w;
//oen
//assign oen = ~(sel_w & wnr & ~csn);
wire oen_w = ~(sel_w & wnr & ~csn);
sirv_gnrl_dffrs #(1) oen_dffrs (oen_w, oen, sclk, spi_rstn);
//data output
wire[31:0] miso_reg;
wire[31:0] miso_wire;
sirv_gnrl_dfflr #(32) miso_reg_dfflr (rddata_update, rddata, miso_reg, sclk, spi_rstn);
assign miso_wire = miso_reg;
///////////////////////////////////////////////////////////////////////////////////////////////////////
//SPI send data
///////////////////////////////////////////////////////////////////////////////////////////////////////
generate
genvar j;
wire [31:0] send_vld ;
wire [31:0] dtemp ;
for(j=0;j<32;j=j+1) begin: spi_pll_send
//assign send_vld[j] = (bit_cnt == ((j==31) ? 0 : (j+1)) );
assign send_vld[j] = (bit_cnt == j );
if(j==0) begin: dtemp0
assign dtemp[j] = (send_vld[j]) ? miso_wire[31-j] : 1'b0;
end
else begin: dtemp1_32
assign dtemp[j] = (send_vld[j]) ? miso_wire[31-j] : dtemp[j-1];
end
end
endgenerate
assign miso = dtemp[31];
endmodule