234 lines
8.9 KiB
Verilog
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
|
|
|
|
|
|
|
|
|
|
|