Forum Discussion

Altera_Forum's avatar
Altera_Forum
Icon for Honored Contributor rankHonored Contributor
12 years ago

PCI testbench verifying....please help...

Guys,

I have created myself a PCI testbench for verifying home made PCI card,

Can anyone give idea if I'm doing in a right way or not ?

I'm following the paper "Interfacing PCI with FPGA"

The port is not yet completed, because it's a test.....

Any ideas or references will be very appreciated,

Thanks a lot in advance.

Please see the code :


/* testbench for PCI
File: PCI_testbench.v */
//`timescale 10ns / 10ns
module pci_testbench;
wire  t_ad;  //input output data multiplex with address
reg  t_cbe;  //command or byte enable
reg t_frame;      //input
reg t_clk;        //input
reg t_ad_value;
reg t_irdy;       //input
reg t_devsel;     //output
reg t_trdy;       //output
reg t_reset;      //input
pci my_pci(.ad(t_ad), .cbe(t_cbe), .clk(t_clk), .frame(t_frame), .irdy(t_irdy), .reset(t_reset));
assign t_ad = t_ad_value;
initial
 t_clk = 1'b0 ;
always
# 5 t_clk =~t_clk;
initial 
begin
    /*
     Cycle 1 - The bus is idle
     */
     
     /*
     Cycle 2 - The initiator assets a valid address and places a read command on CBE
     ==>Address phase
     */
    # 1  t_reset = 1'b0;             //put reset on low
   # 1  t_frame = 1'b0;              //active low, the device is ready to perform
     //#10 t_ad = 32'b1010100010;
    # 1  t_cbe = 4'b0010;             //read command
    # 2  t_ad_value = 32'h0000_0001; //insert address
     
     /*
     Cycle 3 ->
     The initiator tristates the address, prepare for reading data.
     Drive a valid byte enable information on CBE.
     Asserts IRDY ==> LOW , indicating it's ready to capture read data.
     Asserts DEVSEL ==> LOW, in this cycle or the next as an acknowledgment it has positively decoded the address
     The target drives TRDY==>HIGH indicating it is not yet providing valid read data.
     */
    # 1  t_reset = 1'b0;             //put reset on low
    # 1  t_ad_value = 32'bz; //insert tristate value
     //#3  t_cbe = //drive a valid byte enable
     # 2  t_irdy = 1'b0;
     //t_devsel = 1'b0;
     //t_trdy = 1'b1;
   
     /*Cycle 4 ->
     Target provides valid data and asserts TRDY ==> LOW indicating to the initiator that data is valid.
     TRDY and IRDY now are both LOW during this cycle causing a data transfer to take place.
     The initiator captures the data. 
     This is the first data phase.
     */
     //#2 t_trdy = 1'b0;
     /*
      Cycle 5 - The target deasserts TRDY# high
        indicating it needs more time to prepare the next data
        transfer.
     */
      //#1 t_trdy = 1'b1;
      /*
      Cycle 6 - The second data phase occurs as both
        IRDY# and TRDY# are low. The initiator captures
        the data provided by the target.
     */
     //#2 t_trdy = 1'b0;
      /*
      Cycle 7 - The target provides valid data for the third
      data phase, but the initiator indicates it is not ready
        by deasserting IRDY# high.
      */
      //#2 t_trdy = 1'b0;
      /*
      Cycle 8 - The initiator re-asserts IRDY# low to
        complete the third data phase. The initiator captures
        the data provided by the target. The initiator drives
        FRAME# high indicating this is the final data phase
        (master termination).
        */
       # 1  t_reset = 1'b0;             //put reset on low
      # 1  t_frame = 1'b1;              //final data phase ( master termination)
        /*
        Cycle 9 - FRAME#, AD, and C/BE# are tri-stated, as
        IRDY#, TRDY#, and DEVSEL# are driven inactive
        high for one cycle prior to being tri-stated.
      */
       # 1  t_reset = 1'b0;             //put reset on low
     # 1  t_frame = 1'bz;              //final data phase ( master termination)
      t_ad_value = 32'bz;
        t_cbe = 4'bz;
        
    end
endmodule

The result in ModelSim

https://www.alteraforum.com/forum/attachment.php?attachmentid=7282

The code I wanna test :


module pci(reset,clk,frame,irdy,trdy,devsel,idsel,ad,cbe,par,stop,inta,led_out);
    input reset;
    input clk;
    input frame;
    input irdy;
    output trdy;
    output devsel;
    input idsel;
    inout  ad;
    input  cbe;
    inout par;
    output stop;
    output inta;
    output  led_out;
parameter DEVICE_ID = 16'h9500;
parameter VENDOR_ID = 16'h106d;        // Sequent!
parameter DEVICE_CLASS = 24'hFF0000;    // Misc
parameter DEVICE_REV = 8'h01;
parameter SUBSYSTEM_ID = 16'h0001;    // Card identifier
parameter SUBSYSTEM_VENDOR_ID = 16'hBEBE; // Card identifier
parameter DEVSEL_TIMING = 2'b00;    // Fast!
reg  state;
reg  data;
reg  enable;
parameter EN_NONE = 0;
parameter EN_RD = 1;
parameter EN_WR = 2;
parameter EN_TR = 3;
reg memen; // respond to baseaddr?
reg  baseaddr;
reg  address;
parameter ST_IDLE = 3'b000;
parameter ST_BUSY = 3'b010;
parameter ST_MEMREAD = 3'b100;
parameter ST_MEMWRITE = 3'b101;
parameter ST_CFGREAD = 3'b110;
parameter ST_CFGWRITE = 3'b111;
parameter MEMREAD = 4'b0110;
parameter MEMWRITE = 4'b0111;
parameter CFGREAD = 4'b1010;
parameter CFGWRITE = 4'b1011;
`define LED
`ifdef LED
reg  led;
`endif
`undef STATE_DEBUG_LED
`ifdef STATE_DEBUG_LED
assign led_out = ~state;
`else
`ifdef LED
assign led_out = ~led;  // board is wired for active low LEDs
`endif
`endif
assign ad = (enable == EN_RD) ? data : 32'bZ;
assign trdy = (enable == EN_NONE) ? 'bZ : (enable == EN_TR ? 1 : 0);
assign par = (enable == EN_RD) ? 0 : 'bZ;
reg devsel;
assign stop = 1'bZ;
assign inta = 1'bZ;
wire cfg_hit = ((cbe == CFGREAD || cbe == CFGWRITE) && idsel && ad == 2'b00);
wire addr_hit = ((cbe == MEMREAD || cbe == MEMWRITE) && memen && ad == {12'b0, baseaddr});
wire hit = cfg_hit | addr_hit;
always @(posedge clk)
begin
    if (~reset) begin
        state <= ST_IDLE;
        enable <= EN_NONE;
        baseaddr <= 0;
        devsel <= 'bZ;
        memen <= 0;
`ifdef LED
        led <= 0;
`endif
    end
    else    begin
                
    case (state)
        ST_IDLE: begin
            enable <= EN_NONE;
            devsel <= 'bZ;
            if (~frame) begin
                address <= ad;
                if (hit) begin
                    state <= {1'b1, cbe, cbe};
                    devsel <= 0;
                    // pipeline the write enable
                    if (cbe)
                        enable <= EN_WR;
                end
                else begin
                    state <= ST_BUSY;
                    enable <= EN_NONE;
                end
            end
        end
        ST_BUSY: begin
            devsel <= 'bZ;
            enable <= EN_NONE;
            if (frame)
                state <= ST_IDLE;
        end
        ST_CFGREAD: begin
            enable <= EN_RD;
            if (~irdy || trdy) begin
                case (address)
                    0: data <= { DEVICE_ID, VENDOR_ID };
                    1: data <= { 5'b0, DEVSEL_TIMING, 9'b0,  14'b0, memen, 1'b0};
                    2: data <= { DEVICE_CLASS, DEVICE_REV };
                    4: data <= { 12'b0, baseaddr, 8'b0, 4'b0010 }; // baseaddr + request mem < 1Mbyte
                    11: data <= {SUBSYSTEM_ID, SUBSYSTEM_VENDOR_ID };
                    16: data <= { 24'b0, baseaddr };
                    default: data <= 'h00000000;
                endcase
                address <= address + 1;
            end
            if (frame && ~irdy && ~trdy) begin
                devsel <= 1;
                state <= ST_IDLE;
                enable <= EN_TR;
            end
        end
        ST_CFGWRITE: begin
            enable <= EN_WR;
            if (~irdy) begin
                case (address)
                    4: baseaddr <= ad;  // XXX examine cbe
                    1: memen <= ad;
                    default: ;
                endcase
                address <= address + 1;
                if (frame) begin
                    devsel <= 1;
                    state <= ST_IDLE;
                    enable <= EN_TR;
                end
            end
        end
        ST_MEMREAD: begin
            enable <= EN_RD;
            if (~irdy || trdy) begin
                case (address)
`ifdef LED
                    0: data <= { 28'b0, led };
`endif
                    default: data <= 'h00000000;
                endcase
                address <= address + 1;
            end
            if (frame && ~irdy && ~trdy) begin
                devsel <= 1;
                state <= ST_IDLE;
                enable <= EN_TR;
            end
        end
        ST_MEMWRITE: begin
            enable <= EN_WR;
            if (~irdy) begin
                case (address)
`ifdef LED
                    0: led <= ad;
`endif
                    default: ;
                endcase
                address <= address + 1;
                if (frame) begin
                    devsel <= 1;
                    state <= ST_IDLE;
                    enable <= EN_TR;
                end
            end
        end
    endcase
    end
end
endmodule
No RepliesBe the first to reply