📄 spi.v
字号:
//----------------------------------------------------------------------------
// Project : SCP1 - Standard Communication Platform Version 1
//----------------------------------------------------------------------------
// Source : $Source: /db1/Razor_db/RAZOR_UNIVERSE/DOMAIN_01/SCP/Archive/RZ_VCS/scp1/design/arm_periph/spi/rtl/spi.v,v $
// Revision : $Revision: 1.6 $
// Date : $Date: 2000/02/16 09:53:26 $
// Author : $Author: velard_j $
//
//-Description----------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
module spi(
psel_spi,
pstb,
pa,
pdi,
pdo,
pwrite,
pclk,
pnres,
test_comb,
scan_in1,
scan_in2,
scan_in3,
scan_out1,
scan_out2,
scan_out3,
test_shift,
spi_si,
spi_so,
spi_clk,
spi_a,
spi_oen,
spi_cs,
powerdown,
spi_int,
pdoe,
dma_req,
dma_op_add_req
);
// I/O definitions
input psel_spi;
input pstb;
input [7:0] pa;
input [7:0] pdi;
output [7:0] pdo;
input pwrite;
input pclk;
input pnres;
input test_comb;
input scan_in1;
input scan_in2;
input scan_in3;
output scan_out1;
output scan_out2;
output scan_out3;
input test_shift;
input spi_si;
output spi_so;
output spi_clk;
output spi_a;
output spi_oen;
output [3:0] spi_cs;
input powerdown;
output spi_int;
output pdoe;
output dma_req;
output dma_op_add_req;
//wire and reg definition for interconnexion
wire [7:0] pdo;
wire spi_so;
wire spi_clk;
wire spi_a;
wire spi_oen;
wire [3:0] spi_cs;
wire spi_int;
wire busy;
wire [5:0] opcode_length;
wire [5:0] address_length;
wire [1:0] spi_mode;
wire wait_state_en;
wire [1:0] wait_numb;
wire start;
wire [2:0] transfert_type;
wire [31:0] opcode_field;
wire [31:0] addr_field;
wire function_clk;
wire nenable_reg_clk;
wire [7:0] fifo_do;
wire [7:0] fifo_di;
wire [7:0] page_size;
wire [3:0] cs_polarity;
wire [1:0] activate_cs;
wire [7:0] rxdata;
wire [3:0] fifo_level;
wire [3:0] tx_trigger;
wire [3:0] rx_trigger;
wire [3:0] clk_divider;
wire [1:0] it_mask;
wire [1:0] int_val;
wire [1:0] lcd_a;
wire [7:0] page_number;
wire [1:0] dma_mask;
wire [2:0] time_ext;
wire ntest_comb;
wire nena_fifo_clk;
wire nclkena;
// Instances palcement
spi_regs reg_if
(//-- VPB --------------------------------------------------------------------
.psel_spi(psel_spi),
.pstb(pstb),
.pa(pa),
.pdin(pdi),
.pdout(pdo),
.pwrite(pwrite),
//-- clk/reset --------------------------------------------------------------
.pclk(reg_clk),
.pnres(pnres),
//-- SPI specific I/Os-------------------------------------------------------
.fifo_do(fifo_do), // fifo data out bus
.busy(busy), // transfer is ongoing
.opcode_length(opcode_length), // specify the size of opcode field to be sent
.address_length(address_length), // specify the size of address field to be sent
.spi_mode(spi_mode), // specify which spi mode will be used for transfert 0 1 2 3
.wait_state_en(wait_state_en), // activation of wait state between opcode-address and data
.wait_state_numb(wait_numb), // number of wait state to be insterted.
.device_cs_polarity(cs_polarity), // active high/low chip select for the devices.
.addressed_device(activate_cs), // which device is addressed acive high (broadcast possible)
.start_transfert(start_reg), // statr transfer. to be plugged on an edge detector
.transfert_type(transfert_type), // read/write/opcode... type of tranfert
.address_field(addr_field), // address bits to be sent (from MSB to LSB)
.opcode_field(opcode_field), // opcode to be sent to device from MSB
.page_size(page_size), // number of bytes to be sent/received
.lcd_address(lcd_a), // LCD specific serial address bit
.nwr_fifo(nwr_fifo_reg), // write data to fifo
.nrd_fifo(nrd_fifo_reg), // read_data from fifo
.break(break), //in case of fifo full/empty stop transmission completely
.clk_divider(clk_divider),
.it_mask(it_mask),
.tx_trigger(tx_trigger),
.rx_trigger(rx_trigger),
.int_reg_read(int_reg_read),
.spi_int(spi_int),
.dma_mask(dma_mask),
.int_val(int_val),
.fifo_full(fifo_full),
.fifo_empty(fifo_empty),
.fifo_level(fifo_level[2:0]),
.pdoe(pdoe),
.page_number(page_number),
.time_ext(time_ext)
);
spi_core core(
.clk(function_clk), //clock
.nreset(pnres), //async system reset
.wait_state_en(wait_state_en), //enable usage of wait states
.spi_si(spi_si), //spi serial output
.spi_mode(spi_mode), //spi mode (0, 1, 2, 3)
.opcode_length(opcode_length), //size of opcode to be transmitted
.address_length(address_length), //size of address to be sent
.wait_numb(wait_numb), //number of wait states to be inserted
.opcode_field(opcode_field), //opcode to send
.addr_field(addr_field), //adress to send
.data_field(fifo_do), //data to send
.start(start), //initiate transfert
.transfert_type(transfert_type), //read/write, opcode+read/write ....
.break(break), //in case of fifo full/empty stop transmission completely
.lcd_a(lcd_a), //bit value to be sent with opcode+address and data field
.time_ext(time_ext),
.spi_clk(spi_clk), //spi clock to be sent to device
.spi_so(spi_so), //spi serial output
.busy(busy), //indicates a tranfer is ongoing
.fifo_empty(fifo_empty), //fifo is empty
.fifo_full(fifo_full), //fifo is full
.nwr_fifo_r(nwr_fifo_core), //write to fifo
.nrd_fifo(nrd_fifo_core), //read from fifo
.nb_data_byte(page_size), //number of data byte to send, receive
.activate_cs(activate_cs), //designate the device that will be addressed
.inactive_cs_state(cs_polarity),//activity level of the cs
.spi_cs(spi_cs), //spi chip select to devices
.spi_oen(spi_oen), //spi output enable active low
.rxdata(rxdata), //serialy received data
.spi_a(spi_a), //serial address for LCD
.transfert_started(transfert_started),
.page_number(page_number),
.n_opcode_addr_busy(n_opcode_addr_busy)
);
spi_it int(
.clk(fifo_clk),
.nreset(pnres),
.read(int_reg_read),
.end_com(~busy),
.fifo_level(fifo_level),
.rx_trigger_level(rx_trigger),
.tx_trigger_level(tx_trigger),
.operation(transfert_type),
.mask(it_mask),
.dma_mask(dma_mask),
.start_from_reg(start_reg),
.busy(transfert_started),
.n_opcode_addr_busy(n_opcode_addr_busy),
.spi_int(spi_int),
.it_val(int_val),
.dma_req(dma_req),
.start_to_core(start),
.dma_op_add_req(dma_op_add_req)
);
// the current fifo depth is 8 bytes if you want to change this please
// open the spi_fifo.v file to check the parameter used for HDLI, then
// reproduce them and change the fifo depth according to your
// wishes.
// it will also be nescessary to make some small modification to the
// Interupt block due to a change in the fifo_level_bus size.
//
spi_fifo fifo(.cp(fifo_clk), // FIFO clock
.nrd(fifo_nrd), // FIFO Read enable
.nwr(fifo_nwr), // FIFO Write enable
.nreseta(pnres), // FIFO asynchronous reset
.di(fifo_di), // FIFO Data input
.full(fifo_full), // FIFO Full flag
.empty(fifo_empty), // FIFO Empty flag
.level(fifo_level), // FIFO Real time level indicator bus
.do(fifo_do)); // FIFO Data output bus
//clock divider used to have a spi programable clock speed
//if the clock gating scheme is not in use the folowing can be removed
spi_clkdiv_count clkdiv_cnt (.clk(div_clk), // Clock Input
.cdn(pnres), // Clear Direct Not Input
.maxval(clk_divider), // Programmable Maximum Count Value
.q(), // 3 bit Result
.tci(clkdiv_tci)); // Terminal Count Indicator
reg nrd_fifo_core_r;
always @(posedge fifo_clk or negedge pnres) //flop used to make the nrd signal comming from core
if(!pnres) //to fifo one clock edge regardless of where the clock
nrd_fifo_core_r<=1; //is comming from, register or core.
else //it is required that the reg clock is faster than function
nrd_fifo_core_r<=nrd_fifo_core; //clock
reg nwr_fifo_core_r;
always @(posedge fifo_clk or negedge pnres) //flop used to make the nwr signal comming from core
if(!pnres) //to fifo one clock edge regardless of where the clock
nwr_fifo_core_r<=1; //is comming from, register or core.
else //it is required that the reg clock is faster than function
nwr_fifo_core_r<=nwr_fifo_core; //clock
//top level glue logic for clock gating due to power consumption
assign fifo_nwr=nwr_fifo_reg & (nwr_fifo_core | ~nwr_fifo_core_r);
assign fifo_nrd=nrd_fifo_reg & (~nrd_fifo_core | nrd_fifo_core_r);
assign fifo_di= nwr_fifo_core ? pdi : rxdata;
assign nclkena = (~clkdiv_tci)| powerdown; //negative enable for funtioanl clock
assign nenable_reg_clk = ~psel_spi; //negative enable for register clock
assign nena_fifo_clk = nenable_reg_clk & nclkena; //negative enable for fifo
// clock will toggle infunctional mode
//and during processor access.
assign ntest_comb = ~test_comb;
// clock gates for the 4 domains
//synopsys translate_off
`ifdef STRUCTURAL
//synopsys translate_on
// A set_clock_gating_check constraint should be set on the design.
// This constraint will force dc_compiler to check arrival time of the
// gating signal with respect to the clock and to not optimize gates
// gating clock with the rest of the logic. However, it may change the
// drive of these gates.
aon21d2 reg_clk_u0( .a1( nenable_reg_clk ),
.a2( ntest_comb ),
.b ( pclk ),
.z ( reg_clk ) );
aon21d2 clk_div_u0( .a1( powerdown ),
.a2( ntest_comb ),
.b ( pclk ),
.z ( div_clk ) );
aon21d2 fifo_clk_u0( .a1( nclkena ),
.a2( ntest_comb ),
.b ( pclk ),
.z ( function_clk ) );
aon21d2 function_clk_u0( .a1( nena_fifo_clk ),
.a2( ntest_comb ),
.b ( pclk ),
.z ( fifo_clk ) );
//synopsys translate_off
`else
assign div_clk = pclk | (powerdown & ntest_comb);
assign function_clk = pclk | (nclkena & ntest_comb);
assign reg_clk = pclk | (nenable_reg_clk & ntest_comb);
assign fifo_clk = pclk | (nena_fifo_clk & ntest_comb);
`endif
//synopsys translate_on
endmodule // temp_top
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -