//+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