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 + -
显示快捷键?