pci_tar.tf

来自「VHDLVERILOG语言实现的CARDBUS的IP源码,已经实现现场应用」· TF 代码 · 共 745 行 · 第 1/2 页

TF
745
字号
//------------------------------------------------------------------------------
//
// File : pci_tar.tf
// Last Modification: 06/26/2001
//
// Created In SpDE Version: SpDE 8.22
// Author :	Richard Yuan, QuickLogic Corporation
// Copyright (C) 2001, Licensed customers of QuickLogic may copy and modify
// this file for use in designing with QuickLogic devices only.
//	
// Description :
//	This is a PCI target model.
//	Please see "The QL5064 PCI Bus Simulation Environment" for detailed informaiton.
//
// Hierarchy:
//	This file is to be included by pci5(3/4)32_208.tf.
//
// History:	
//	Date	        Author					Version
//  06/26/01		Richard Yuan			1.0
//		- Header reorganized to conform to coding standard.
//
//------------------------------------------------------------------------------


/*************************************************************************/
/*  pci_parity_check                                                     */
/*                                                                       */
/*  module checks ad and c_be parity                                     */
/*                                                                       */
/*************************************************************************/

`timescale 1ns/1ns

module pci_parity_check(ad_p, c_be_n_p, parity32, parity64);

input  [63:0] ad_p;
input  [7:0] c_be_n_p;
output parity32;
output parity64;

assign parity32 = (^ad_p[31:0]) ^ (^c_be_n_p[3:0]);
assign parity64 = (^ad_p[63:32]) ^ (^c_be_n_p[7:4]);

endmodule

/*************************************************************************/
/*  pci_tar.v                                                            */
/*                                                                       */
/*  target only reference pci design                                     */
/*                                                                       */
/*************************************************************************/

module pci_tar(clk, pci_ad, c_be_n, idsel, par, par64, frame_n, irdy_n, trdy_n, 
    devsel_n, req64_n, ack64_n, rst_n, stop_n, perr_n);

input  clk;                  // pci clock
inout  [63:0] pci_ad;        // multiplexed address/data
input  [7:0] c_be_n;         // command/byte enable
input  idsel;				 // configuration access
inout  par;                  // parity
inout  par64;                // parity
input  frame_n;              // transfer frame
input  irdy_n;               // initiator ready
inout  trdy_n;               // target ready
inout  devsel_n;             // device selected
input  req64_n;              // 64-bit request line
inout  ack64_n;              // 64-bit acknowledgement line
input  rst_n;                // PCI master reset
inout  stop_n;               // stop request
inout  perr_n;               // parity error signal

wire [63:0] #4 pci_ad;
wire [7:0] #4 c_be_n;
wire #4 idsel;
wire #4 par;
wire #4 trdy_n;
wire #4 stop_n;
wire #4 devsel_n;
wire #4 perr_n;

reg [63:0] mem_addr;         // address latch
wire [63:0] dataout_reg;      // output data latch
wire adoe;                    // address/data output enable control
wire trdy_reg;                // target ready register
wire trdyoe;                  // target ready output enable
wire stop_reg;                // stop register
reg [7:0] target;            // main state machine
reg [9:0] pcicmd_reg;        // command register 
reg [7:0] c_be_n_d;          // c_be_n input latch
reg parity_en;		     // parity enable
reg [31:0] lower_addr;       // latch lower address in a 64bit addr
reg req64_transaction;       // latch req64 if it is meant for us
reg cfg_access, io_access, ia_access, sc_access;
reg [31:0] sc_reg;

wire frame;
wire irdy;
wire trdy;
wire devsel;
wire req64;
wire ack64;
wire rst;
wire stop;
wire stop_en;
wire parity32_out;             // Parity
wire parity64_out;             // Parity
wire [15:0] pcicmd;          // command register
wire match;                  // ad[] is 32 bit and in our address space
wire match64;                // ad[] is 64 bit and still in our address space
wire matchcfg;
wire matchio;
wire matchia;
wire write_trdy_en;          // enables trdy on a write cycle

integer data_count;          // counts the number of data phases

// main state machine states
parameter idle              = 8'h01;  // 0000 0001
parameter read_turnaround   = 8'h02;  // 0000 0010
parameter s_data            = 8'h04;  // 0000 0100
parameter w_data            = 8'h08;  // 0000 1000
parameter sc				= 8'h10;  // 0001 0000
parameter wait_cycle        = 8'h20;  // 0010 0000
parameter dualaddress_cycle = 8'h40;  // 0100 0000
parameter aborting          = 8'h80;  // 1000 0000

parameter OutDly = 2;

// Module Parameters
//parameter MEM_SIZE = 1024;              //Size of memory in bytes
parameter MEM_SIZE = 4096;              //Size of memory in bytes
parameter IO_SIZE = 256;                //Size of I/O in bytes
parameter CFG_SIZE = 256;               //Size of memory in bytes
reg [1:0]  DEVICE_SPEED;                //0=fast, 1=medium, 2=slow, 3=bridge
reg [63:0] BASE_ADDRESS;                //Base address for this device
reg [31:0] BASE_ADDRESS_IO;             //I/O Base address for this device
reg [63:0] BUS_SIZE;                    //32 or 64 bit bus
reg [63:0] STOP_COUNT;                  //Number of data phases before asserting stop
reg        STOP_ENABLE;                 //Enables ability to assert stop
reg        WAITSTATES_ENABLE;           //Enable insertion of stop states
reg        VARIABLE_WAITS;              //Enable variable wait lengths (INITIAL_WAITS and SUBSEQUENT_WAITS are ignored)
reg [15:0] XFER_COUNT;
reg [63:0] MAX_WAITS;                   //Max # of wait states inserted in variable waits mode
reg [63:0] MIN_WAITS;                   //Min # of wait states inserted in variable waits mode 
reg [63:0] INITIAL_WAITS;               //# of waits to insert before first trdy
reg [63:0] SUBSEQUENT_WAITS;            //# of waits to insert before subsequent trdy's
reg [63:0] STOP_WAITS;                  //# of waits to pause before asserting stop (after STOP_COUNT data phases)
reg        ENABLE_RETRY_COUNT;          //Enable ability to disable stops after RETRY_COUNT stop assertions
reg [63:0] RETRY_COUNT;                 //# of times to assert stop before setting STOP_ENABLE to 0
reg        WRONG_PAR;                          //Should par be inverted?
reg        WRONG_PAR64;                        //Should par64 be inverted?
reg        PERR_ASSERT;                        //Assert perr on a write transaction?
reg        TARGET_ABORT;                //Do a target abort before ever asserting trdy
reg	[63:0] TABORT_COUNT; // Support for phase-delayed Target Aborts (BDS,QL)
reg	       TABORT_ENABLE; // Support for phase-delayed Target Aborts (BDS,QL)
reg		   IA_ENABLE;					//Enable response to Interrupt Acknowledge (RY,QL)
reg	[31:0] INTERRUPT_VECTOR;			//Interrupt vector (RY,QL)

reg Assert_Target_Abort; //control register for TARGET_ABORT mode
reg devsel_activate;
reg devsel_ok;
wire target_selected;

wire ADDRESS_64;
assign ADDRESS_64 = (BASE_ADDRESS+MEM_SIZE) > 33'h1_0000_0000;

initial
  begin
    DEVICE_SPEED = 2'b01;                   //default: Medium speed device
    BASE_ADDRESS = 64'h00000000_00000000;   //Base address for this device
    BASE_ADDRESS_IO = 32'h00000000;         //I/O Base address for this device
    BUS_SIZE = 32;                          //32 or 64 bit bus
    STOP_COUNT = 5;                         //Number of data phases before asserting stop
    STOP_ENABLE = 1;                        //Enables ability to assert stop
    WAITSTATES_ENABLE = 0;                  //Enable insertion of stop states
    VARIABLE_WAITS = 0;                     //Enable variable wait lengths (INITIAL_WAITS and SUBSEQUENT_WAITS are ignored)
	XFER_COUNT = 1;
    MAX_WAITS = 10;                         //Max # of wait states inserted in variable waits mode
    MIN_WAITS = 0;                          //Min # of wait states inserted in variable waits mode 
    INITIAL_WAITS = 2;                      //# of waits to insert before first trdy
    SUBSEQUENT_WAITS = 1;                   //# of waits to insert before subsequent trdy's
    STOP_WAITS = 2;                         //# of waits to pause before asserting stop (after STOP_COUNT data phases)
    RETRY_COUNT = 10;                       //# of times to assert stop before setting STOP_ENABLE to 0
    ENABLE_RETRY_COUNT = 0;                 //Disable Retry Count By Default
    WRONG_PAR = 0;
    WRONG_PAR64 = 0;
    PERR_ASSERT = 0;
    TARGET_ABORT = 0;
	TABORT_COUNT = 0;
	TABORT_ENABLE = 0;
	IA_ENABLE = 0;
	INTERRUPT_VECTOR = 32'h00000000;
	devsel_activate = 1'b0;
	devsel_ok = 1'b0;
	Assert_Target_Abort = 1'b0;
	end

// The Memory Itself
reg[7:0] MyMemory[0:(MEM_SIZE-1)];   // Memory Device
reg[7:0] MyIO[0:(IO_SIZE-1)];   // I/O Device
reg[7:0] MyCfg[0:(CFG_SIZE-1)];   // Cfg Space

assign frame     = !frame_n;
assign irdy      = !irdy_n;
assign trdy      = !trdy_n;
assign devsel    = !devsel_n;
assign req64     = !req64_n;
assign rst       = !rst_n;
assign stop      = !stop_n;
assign pcicmd[15:0] = {6'b0, pcicmd_reg[9:0]};

reg frame_d;
always @(posedge clk) frame_d <= frame;
wire in_addr_phase = ~frame_d & frame;

// state machine
always @ (posedge clk or posedge rst)
begin
    if (rst) begin
        target <= idle;
		io_access <= 1'b0;
		cfg_access <= 1'b0;
		ia_access <= 1'b0;
		sc_access <= 1'b0;
	end
    else begin
        case(target)
            idle: begin
				io_access <= 1'b0;
				cfg_access <= 1'b0;
				ia_access <= 1'b0;
				sc_access <= 1'b0;
                if (TARGET_ABORT) 
                        target <= aborting; //Allow devsel to be asserted then go idle
                else if (in_addr_phase & ADDRESS_64 & (c_be_n[3:0] == 4'b1101))
                        target <= dualaddress_cycle; // Get two chunks of address
                else if (in_addr_phase & (~ADDRESS_64) & (c_be_n[3:0] == 4'b1101))
                        target <= wait_cycle; // Can't be a match
                else if (match & (c_be_n[3:0] == 4'b0110))
						target <= read_turnaround; // Memory Read
                else if (match & (c_be_n[3:0] == 4'b0111))
						target <= w_data; // Memory Write
                else if (match & (c_be_n[3:0] == 4'b1100))
						target <= read_turnaround; // Memory Read Multiple
                else if (match & (c_be_n[3:0] == 4'b1110))
						target <= read_turnaround; // Memory Read Line
                else if (match & (c_be_n[3:0] == 4'b1111))
						target <= w_data; // Memory Write and Invalidate
                else if (match & (c_be_n[3:0] == 4'b0010)) begin
                        target <= read_turnaround; // I/O Read
						io_access <= 1'b1;
				end
                else if (match & (c_be_n[3:0] == 4'b0011)) begin
                        target <= w_data; // I/O Write
						io_access <= 1'b1;
				end
                else if (matchcfg & (c_be_n[3:0] == 4'b1010)) begin
						target <= read_turnaround; // Config Read
						cfg_access <= 1'b1;
				end
                else if (matchcfg & (c_be_n[3:0] == 4'b1011)) begin
						target <= w_data; // Config Write
						cfg_access <= 1'b1;
				end
                else if (matchia) begin
						target <= read_turnaround; // Interrupt Acknowledge
						ia_access <= 1'b1;
				end
				else if (in_addr_phase & (c_be_n[3:0] == 4'b0001)) begin
						target <= sc;
						sc_access <= 1'b1;
				end
                else 
                        target <= idle;
			end

            dualaddress_cycle:
                if (match64 & (c_be_n[3:0] == 4'b0110))
						target <= read_turnaround; // Memory Read
                else if(match64 & (c_be_n[3:0] == 4'b0111))
						target <= w_data; // Memory Write
                else if(match64 & (c_be_n[3:0] == 4'b1100))
						target <= read_turnaround; // Memory Read Multiple
                else if(match64 & (c_be_n[3:0] == 4'b1110))
						target <= read_turnaround; // Memory Read Line
                else if(match64 & (c_be_n[3:0] == 4'b1111))
						target <= w_data; // Memory Write and Invalidate
                else if(match64 & (c_be_n[3:0] == 4'b0010))
                        target <= read_turnaround; // I/O Read, but mapped to mem space
                else if(match64 & (c_be_n[3:0] == 4'b0011))
                        target <= w_data; // I/O Write, but mapped to mem space
                else 
                        target <= idle;
 
            read_turnaround:
                begin
                    //Latch Address, prepare to return data
                    target <= s_data;
                end

            s_data:
                if (irdy & (trdy_reg || stop) & !frame) // Last Read!
                    target <= idle;
                else if ((TABORT_COUNT == data_count) && TABORT_ENABLE)
					 target <= aborting;
                else if (irdy & (trdy_reg || stop) & frame) // Send Next Data Chunk
                    target <= s_data; 
	            else if (!((trdy_reg || stop) & irdy))
                    target <= s_data;

		    w_data:
                if (irdy & (trdy_reg || stop) & !frame) // Last Write!
                    target <= idle;
                else if ((TABORT_COUNT == data_count) && TABORT_ENABLE)
					 target <= aborting;
                else if (irdy & (trdy_reg || stop) & frame) //Receive Next Data Chunk
                    target <= w_data;
                else if(!((trdy_reg || stop) & irdy))
		    		target <= w_data;
                    
            wait_cycle:
                target <= idle;

		    sc:
                if (irdy & !frame)
                    target <= idle;
                else
					target <= sc;

            aborting:
                if (~TARGET_ABORT && ~TABORT_ENABLE) target <= idle;
                else if (Assert_Target_Abort) target <= idle;
				else if (TABORT_ENABLE && (TABORT_COUNT <= data_count)) begin
				Assert_Target_Abort = 1;
				devsel_ok = 0;
				devsel_activate = 0;
		        @(posedge clk);
		        while (frame == 1'b1) @(posedge clk);
  				Assert_Target_Abort <= 1'b0;
				target <= idle;
				end

            default:
                target <= idle;
        endcase
    end
end  // state machine

//Drive ack64_n: whenever we are selected and req64 is active!
wire ack64_oe;
assign ack64_n =  ack64_oe ? (!ack64) : (1'bz); 
assign ack64 = devsel & req64_transaction;
assign ack64_oe = (adoe | write_trdy_en);

always @(posedge clk or posedge rst)
begin
  if (rst)
    req64_transaction <= 1'b0;
  else
    if ((BUS_SIZE == 64) & (req64 || req64_transaction) & (!(target == idle) || frame)
    					 & !(cfg_access || matchcfg) & !(io_access || matchio) & !(ia_access || matchia))
    	req64_transaction <= 1'b1;
    else req64_transaction <= 1'b0;
end


//Drive req64_transaction
always @(posedge clk or posedge rst) 
begin
  if (rst)
    lower_addr <= 32'b0;
  else

⌨️ 快捷键说明

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