📄 spi_regs.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 + -