⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 spi_regs.v

📁 verilog语言写的SPI接口,全同步设计,低门数,可以很容易应用到嵌入设计方案中.
💻 V
字号:
//-----------------------------------------------------------------------------
// Project: Standard Communication Platform
//-----------------------------------------------------------------------------
//
// $RCSfile: spi_regs.v,v $
//
// $Revision: 1.5 $
// $Name:  $
// $Date: 1999/11/02 09:47:38 $
// $Author: jwagensv $
//
//-Description ----------------------------------------------------------------
//
// VPB based registers template.
//
// This template implements registers in a way which is compliant with
// release 1.0 of the VPB specification (except that it supports only
// bi-directional busses).
//
//-----------------------------------------------------------------------------



//-----------------------------------------------------------------------------

module spi_regs 
  (//-- VPB --------------------------------------------------------------------
   psel_spi,
   pstb,
   pa,
   pdin,
   pdout,
   pwrite,
   pdoe,               // output enable for pdout bus (read performed)
   //-- clk/reset --------------------------------------------------------------
   pclk,
   pnres,
   //-- SPI specific I/Os-------------------------------------------------------
   fifo_do,            // fifo data out bus
   busy,               // transfer is ongoing
   opcode_length,      // specify the size of opcode field to be sent
   address_length,     // specify the size of address field to be sent
   spi_mode,           // specify which spi mode will be used for transfert 0 1 2 3
   wait_state_en,      // alows the activation of wait state between opcode-address and data 
   wait_state_numb,    // number of wait state to be insterted.
   device_cs_polarity, // active high/low chip select for the devices.
   addressed_device,   // which device is addressed acive high (broadcast possible)
   start_transfert,    // statr transfer. to be plugged on an edge detector
   transfert_type,     // read/write/opcode... type of tranfert
   address_field,      // address bits to be sent (from MSB to LSB)
   opcode_field,       // opcode to be sent to device from MSB
   page_size,          // number of bytes to be sent/received
   lcd_address,        // LCD specific serial address bit
   nwr_fifo,           // write data to fifo 
   nrd_fifo,           // read_data from fifo
   break,              // in case of fifo full/empty stop transmission completely
   clk_divider,        // p_ck/clk_divider=2*spi_clk
   it_mask,            // mask the interupts
   tx_trigger,         // trigger in tx mode
   rx_trigger,         // trigger in rx mode
   int_reg_read,       // indicate that interupt status register is beeing read
   dma_mask,           // mask the dma output
   spi_int,            // spi_interrupt input
   int_val,            // interrupt value 
   fifo_full,          // fifo is full  => fifo status register
   fifo_empty,         // fifo is empty => fifo status register
   fifo_level,         // how may byte in fifo
   page_number,        //how many pages have to be transmitted
   time_ext            //how many functional clock period must be added to Cs setup/hold/inactive
   );
 

//------- VPB interface pins---------------------
   input         psel_spi, pstb,pwrite;
   input [7:0] 	 pa;
   input [7:0] 	 pdin;
   
   output [7:0]  pdout;

   input 	 pclk;
   input 	 pnres;


//-------SPI specific pins-------------------------------------
   input [7:0] 	 fifo_do;
   input 	 busy;
   
   output [5:0] opcode_length;
   output [5:0] address_length;
   output [1:0] spi_mode;
   output       wait_state_en;
   output [1:0] wait_state_numb;
   output [3:0] device_cs_polarity;
   output [1:0] addressed_device;
   output 	start_transfert;
   output [2:0] transfert_type;
   output [31:0] address_field;
   output [31:0] opcode_field;
   output [7:0]  page_size;
   output [1:0]  lcd_address;
   output 	 nrd_fifo;
   output 	 nwr_fifo;
   output 	 break;
   output [3:0]  clk_divider;
   output [1:0]  it_mask;
   output [3:0]	 tx_trigger;
   output [3:0]	 rx_trigger;
   output 	 int_reg_read;
   output [1:0]  dma_mask;
	 
   input 	 spi_int;
   input [1:0] 	 int_val;
   input 	 fifo_full;
   input 	 fifo_empty;
   input [2:0] 	 fifo_level;
   output 	 pdoe;
   output [7:0]  page_number;
   output [2:0]  time_ext;
   
   

//-----------------------------------------------------------------------------
// Parameters and constants   
//-----------------------------------------------------------------------------
// All flip-flops are modeled (in RTL) with a (cp->q) delay: tcQ.
// This is to prevent potential problems with gated clocks.

   parameter tcQ=1;
   
   `include "spi_map.v" //register offset definition
 

   wire       wait_state_en;
   wire [1:0] wait_state_numb;
   wire [3:0] device_cs_polarity;
   wire [1:0] addressed_device;
   wire       start_transfert;
   reg [2:0] transfert_type;
   reg  [1:0] lcd_address;
   wire       nrd_fifo;
   wire       nwr_fifo;
   wire [3:0] clk_divider;
   wire [3:0] tx_trigger;
   wire [3:0] rx_trigger;
   wire       int_reg_read;
   wire       pdoe;
   wire [2:0] time_ext;
   
   
//registers instanciation
   reg [5:0]  opcode_length;
   reg [5:0]  address_length;
   reg [6:0]  spi_cs_ctrl;
   reg [6:0]  spi_ck_ctrl;
   reg 	      break;
   reg [1:0]  spi_mode;
      
   reg [1:0]  active_dev;
   reg [31:0] address_field;
   reg [31:0] opcode_field;
   reg [7:0]  page_size;
   reg [7:0]  trigger;
   reg [1:0]  it_mask;
   reg [1:0]  dma_mask;
   reg [7:0]  page_number;
              
// register to wire assignments

  
   
   assign wait_state_en       = spi_ck_ctrl[6];
   assign wait_state_numb     = spi_ck_ctrl[5:4];
   assign clk_divider         = spi_ck_ctrl[3:0];
   
   assign device_cs_polarity  = spi_cs_ctrl[3:0];
   assign time_ext            = spi_cs_ctrl[6:4];
      
   assign addressed_device    = active_dev;
   
   assign tx_trigger          = trigger[7:4];
   assign rx_trigger          = trigger[3:0];
   
   
//-----------------------------------------------------------------------------
// signals suffixes :
//   xxx_r : clocked on rising edge
//   xxx_f : clocked on falling edge
//   xxx_c : combinational

   wire 	reg_clk;
   wire 	write_enable_c;
   wire 	read_enable_c;
   reg [7:0] 	pdout;

   reg 		pstb_r;

//-----------------------------------------------------------------------------

//-----------------------------------------------------------------------------
// Registers clock
//-----------------------------------------------------------------------------



   assign reg_clk = pclk;
   


//-----------------------------------------------------------------------------
// PSTB rising edge detection
//-----------------------------------------------------------------------------
// The release 1.0 of the VPB spec. says that VPB devices must tolerate
// multiple rising edges of PClk while PSTB is high.
// For "normal registers", there is no problem. However, for some peripherals,
// some registers (ex. FIFO) should be written only once each time PSTB is
// asserted. Therefore, some logic is added here to ensure that only ONE write
// is performed. If this is not a concern, this logic can be removed.

   always@( posedge pclk or negedge pnres)
     if(!pnres)
       pstb_r <= 0;
     else
       pstb_r <= #tcQ pstb;//&psel_spi;

//-----------------------------------------------------------------------------
// Write registers
//-----------------------------------------------------------------------------

   assign write_enable_c = psel_spi & (pstb & ~pstb_r) & pwrite;

   // bits with asynchronous set/reset

   always@( posedge reg_clk or negedge pnres )
     if ( ~pnres )
       begin
	 address_length    <= 5'h0;
	 opcode_length     <= 5'h0;
	 {break,spi_mode}  <= 3'b0;
	 spi_ck_ctrl       <= 7'h00;
	 spi_cs_ctrl       <= 7'h00;
	 active_dev        <= 4'h0;
	 lcd_address       <= 2'h0;
	  transfert_type   <= 3'h0;
	 page_size         <= 8'h00;
	 trigger           <= 8'h00;
	 it_mask           <= 2'h3;
	 dma_mask          <= 2'h3;
	 page_number       <= 8'h01;
	 
	 
       end
     else
       if( write_enable_c )
	 case(pa[7:0])
	  `OPCODE_SIZE : opcode_length          <= #tcQ pdin[5:0];
	  `ADDR_SIZE   : address_length         <= #tcQ pdin[5:0];
	  `DEVICE_CTRL : begin {break,spi_mode} <= #tcQ pdin[2:0]; active_dev     <= #tcQ pdin[5:4];end
	  `SPI_CK_CTRL : spi_ck_ctrl            <= #tcQ pdin[6:0];
	  `SPI_CS_CTRL : spi_cs_ctrl            <= #tcQ pdin[6:0];
	  `MISC_CTRL   : begin lcd_address      <= #tcQ pdin[5:4]; transfert_type <= #tcQ pdin[2:0];end
	  `PAGE_SIZE   : page_size              <= #tcQ pdin;
	  `TRIGGER     : trigger                <= #tcQ pdin;
	  `IT_MASK     : begin dma_mask         <= #tcQ pdin[5:4]; it_mask        <= #tcQ pdin[1:0];end
	  `NB_TRANSMIT : page_number            <= #tcQ pdin;
	 endcase // case( {pa[8:2], 2'b0} )...
   
   // bits without  asynchronous set/reset
   always@( posedge reg_clk)
     if( write_enable_c )
       case(pa[7:0])
	`OPCODE_LSB  : opcode_field[7:0]    <= #tcQ pdin;
	`OPCODE_01   : opcode_field[15:8]   <= #tcQ pdin;
	`OPCODE_02   : opcode_field[23:16]  <= #tcQ pdin;
	`OPCODE_MSB  : opcode_field[31:24]  <= #tcQ pdin;
	`ADDRESS_LSB : address_field[7:0]   <= #tcQ pdin;
	`ADDRESS_01  : address_field[15:8]  <= #tcQ pdin;
	`ADDRESS_02  : address_field[23:16] <= #tcQ pdin;
	`ADDRESS_MSB : address_field[31:24] <= #tcQ pdin;
       endcase // case(pa[7:0])
   
   //Fifo write enable
   assign nwr_fifo = ~((pa[7:0]==`TxRx_FIFO) & write_enable_c);

   //init_transfer(s) signal
   assign start_transfert=(pa[7:0]==`START_BUSY) & write_enable_c & pdin[0];
   
  
   
//-----------------------------------------------------------------------------
// Read registers decoding/muxing
//-----------------------------------------------------------------------------

   always@(    pa
	       or psel_spi
	       or pwrite
	       or opcode_length
	       or address_length
	       or spi_mode
	       or break
	       or spi_ck_ctrl
	       or spi_cs_ctrl
	       or busy
	       or active_dev
	       or address_field
	       or opcode_field
	       or page_size
	       or fifo_do
	       or int_val
	       or spi_int
	       or fifo_full
	       or fifo_empty
	       or fifo_level
	       or trigger
	       or it_mask
	       or dma_mask
	       or page_number
	       or lcd_address
	       or transfert_type
	       )
     begin
 
	if( (~psel_spi)|pwrite)
	  pdout <= 8'h00;
	else
	  case (pa[7:0])
	   `OPCODE_LSB  : pdout <= opcode_field[7:0];
	   `OPCODE_01   : pdout <= opcode_field[15:8];
	   `OPCODE_02   : pdout <= opcode_field[23:16];
	   `OPCODE_MSB  : pdout <= opcode_field[31:24];
	   `ADDRESS_LSB : pdout <= address_field[7:0];
	   `ADDRESS_01  : pdout <= address_field[15:8];
	   `ADDRESS_02  : pdout <= address_field[23:16];
	   `ADDRESS_MSB : pdout <= address_field[31:24];
	   `TxRx_FIFO   : pdout <= fifo_do;
	   `START_BUSY  : pdout <= {busy,7'h00};
	   `OPCODE_SIZE : pdout <= {2'h0,opcode_length};
	   `ADDR_SIZE   : pdout <= {2'h0,address_length};
	   `DEVICE_CTRL : pdout <= {2'h0,active_dev,break,spi_mode};
	   `SPI_CK_CTRL : pdout <= {1'b0,spi_ck_ctrl};
	   `SPI_CS_CTRL : pdout <= {1'h0,spi_cs_ctrl};
	   `MISC_CTRL   : pdout <= {2'b0,lcd_address,1'b0,transfert_type};
	   `PAGE_SIZE   : pdout <= page_size;
	   `IT_STATUS   : pdout <= {spi_int,5'h0,int_val};
	   `IT_MASK     : pdout <= {2'b0,dma_mask,2'b0,it_mask};
	   `TRIGGER     : pdout <= trigger;
	   `FIFO_STATUS : pdout <= {2'h0,fifo_full,fifo_empty,1'b0,fifo_level};
	   `NB_TRANSMIT : pdout <= page_number;
	   default      : pdout <= 8'hxx;
	  endcase // case(pa[7:0])
       
     end // always@ (    pa...

   assign pdoe = psel_spi & pstb & (~pwrite);
   assign read_enable_c= (psel_spi & (~pstb & pstb_r) & (~pwrite));
   assign nrd_fifo = ~(read_enable_c&(pa==`TxRx_FIFO));
   assign int_reg_read = read_enable_c&(pa==`IT_STATUS);
   
   
   


   
//-----------------------------------------------------------------------------

endmodule
/*   spi_regs 
  (//-- VPB --------------------------------------------------------------------
   .psel_spi(),
   .pstb(),
   .pa(),
   .pdin(),
   .pdout(),
   .pwrite(),
   .pdoe(),               // output enable for pdout bus (read performed)
   //-- clk/reset --------------------------------------------------------------
   .pclk(),
   .pnres(),
   //-- SPI specific I/Os-------------------------------------------------------
   .fifo_do(),            // fifo data out bus
   .busy(),               // transfer is ongoing
   .opcode_length(),      // specify the size of opcode field to be sent
   .address_length(),     // specify the size of address field to be sent
   .spi_mode(),           // specify which spi mode will be used for transfert 0 1 2 3
   .wait_state_en(),      // alows the activation of wait state between opcode-address and data 
   .wait_state_numb(),    // number of wait state to be insterted.
   .device_cs_polarity(), // active high/low chip select for the devices.
   .addressed_device(),   // which device is addressed acive high (broadcast possible)
   .start_transfert(),    // statr transfer. to be plugged on an edge detector
   .transfert_type(),     // read/write/opcode... type of tranfert
   .address_field(),      // address bits to be sent (from MSB to LSB)
   .opcode_field(),       // opcode to be sent to device from MSB
   .page_size(),          // number of bytes to be sent/received
   .lcd_address(),        // LCD specific serial address bit
   .nwr_fifo(),           // write data to fifo 
   .nrd_fifo(),           // read_data from fifo
   .break(),              // in case of fifo full/empty stop transmission completely
   .clk_divider(),        // p_ck/clk_divider=2*spi_clk
   .it_mask(),            // mask the interupts
   .tx_trigger(),         // trigger in tx mode
   .rx_trigger(),         // trigger in rx mode
   .int_reg_read(),       // indicate that interupt status register is beeing read
   .dma_mask(),           // mask the dma output
   .spi_int(),            // spi_interrupt input
   .int_val(),            // interrupt value 
   .fifo_full(),          // fifo is full  => fifo status register 
   .fifo_empty(),         // fifo is empty => fifo status register
   .fifo_level()          // how may byte in fifo          
   );*/

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -