📄 pci_stim.v
字号:
// --------------------------------------------------------------------
// >>>>>>>>>>>>>>>>>>>>>>>>> COPYRIGHT NOTICE <<<<<<<<<<<<<<<<<<<<<<<<<
// --------------------------------------------------------------------
// Copyright (c) 2001 by Lattice Semiconductor Corporation
// --------------------------------------------------------------------
//
// Permission:
//
// Lattice Semiconductor grants permission to use this code for use
// in synthesis for any Lattice programmable logic product. Other
// use of this code, including the selling or duplication of any
// portion is strictly prohibited.
//
// Disclaimer:
//
// This VHDL or Verilog source code is intended as a design reference
// which illustrates how these types of functions can be implemented.
// It is the user's responsibility to verify their design for
// consistency and functionality through the use of formal
// verification methods. Lattice Semiconductor provides no warranty
// regarding the use or functionality of this code.
//
// --------------------------------------------------------------------
//
// Lattice Semiconductor Corporation
// 5555 NE Moore Court
// Hillsboro, OR 97214
// U.S.A
//
// TEL: 1-800-Lattice (USA and Canada)
// 408-826-6000 (other locations)
//
// web: http://www.latticesemi.com/
// email: techsupport@latticesemi.com
//
// --------------------------------------------------------------------
// Revision History :
// --------------------------------------------------------------------
// Ver: | Author :| Mod. Date :| Changes Made:
// v1.0 :| D.S. :| 11/09/98 :| Initial Creation
// V1.1 D.S. 5-13-99 Improvements to structure
// of the tests.
// --------------------------------------------------------------------
//
// Module pci_stim
// This module provides stimulus to the PCI Bus.
//
`timescale 1 ns/10 ps
module pci_stim (irdy_l,
reset_l,
pci_clk,
frame_l,
trdy_l,
stop_l,
devsel_l,
pci_par,
pci_add,
pci_cbe_l,
idsel,
pci_inta_l,
data_stop_l
);
// --------------------------------------------------------------------
// inputs
input irdy_l; // initiator ready
input reset_l; // pci reset
input pci_clk; // pci clock
input pci_inta_l; // the interupt from the target
// --------------------------------------------------------------------
// bidirectionals
inout frame_l; // frame -- start of cycle
inout trdy_l; // target ready
inout stop_l; // transaction stop
inout devsel_l; // device select
inout pci_par; // pci parity signal
inout [31:0] pci_add; // muxed pci address/data bus
inout [3:0] pci_cbe_l; // pci byte enables
// --------------------------------------------------------------------
// outputs
output idsel; // id select
output data_stop_l;
// --------------------------------------------------------------------
// Defines
`define del 11 // bus delay time nsec
`define no_brst 0 // not a burst cycle
`define brst 1 // a burst cycle
`define mem 011
`define io 001
`define wait_enable 1 // enables master wait states on long bursts
`define wait_disable 0 // disables master wait states on long burst
`define data_stop 4'b0000
`define retry_stop 4'b0100
`define abort 4'b0101
`define data_tran 4'b0010
// --------------------------------------------------------------------
// Define internal registers
reg frame_reg; // frame register
reg frame_oe; // frame output enable
reg trdy_reg; // trdy register
reg trdy_oe; // trdy output enable
reg stop_reg; // stop register
reg stop_oe; // stop output enable
reg devsel_reg; // devsel register
reg devsel_oe; // devsel output enable
reg pci_par_reg; // pci parity register
reg pci_par_oe; // pci parity output enable
reg irdy_reg; // irdy register
reg irdy_oe; // ordy output enable
reg [31:0] pci_add_reg; // pci address register
reg pci_add_oe; // pci address output enable
reg [3:0] pci_cbe_reg; // pci byte enable registers
reg pci_cbe_oe; // pci byte enable output enable
reg idsel_reg; // idsel register
reg par_gen; // first par
reg data_stop_l; // stop the cycle
reg [3:0] cycle_stat;
reg [31:0] data_return; // the data returned on a read
// from check cycle
integer num_errors;
reg stop_flag, abort_flag, interupt_flag; // flags
// --------------------------------------------------------------------
// pci tristate buffers/buffers
assign #`del frame_l = frame_oe ? frame_reg : 1'bz;
assign #`del irdy_l = irdy_oe ? irdy_reg : 1'bz;
assign #`del trdy_l = trdy_oe ? trdy_reg : 1'bz;
assign #`del stop_l = stop_oe ? stop_reg : 1'bz;
assign #`del devsel_l = devsel_oe ? devsel_reg : 1'bz;
assign #`del pci_par = pci_par_oe ? pci_par_reg : 1'bz;
assign #`del pci_add = pci_add_oe ? pci_add_reg : 32'bz;
assign #`del pci_cbe_l = pci_cbe_oe ? pci_cbe_reg : 4'bz;
assign #`del idsel = idsel_reg;
// --------------------------------------------------------------------
// call pci tasks to generate cycles
// This initial block is the heart of the whole simulation.
// ALL tasks are called from this block.
// please find the individual tasks later in this file
initial begin
data_stop_l = 1'bZ;
pci_reset; // initialize pci signals
//run a little...
kill_time;
wait (reset_l); // wait until reset goes high
pci_sniff; // perform configuration cycles
// run a little...
kill_time;
write_test; // performs single & burst writes
// run a little...
kill_time;
write_special_cycle; // generates retry, abort, stop, & interupt.
// run a little...
kill_time;
read_test; // performs single & burst writes
// run a little...
kill_time;
read_special_cycle;
// run a little...
kill_time;
single_cycle_only_test;
// list end results...
$display($time," %m \t \t << Simulation complete...>>");
$display($time, " %m \t \t << Number of errors: %d >> ", num_errors);
$stop; // stop simulation
end
// --------------------------------------------------------------------
// PCI Parity // generate new parity at each clock edge
always @(posedge pci_clk)
pci_par_reg <= (^ {pci_add_reg, pci_cbe_reg} );
always @(posedge pci_clk)
par_gen <= (^ {pci_add, pci_cbe_l} );
// --------------------------------------------------------------------
// PCI bus release check block
// The following block of code simply makes sure the
// pci ad bus is in High-Z the clock edge after
// a cycle completes
always @ (posedge pci_clk)
begin
if (frame_l && irdy_l) begin
if (pci_add !== 32'hZ) begin
$display($time, " %m \t \t << ERROR!!! pci_add is NOT High-Z during Turnaround Cycle!! >>");
num_errors = num_errors + 1;
end
end
end
/***********************************************************************/
// The following are all the tests that call the particular cycles.
/***********************************************************************/
// --------------------------------------------------------------------
// pci reset task
task pci_reset;
begin
num_errors <= 0;
frame_reg <= 1;
frame_oe <= 0;
irdy_reg <= 1;
irdy_oe <= 0;
trdy_reg <= 1;
trdy_oe <= 0;
stop_reg <= 1;
stop_oe <= 0;
devsel_reg <= 1;
devsel_oe <= 0;
pci_par_oe <= 0;
pci_add_reg <= 32'h0;
pci_cbe_reg <= 4'h0;
pci_add_oe <= 0;
pci_cbe_oe <= 0;
idsel_reg <= 0;
cycle_stat <= 0; // pci cycle status
end
endtask // of pci_reset;
// --------------------------------------------------------------------
// sniff pci configurations
task pci_sniff; // writes and reads config regs
begin
$display($time," %m \t \t << Initializing PCI Config Registers >>");
// read the devid and vendid expect {16'h0120,16'h1022}
read_config(32'h0000_0000, 1, {16'h0120,16'h1022}); // devid/vendid
// read status and command expect 0400_0000 (devsel timing = 2'b10)
read_config(32'h0000_0004, 1, 32'h0400_0000 );
// set command register bits 1 & 0
write_config(32'h0000_0004, 32'h0000_0003); // setup command reg
// read status and command checking for 0400_0003
read_config(32'h0000_0004, 1, 32'h0400_0003 );
// read class code and Revision ID
// expect {24'h058000,8'h01}
read_config(32'h0000_0008, 1,{24'h058000,8'h01} );
// read misc functions reg0Ch
// expect 32'h00000000
read_config(32'h0000_000c, 1, 32'h0000_0000 ); // read
// resetting BA0 by writting all 1's
write_config(32'h0000_0010, 32'hffff_ffff); // init bar 0
// resetting BA1 by writting all 1's
write_config(32'h0000_0014, 32'hffff_ffff); // init bar 1
// read back the address space allocated for BA0
// original ref. design set to this in config_mux block:
//{`ADDR_1M,`PREFETCH_OFF,`ANYWHERE_IN_32,`IO_ON};
// {28'hFFF0_000,1'b0,2'b00,1'b0}
read_config(32'h0000_0010, 1, {28'hFFF0_000,1'b0,2'b00,1'b1});// read bar 0
// read back the address space allocated for BA1
// original ref. design set to this in config_mux block:
//{`ADDR_1M,`PREFETCH_OFF,`ANYWHERE_IN_32,`MEM_ON};
// {28'hFFFF_FFF,1'b0,2'b00,1'b1}
read_config(32'h0000_0014, 1,{28'hFFF0_000,1'b0,2'b00,1'b0} );// read bar 1
// BA0 will respond to addresses starting at 1000_0000
write_config(32'h0000_0010, 32'h1000_0000); // set bar 0
// BA1 will respond to addresses starting at 2000_0000
write_config(32'h0000_0014, 32'h2000_0000); // set bar 1
//read bar 2 should return 0 because it's not implemented
read_config(32'h0000_0018, 1, 32'h0000_0000 ); // read bar 2
// read SubsystemID and Subsystem VendorID
// {16'h0120,16'h1022}
read_config(32'h0000_002C, 1, {16'h0120,16'h1022} );
// read unimplemented reg it should return 0's
read_config(32'h0000_0030, 1, 32'h0000_0000 ); // read unimplemented reg
// read (Max_Lat/Min_Gnt/Interrupt Pin/ Interupt Line)
read_config(32'h0000_003C, 1,{16'h0000,8'h01,8'h00} );
// testing Interupt Line Reg
// Not that FF would ever be valid but it sets all the
// bits to that register to one, and verifies functionality
write_config(32'h0000_003C, 32'h0000_00ff); // write 3C
// read (Max_Lat/Min_Gnt/Interrupt Pin/ Interupt Line)
// making sure Ineterupt Line reg is set to FF.
// Not that FF would ever be valid but it sets all the
// bits to that register to one, and verifies functionality
read_config(32'h0000_003C, 1,{16'h0000,8'h01,8'hFF} );
$display($time," %m \t \t << PCI Config Initialization Complete >>");
$display($time," %m \t \t << Number of configuration cycle errors: %d >>", num_errors);
end
endtask // of pci_sniff;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -