OpenCores
URL https://opencores.org/ocsvn/pci_mini/pci_mini/trunk

Subversion Repositories pci_mini

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /pci_mini/trunk
    from Rev 4 to Rev 7
    Reverse comparison

Rev 4 → Rev 7

/pci_mini-34.v
0,0 → 1,739
// *************************************************************** //
// //
// PCI_TARGET-Wishbone_MASTER INTERFACE MODULE (PCI-mini) //
// v3.4 //
// //
// The original PCI module is from: Ben Jackson //
// http://www.ben.com/minipci/verilog.php //
// //
// Redesigned for wishbone : Istvan Nagy, buenos@freemail.hu //
// //
// //
// DOWNLOADED FROM OPENCORES. (License = GPL) //
// //
// *************************************************************** //
 
// The core implements a 16MB relocable memory image. Relocable on the
// wb bus. the wb address = 4M*wb_baseaddr_reg + PCI_addr[23:2]
// Only Dword aligned Dword accesses allowed on the PCI. This way
// we can access to the 4GB wb-space through a 16MB PCI-window.
// The addressing on the wb-bus, is Dword addressing, while on the
// PCI bus, the addressing is byte addressing. A(pci)=A(wb)*4
// The PCI address is increasing by 4, and we get 4 bytes. The wb
// address is increasing by 1, and we get 1 Dword (= 4 bytes also).
// The wb_baseaddr_reg is the wb image relocation register, can be
// accessed at 50h address in the PCI configuration space.
// Other bridge status and command is at the 54h and 58h addresses.
// if access fails with timeout, then the address will be in the
// wb address will be stored in the failed_addr_reg at 5Ch address.
//
// Wishbone compatibility:
// Wishbone signals: wb_address, wb_dat_o, wb_dat_i, wb_sel_o, wb_cyc_o,
// wb_stb_o, wb_wr_o, wb_reset_o, wb_clk_o, wb_ack_i.
// Not implemented wb signals: error, lock, retry, tag-signals.
// The peripheral has to response with ack in 16 clk cycles.
// The core has wishbone clk and reset outputs, just like a Syscon module.
// The core generates single reads/writes. These are made of 4 phases, so
// dont write new data, until internal data movement finishes: about 300...500ns
//
// PCI compatibility:
// Only single DWORD reads/writes are supported. between them, the software has
// to wait 300...500nsec, to prevent data corrupting. STOP signaling is not
// implemented, so target terminations also not.
// Single Byte access is NOT supported! It may cause corrupt data.
// The core uses INTA interrupt signal. There are some special PCI config
// registers, from 50h...60h config-space addresses.
// PCI-parity: it generates parity, but doesnt check incoming parity.
// Because of the PC chipset, if you read a value and write it back,
// the chipset will not write anything, because it can see the data is not
// changed. This is important at some peripherals, where you write, to control.
// Device specific PCI config header registers:
// name: addr: function:
// wb_baseaddr_reg; 50h A(wb)=(A(pci)-BAR0)/4 + wb_baseaddr_reg. RESET TO 0
// user_status_reg; 54h not used yet
// user_command_reg; 58h not used yet
// failed_addr_reg; 5Ch address, when timeout occurs on the wb bus.
//
// Local bus arbitration:
// This is not really wishbone compatible, but needed for the PCI.
// The method is: "brute force". it means if the PCI interface wants to
// be mastering on the local (wishbone) bus, then it will be mastering,
// so, the other master(s) must stop anything immediately. The req signal
// goes high when there is an Address hit on teh PCI bus. so the other
// master has few clk cycles to finish.
// Restrictions: the peripherals have to be fast: If the other master
// starts a transaction before req goes high, the ack has to arrive before
// the PCI interface starts its own transaction. (max 4clk ACK delay)
// The other master or the bus unit must sense the req, and give bus
// mastering to the PCI-IF immediatelly, not just when the other master
// finished everything, like at normal arbitration schemes.
//
// Buffering:
// There is a single Dword buffering only.
//
// The led_out interface:
// only for system-debug: we can write to the LEDs, at any address.
// (in the same time there is a wishbone write also)
//
// Changes since original version: wishbone interface,
// bigger memory-image, parity-generation,
// interrupt handling. Code size is 3x bigger. New registers,
//
// Device Compatibility:
// Until v3.3 the code was tested on Xilinx FPGAs (sp2, sp3) with ISE 4.7-9.1 and VIA/AMD chipsets.
// Version 3.4 has modifications to work on Actel/Microsemi ProASIC3 with Sinplify and Intel Atom chipset.
// (v3.4 was not tested on Xilinx FPGAs) To make sure that it runs on the Actel FPGA, we have to use the
// timing constraint SDC file, AND ALSO set the P&R to Timing optimized and "effort"=high.
//
// *************************************************************** //
 
 
 
module pci(reset, pciclk, frame, irdy, trdy, devsel, idsel, ad, cbe, par, stop, inta, serr, perr, led_out, wb_address, wb_dat_o, wb_dat_i, wb_sel_o, wb_cyc_o, wb_stb_o, wb_wr_o, wb_reset_o, wb_clk_o, wb_ack_i, wb_irq, wb_req, wb_gnt, wb_req_other, contr_o);
input reset;
input pciclk;
input frame;
input irdy;
output trdy;
output devsel;
input idsel;
inout [31:0] ad;
input [3:0] cbe;
inout par;
output stop;
output inta;
output serr;
output perr;
output [3:0] led_out;
output [31:0] wb_address;
output [31:0] wb_dat_o;
input [31:0] wb_dat_i;
output [3:0] wb_sel_o;
output wb_cyc_o;
output wb_stb_o;
output wb_wr_o;
output wb_reset_o;
output wb_clk_o;
input wb_ack_i;
input wb_irq;
output wb_req;
input wb_gnt;
input wb_req_other;
output [7:0] contr_o;
 
parameter DEVICE_ID = 16'h9500;
parameter VENDOR_ID = 16'h11AA; // 16'h11AA = actel,
parameter DEVICE_CLASS = 24'h118000; // some examples: 068000=bridge/other, 078000=simple_comm_contr/other, 118000=data_acquisition/other
parameter DEVICE_REV = 8'h01;
parameter SUBSYSTEM_ID = 16'h0001; // Card identifier
parameter SUBSYSTEM_VENDOR_ID = 16'h13C7; // 13C7 = bluechip technology
parameter DEVSEL_TIMING = 2'b00; // Fast!
 
reg [2:0] state;
reg [31:0] data;
 
reg [1:0] enable;
parameter EN_NONE = 2'b00;
parameter EN_RD = 2'b01;
parameter EN_WR = 2'b10;
parameter EN_TR = 2'b11;
 
reg memen; // respond to baseaddr?
reg [7:0] baseaddr;
reg [5:0] address;
 
reg [9:0] wb_baseaddr_reg; //remap the image on the wishbone bus
reg [31:0] wb_address_1;
reg [31:0] user_status_reg;
reg [31:0] user_command_reg;
reg [31:0] failed_addr_reg;
reg [31:0] dummy_reg;
reg [31:0] pci_read_reg;
reg [31:0] pci_write_reg;
reg [31:0] wb_read_reg;
reg [31:0] wb_write_reg;
reg [3:0] pci_read_sel_reg;
reg [3:0] pci_write_sel_reg;
reg [3:0] wb_read_sel_reg;
reg [3:0] wb_write_sel_reg;
 
assign contr_o = user_command_reg [7:0];
 
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 [3:0] led;
`endif
 
`undef STATE_DEBUG_LED
`ifdef STATE_DEBUG_LED
assign led_out = ~state;
`else
`ifdef LED
assign led_out = ~led;
`endif
`endif
 
assign ad = (enable == EN_RD) ? data : 32'bZ;
 
reg [1:0] enable_delayed;
always @(posedge pciclk)
begin enable_delayed <= enable; end
 
 
// TRDY# Generation --------------------------------------------------
reg [31:0] wb_address_previous;
reg [31:0] wb_address_readonly;
reg trdy;
//assign trdy = (enable_delayed == EN_NONE) ? 'bZ : (enable == EN_TR ? 1 : 0);
always @(posedge pciclk) //delaying of trdy
if (enable_delayed == EN_NONE)
trdy <= 'bZ;
else if (enable == EN_TR)
trdy <= 'b1;
else if ((wb_address_previous != wb_address_readonly) && (state == ST_MEMREAD))
trdy <= 'b1;
else
trdy <= 'b0;
 
//assign trdylocal = (enable_delayed == EN_NONE) ? 'b1 : (enable == EN_TR ? 1 : 0);
reg trdylocal;
always @(posedge pciclk) //delaying of trdy
if (enable_delayed == EN_NONE)
trdylocal <= 'b1;
else if (enable == EN_TR)
trdylocal <= 'b1;
else if ((wb_address_previous != wb_address_readonly) && (state == ST_MEMREAD))
trdylocal <= 'b1;
else
trdylocal <= 'b0;
 
 
// STOP# Generation --------------------------------------------------
//auto-generate Retry for read completion transactions, by using STOP# and target-abort:
reg stop;
always @(posedge pciclk) //delaying of trdy
if (enable_delayed == EN_NONE)
stop <= 'bZ;
else if (enable == EN_TR)
stop <= 'b1;
else if ((wb_address_previous != wb_address_readonly) && (state == ST_MEMREAD))
stop <= 'b0;
else
stop <= 'bZ;
reg stoplocal;
always @(posedge pciclk) //delaying of trdy
if (enable_delayed == EN_NONE)
stoplocal <= 'b1;
else if (enable == EN_TR)
stoplocal <= 'b1;
else if ((wb_address_previous != wb_address_readonly) && (state == ST_MEMREAD))
stoplocal <= 'b0;
else
stoplocal <= 'b1;
//assign stop = 1'bZ; //if not used
 
 
 
 
reg devsel;
 
assign serr = 1'bZ;
assign perr = 1'bZ;
 
 
wire cfg_hit = ((cbe == CFGREAD || cbe == CFGWRITE) && idsel && ad[10:8] == 3'b000 && ad[1:0] == 2'b00);
wire addr_hit = ((cbe == MEMREAD || cbe == MEMWRITE) && memen && ad[31:24] == {baseaddr});
wire hit = cfg_hit | addr_hit;
 
//count hit for debug purposes. also trigger on it in the logic analyzer:
reg [7:0] hitcounter;
always @(posedge pciclk)
if (~reset) begin
hitcounter <= 4'b00000000;
end
else begin
if ((hit=='b1) & (frame == 'b0)) hitcounter <= hitcounter +1;
end
 
 
 
 
 
// Wishbone SYSCON: output signals------------------------------------
assign wb_reset_o = ~reset;
assign wb_clk_o = pciclk;
//reg wb_clk_o;
//always @(posedge clk)
//wb_clk_o = wb_clk_o+ 1;
 
 
// PCI parity generation:---------------------------------------------
// during read, the parity on AD, and delayen by one clk.
reg par_en;
reg par_latched;
reg EN_RDd;
reg addr_increment;
wire data_par = (data[31] ^ data[30] ^ data[29] ^ data[28]) ^
(data[27] ^ data[26] ^ data[25] ^ data[24]) ^
(data[23] ^ data[22] ^ data[21] ^ data[20]) ^
(data[19] ^ data[18] ^ data[17] ^ data[16]) ^
(data[15] ^ data[14] ^ data[13] ^ data[12]) ^
(data[11] ^ data[10] ^ data[9] ^ data[8]) ^
(data[7] ^ data[6] ^ data[5] ^ data[4]) ^
(cbe[3] ^ cbe[2] ^ cbe[1] ^ cbe[0]) ^
(data[3] ^ data[2] ^ data[1] ^ data[0]) ;
always @(posedge pciclk) //delaying of parity
if ((enable == EN_RD)|(enable == EN_TR)) begin
par_latched = data_par; end
else
begin par_latched = 0; end
always @(posedge pciclk) //delaying of EN_RD
EN_RDd = EN_RD;
//assign par = (enable == EN_RD) ? 0 : 'bZ;
assign par = ((enable == EN_RD)|(enable == EN_RDd)) ? par_latched : 'bZ; //output control
 
 
 
// Interrupt handling:--------------------------------------------------------------------
reg int_dis;
wire int_stat;
reg [7:0] int_line;
assign inta = ((wb_irq == 1) && (int_dis == 0)) ? 1'b0 : 1'bZ;
assign int_stat = wb_irq;
 
 
 
// WB bus arbitration:--------------------------------------------------------------------
//assign wb_req = mastering;
reg arb_start;
reg arb_stop;
reg wb_req;
 
parameter arb_state1 = 2'b00;
parameter arb_state2 = 2'b01;
reg arb_state = arb_state1;
always@(posedge pciclk) begin
if (wb_reset_o) begin
arb_state <= arb_state1;
wb_req <= 0;
end
else
case (arb_state)
arb_state1 : begin //arbitration is not needed: IDLE
wb_req <= 0;
if (arb_start == 1)
arb_state <= arb_state2;
end
arb_state2 : begin //arbitration is needed
wb_req <= 1;
if (arb_stop == 1)
arb_state <= arb_state1;
end
default : begin // Fault Recovery
arb_state <= arb_state1;
wb_req <= 0;
end
endcase
end
 
 
// -------------- wishbone state machine --------------------------------------------------
//write FIFO buffer:
reg [31:0] wb_wr_buf [5:0]; //64 Dwords wb write buffer: wb_wr_buf[index] <= value;
reg [3:0] wb_wr_sel_buf [5:0]; //select lines, write buffer: wb_wr_buf[index] <= value;
reg [31:0] fifo_start_wb_addr;
reg [31:0] fifo_act_wb_addr;
reg [5:0] fifo_max_count;
reg [5:0] fifo_wb_counter;
reg [5:0] fifo_wb_counter_o;
reg fifo_flush; //wb output mux control
reg fifo_flush_start; //start pulse
reg fifo_fill; //disable wb during filling fifo
reg [3:0] wbw_timeout_count_new;
reg [1:0] wbw_phase;
//read FIFO buffer:
reg [31:0] wb_rd_buf [5:0]; //64 Dwords wb read buffer: wb_rd_buf[index] <= value;
reg [3:0] wb_rd_sel_buf [5:0]; //select lines, write buffer: wb_wr_buf[index] <= value;
reg [31:0] fifo_start_wb_addr_rd;
reg [31:0] fifo_act_wb_addr_rd;
reg [5:0] fifo_max_count_rd;
reg [5:0] fifo_wb_counter_rd;
reg [5:0] fifo_wb_counter_o_rd;
reg fifo_flush_rd; //wb output mux control
reg fifo_fill_start_rd; //start pulse
reg fifo_fill_rd; //disable wb during filling fifo
reg [3:0] wbr_timeout_count_new;
reg [1:0] wbr_phase;
//
reg wb_cyc_o;
reg wb_stb_o;
reg wb_wr_o;
reg [31:0] wb_address;
reg [3:0] wb_sel_o;
reg [31:0] wb_dat_o;
reg machinereset;
reg mastering;
//assign wb_req = mastering;
 
 
parameter machine_waiting = 2'b00;
parameter machine_flushing = 2'b01;
parameter machine_read_filling = 2'b11;
reg [1:0] wbwf_state = machine_waiting;
always@(posedge wb_clk_o)
if (wb_reset_o) begin
wbwf_state <= machine_waiting;
wbw_phase <= 0;
wbw_timeout_count_new <= 0;
fifo_wb_counter_o<=0;
fifo_flush <= 0;
wb_cyc_o <= 0;
wb_stb_o <= 0;
wb_wr_o <= 0;
wbr_phase <= 0;
wbr_timeout_count_new <= 0;
fifo_wb_counter_o_rd<=0;
fifo_fill_rd <= 0;
wb_address[31:0] = 32'b0;
wb_sel_o = 4'b0;
wb_dat_o = 32'b0;
pci_read_reg <= 0;
mastering <= 0;
arb_stop <= 0;
failed_addr_reg <= 0;
end
else
case (wbwf_state)
machine_waiting : begin //no operation on Wishbone bus **************
wbw_phase <= 0;
wbw_timeout_count_new <= 0;
wbr_phase <= 0;
wbr_timeout_count_new <= 0;
wb_address[31:0] = 32'b0;
wb_cyc_o <= 0;
wb_stb_o <= 0;
wb_wr_o <= 0;
wb_sel_o = 4'b0;
wb_dat_o = 32'b0;
arb_stop <= 0;
if (fifo_flush_start == 1)
begin fifo_flush <= 1; wbwf_state <= machine_flushing; fifo_wb_counter_o<=0; mastering <= 1; end
else if (fifo_fill_start_rd == 1)
begin fifo_fill_rd <= 1; wbwf_state <= machine_read_filling; fifo_wb_counter_o_rd<=0; mastering <= 1; end
end
machine_flushing : begin //wr-FIFO flushing: wb write***********************
wb_sel_o = pci_write_sel_reg;
wb_dat_o = pci_write_reg; //wb_wr_buf[fifo_wb_counter_o];
wb_address[31:0] = fifo_start_wb_addr; //[31:0]+fifo_wb_counter_o ;
if ( wbw_phase== 0 ) begin //phase 0: setup
wb_cyc_o <= 0;
wb_stb_o <= 0;
wb_wr_o <= 0;
wbw_phase <= wbw_phase + 1;
//address and data also changes now, from FIFO
end
else if ( wbw_phase== 1 ) begin //phase 1: access
wb_cyc_o <= 1;
wb_stb_o <= 1;
wb_wr_o <= 1;
wbw_phase <= wbw_phase + 1;
end
else if ( wbw_phase== 2 ) begin //phase 2: wait for ack
wbw_timeout_count_new <= wbw_timeout_count_new +1;
if ((wb_ack_i==1) | (wbw_timeout_count_new==15)) begin
wbw_phase <= wbw_phase + 1;
wb_cyc_o <= 0;
wb_stb_o <= 0;
wb_wr_o <= 0;
if (wbw_timeout_count_new==15) begin failed_addr_reg <= wb_address; end
end
else begin wb_cyc_o <= 1; wb_stb_o <= 1; wb_wr_o <= 1; end
end
else if ( wbw_phase== 3 ) begin //phase 3: hold (finish)
wb_cyc_o <= 0;
wb_stb_o <= 0;
wb_wr_o <= 0;
wbw_phase <= wbw_phase + 1;
wbw_timeout_count_new <=0;
fifo_wb_counter_o <= fifo_wb_counter_o + 1; //for next word
//if ((fifo_wb_counter_o == fifo_max_count-1)|(machinereset == 1)) begin
fifo_flush <= 0;
wbwf_state <= machine_waiting;
fifo_wb_counter_o<=0;
mastering <= 0;
arb_stop <= 1;
//end
end
end
machine_read_filling : begin //rd-FIFO filling: wb read********************
wb_sel_o = pci_read_sel_reg;
wb_dat_o = 32'b0;
wb_address[31:0] = fifo_start_wb_addr_rd; //[31:0]+fifo_wb_counter_o_rd ;
if ( wbr_phase== 0 ) begin //phase 0: setup
wb_cyc_o <= 0;
wb_stb_o <= 0;
wb_wr_o <= 0;
wbr_phase <= wbr_phase + 1;
//address and data also changes now, from FIFO
end
else if ( wbr_phase== 1 ) begin //phase 1: access
wb_cyc_o <= 1;
wb_stb_o <= 1;
wb_wr_o <= 0;
wbr_phase <= wbr_phase + 1;
end
else if ( wbr_phase== 2 ) begin //phase 2: wait for ack
wbr_timeout_count_new <= wbr_timeout_count_new +1;
if ((wb_ack_i==1) | (wbr_timeout_count_new==15)) begin
//wb_rd_buf[fifo_wb_counter_o_rd] <= wb_dat_i; //sampling
pci_read_reg <= wb_dat_i; //sampling
wbr_phase <= wbr_phase + 1;
wb_cyc_o <= 0;
wb_stb_o <= 0;
wb_wr_o <= 0;
if (wbw_timeout_count_new==15) begin failed_addr_reg <= wb_address; end
end
else begin wb_cyc_o <= 1; wb_stb_o <= 1; wb_wr_o <= 0; end
end
else if ( wbr_phase== 3 ) begin //phase 3: hold (finish)
wb_cyc_o <= 0;
wb_stb_o <= 0;
wb_wr_o <= 0;
wbr_phase <= wbw_phase + 1;
wbr_timeout_count_new <=0;
fifo_wb_counter_o_rd <= fifo_wb_counter_o_rd + 1; //for next word
//if ((fifo_wb_counter_o_rd == fifo_max_count_rd-1)|(machinereset == 1)) begin
fifo_fill_rd <= 0;
wbwf_state <= machine_waiting;
fifo_wb_counter_o_rd<=0;
mastering <= 0;
arb_stop <= 1;
//end
end
end
default : begin // Fault Recovery
wbwf_state <= machine_waiting;
end
endcase
 
 
 
 
 
 
 
// main PCI state machine: ---------------------------------------------------------------
always @(posedge pciclk)
begin
if (~reset) begin
state <= ST_IDLE;
enable <= EN_NONE;
baseaddr <= 0;
devsel <= 'bZ;
memen <= 0;
int_line <= 8'b0;
int_dis <= 0;
wb_baseaddr_reg <= 0;
wb_address_1[31:0] <= 0;
user_status_reg <= 0;
user_command_reg <= 0;
fifo_flush_start <= 0;
fifo_fill_start_rd <= 0;
fifo_wb_counter <= 0;
fifo_wb_counter_rd <= 0;
dummy_reg <= 0;
pci_write_reg <= 0;
machinereset <= 0;
led <= 0;
arb_start <= 0;
addr_increment <= 0;
wb_address_readonly <= 0;
wb_address_previous <= 5;
 
end
else begin
case (state)
ST_IDLE: begin
//enable <= EN_NONE;
//devsel <= 'bZ;
fifo_flush_start <= 0;
fifo_fill_start_rd <= 0;
fifo_wb_counter <= 0;
fifo_wb_counter_rd <= 0;
machinereset <= 0;
addr_increment <= 0;
if (~frame) begin
address <= ad[7:2];
if (hit) begin
devsel <= 0;
state <= {1'b1, cbe[3], cbe[0]};
if (addr_hit) begin arb_start <= 1; end
//devsel <= 0;
wb_address_1[31:0] <= {wb_baseaddr_reg, ad[23:2]};
//if (wbwf_state == machine_waiting) begin //sample address, if FIFO is not busy
fifo_start_wb_addr <= {wb_baseaddr_reg, ad[23:2]};
fifo_start_wb_addr_rd <= {wb_baseaddr_reg, ad[23:2]};
//end
// pipeline the write enable
if (cbe[0]) begin //its one?
enable <= EN_WR;
end
else begin
enable <= EN_RD;
end
if (cbe==4'b0110) begin //latch previous address if its going to be a memory read
wb_address_previous[31:0] <= wb_address_readonly[31:0];
wb_address_readonly[31:0] <= {wb_baseaddr_reg, ad[23:2]};
end
end
else begin
devsel <= 'bZ;
state <= ST_BUSY;
enable <= EN_NONE;
end
end
end
 
ST_BUSY: begin
devsel <= 'bZ;
enable <= EN_NONE;
arb_start <= 0;
if (frame)
state <= ST_IDLE;
end
 
ST_CFGREAD: begin
//enable <= EN_RD;
if (~irdy || trdylocal) begin
case (address)
0: data <= { DEVICE_ID, VENDOR_ID };
1: data <= { 5'b0, DEVSEL_TIMING, 5'b0, int_stat, 8'b0, int_dis, 8'b0, memen, 1'b0};
2: data <= { DEVICE_CLASS, DEVICE_REV };
4: data <= { baseaddr, 12'b0, 8'b0, 4'b0000 }; // baseaddr + request mem < 1Mbyte
11: data <= {SUBSYSTEM_ID, SUBSYSTEM_VENDOR_ID };
15: data <= {16'b0, 7'b0, 1'b1, int_line}; //irq pin and line
16: data <= { 24'b0, baseaddr };
20: data <= { wb_baseaddr_reg, 22'b0}; //wb base address: for wb-local relocation
21: data <= user_status_reg;
22: data <= user_command_reg;
23: data <= failed_addr_reg; //actual addr, at a timeout
default: data <= 'h00000000;
endcase
//address <= address + 1;
arb_start <= 0;
addr_increment <= 1;
if (addr_increment) begin address <= address + 1; end
end
if (frame && ~irdy && ~trdylocal) begin
devsel <= 1;
state <= ST_IDLE;
enable <= EN_TR;
end
else begin
enable <= EN_RD;
end
end
 
ST_CFGWRITE: begin
//enable <= EN_WR;
if (~irdy) begin
case (address)
4: baseaddr <= ad[31:24]; // XXX examine cbe
1: begin memen <= ad[1]; int_dis <= ad[10]; end
15: int_line <= ad[7:0];
20: wb_baseaddr_reg <= ad[31:22];
22: user_command_reg <= ad[31:0];
24: machinereset <= 1; //resetting the wb state machine (60h)
default: ;
endcase
//address <= address + 1;
arb_start <= 0;
addr_increment <= 1;
if (addr_increment) begin address <= address + 1; end
if (frame && ~trdylocal) begin
devsel <= 1;
state <= ST_IDLE;
enable <= EN_TR;
end
else begin
enable <= EN_WR;
end
end
end
 
ST_MEMREAD: begin
//enable <= EN_RD;
arb_start <= 0;
if (~irdy || trdylocal) begin
//address <= address + 1;
data <= pci_read_reg;
pci_read_sel_reg <= ~cbe;
end
if (frame && ~irdy && (~trdylocal || ~stoplocal)) begin
devsel <= 1;
state <= ST_IDLE;
enable <= EN_TR;
//fifo_fill_rd<=0;
//if (wbwf_state == machine_waiting) begin
fifo_fill_start_rd <= 1;
//end
end
else begin
enable <= EN_RD;
end
end
 
ST_MEMWRITE: begin
//enable <= EN_WR;
arb_start <= 0;
if (~irdy) begin
led <= ad[3:0];
pci_write_reg <= ad[31:0];
pci_write_sel_reg <= ~cbe;
//address <= address + 1;
if (frame & ~trdylocal) begin
devsel <= 1;
state <= ST_IDLE;
enable <= EN_TR;
fifo_fill<=0;
//if (wbwf_state == machine_waiting) begin
fifo_flush_start <= 1;
//end
end
else begin
enable <= EN_WR;
end
end
 
end
 
endcase
end
end
endmodule
/pci-32.v
0,0 → 1,626
// *************************************************************** //
// //
// PCI_TARGET-Wishbone_MASTER INTERFACE MODULE (PCI-mini) //
// v2.0 //
// //
// The original PCI module is from: Ben Jackson //
// http://www.ben.com/minipci/verilog.php //
// //
// Redesigned for wishbone : Istvan Nagy, buenos@freemail.hu //
// PEC Products, Industrial Technologies //
// //
// *************************************************************** //
 
// The core implements a 16MB relocable memory image. Relocable on the
// wb bus. the wb address = 4M*wb_baseaddr_reg + PCI_addr[23:2]
// Only Dword aligned Dword accesses allowed on the PCI. This way
// we can access to the 4GB wb-space through a 16MB PCI-window.
// The addressing on the wb-bus, is Dword addressing, while on the
// PCI bus, the addressing is byte addressing. A(pci)=A(wb)*4
// The PCI address is increasing by 4, and we get 4 bytes. The wb
// address is increasing by 1, and we get 1 Dword (= 4 bytes also).
// The wb_baseaddr_reg is the wb image relocation register, can be
// accessed at 50h address in the PCI configuration space.
// Other bridge status and command is at the 54h and 58h addresses.
// if access fails with timeout, then the address will be in the
// wb address will be stored in the failed_addr_reg at 5Ch address.
//
// Wishbone compatibility:
// Wishbone signals: wb_address, wb_dat_o, wb_dat_i, wb_sel_o, wb_cyc_o,
// wb_stb_o, wb_wr_o, wb_reset_o, wb_clk_o, wb_ack_i.
// Not implemented wb signals: error, lock, retry, tag-signals.
// The peripheral has to response with ack in 16 clk cycles.
// The core has wishbone clk and reset outputs, just like a Syscon module.
// The core generates single reads/writes. These are made of 4 phases, so
// dont write new data, until internal data movement finishes: about 300...500ns
//
// PCI compatibility:
// Only single DWORD reads/writes are supported. between them, the software has
// to wait 300...500nsec, to prevent data corrupting. STOP signaling is not
// implemented, so target terminations also not.
// Single Byte access is NOT supported! It may cause corrupt data.
// The core uses INTA interrupt signal. There are some special PCI config
// registers, from 50h...60h config-space addresses.
// PCI-parity: it generates parity, but doesnt check incoming parity.
// Because of the PC chipset, if you read a value and write it back,
// the chipset will not write anything, because it can see the data is not
// changed. This is important at some peripherals, where you write, to control.
// Device specific PCI config header registers:
// name: addr: function:
// wb_baseaddr_reg; 50h A(wb)=(A(pci)-BAR0)/4 + wb_baseaddr_reg
// user_status_reg; 54h not used yet
// user_command_reg; 58h not used yet
// failed_addr_reg; 5Ch address, when timeout occurs on the wb bus.
//
// Local bus arbitration:
// This is not really wishbone compatible, but needed for the PCI.
// The method is: "brute force". it means if the PCI interface wants to
// be mastering on the local (wishbone) bus, then it will be mastering,
// so, the other master(s) must stop anything immediately. The req signal
// goes high when there is an Address hit on teh PCI bus. so the other
// master has few clk cycles to finish.
// Restrictions: the peripherals have to be fast: If the other master
// starts a transaction before req goes high, the ack has to arrive before
// the PCI interface starts its own transaction. (max 4clk ACK delay)
// The other master or the bus unit must sense the req, and give bus
// mastering to the PCI-IF immediatelly, not just when the other master
// finished everything, like at normal arbitration schemes.
//
// Buffering:
// There is a single Dword buffering only.
//
// The led_out interface:
// only for system-debug: we can write to the LEDs, at any address.
// (in the same time there is a wishbone write also)
//
// Changes since original version: wishbone interface,
// bigger memory-image, parity-generation,
// interrupt handling. Code size is 3x bigger. New registers,
//
// *************************************************************** //
 
 
 
module pci(reset,clk,frame,irdy,trdy,devsel,idsel,ad,cbe,par,stop,inta,serr,perr,led_out, wb_address, wb_dat_o, wb_dat_i, wb_sel_o, wb_cyc_o, wb_stb_o, wb_wr_o, wb_reset_o, wb_clk_o, wb_ack_i, wb_irq, wb_req, wb_gnt, wb_req_other);
input reset;
input clk;
input frame;
input irdy;
output trdy;
output devsel;
input idsel;
inout [31:0] ad;
input [3:0] cbe;
inout par;
output stop;
output inta;
output serr;
output perr;
output [3:0] led_out;
output [31:0] wb_address;
output [31:0] wb_dat_o;
input [31:0] wb_dat_i;
output [3:0] wb_sel_o;
output wb_cyc_o;
output wb_stb_o;
output wb_wr_o;
output wb_reset_o;
output wb_clk_o;
input wb_ack_i;
input wb_irq;
output wb_req;
input wb_gnt;
input wb_req_other;
 
parameter DEVICE_ID = 16'h9500;
parameter VENDOR_ID = 16'h10EE; // 16'h10EE=xilinx, 16'h106d; // Sequent!
parameter DEVICE_CLASS = 24'h068000; // Bridge device - other_bridge_type (original:FF0000 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 [2:0] state;
reg [31:0] data;
 
reg [1:0] enable;
parameter EN_NONE = 0;
parameter EN_RD = 1;
parameter EN_WR = 2;
parameter EN_TR = 3;
 
reg memen; // respond to baseaddr?
reg [7:0] baseaddr;
reg [5:0] address;
 
reg [9:0] wb_baseaddr_reg; //remap the image on the wishbone bus
reg [31:0] wb_address_1;
reg [31:0] user_status_reg;
reg [31:0] user_command_reg;
reg [31:0] failed_addr_reg;
reg [31:0] dummy_reg;
reg [31:0] pci_read_reg;
reg [31:0] pci_write_reg;
reg [31:0] wb_read_reg;
reg [31:0] wb_write_reg;
reg [3:0] pci_read_sel_reg;
reg [3:0] pci_write_sel_reg;
reg [3:0] wb_read_sel_reg;
reg [3:0] wb_write_sel_reg;
 
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 [3:0] led;
`endif
 
`undef STATE_DEBUG_LED
`ifdef STATE_DEBUG_LED
assign led_out = ~state;
`else
`ifdef LED
assign led_out = ~led;
`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;
assign serr = 1'bZ;
assign perr = 1'bZ;
 
 
wire cfg_hit = ((cbe == CFGREAD || cbe == CFGWRITE) && idsel && ad[1:0] == 2'b00);
wire addr_hit = ((cbe == MEMREAD || cbe == MEMWRITE) && memen && ad[31:24] == {baseaddr});
wire hit = cfg_hit | addr_hit;
 
// Wishbone SYSCON: output signals------------------------------------
assign wb_reset_o = ~reset;
assign wb_clk_o = clk;
//reg wb_clk_o;
//always @(posedge clk)
//wb_clk_o = wb_clk_o+ 1;
 
 
// PCI parity generation:---------------------------------------------
// during read, the parity on AD, and delayen by one clk.
reg par_en;
reg par_latched;
reg EN_RDd;
wire data_par = (data[31] ^ data[30] ^ data[29] ^ data[28]) ^
(data[27] ^ data[26] ^ data[25] ^ data[24]) ^
(data[23] ^ data[22] ^ data[21] ^ data[20]) ^
(data[19] ^ data[18] ^ data[17] ^ data[16]) ^
(data[15] ^ data[14] ^ data[13] ^ data[12]) ^
(data[11] ^ data[10] ^ data[9] ^ data[8]) ^
(data[7] ^ data[6] ^ data[5] ^ data[4]) ^
(cbe[3] ^ cbe[2] ^ cbe[1] ^ cbe[0]) ^
(data[3] ^ data[2] ^ data[1] ^ data[0]) ;
always @(posedge clk) //delaying of parity
if ((enable == EN_RD)|(enable == EN_TR)) begin
par_latched = data_par; end
else
begin par_latched = 0; end
always @(posedge clk) //delaying of EN_RD
EN_RDd = EN_RD;
//assign par = (enable == EN_RD) ? 0 : 'bZ;
assign par = ((enable == EN_RD)|(enable == EN_RDd)) ? par_latched : 'bZ; //output control
 
 
 
// Interrupt handling:--------------------------------------------------------------------
reg int_dis;
wire int_stat;
reg [7:0] int_line;
assign inta = ((wb_irq == 1) && (int_dis == 0)) ? 1'b0 : 1'bZ;
assign int_stat = wb_irq;
 
 
 
// WB bus arbitration:--------------------------------------------------------------------
//assign wb_req = mastering;
reg arb_start;
reg arb_stop;
reg wb_req;
 
parameter arb_state1 = 2'b00;
parameter arb_state2 = 2'b01;
reg arb_state = arb_state1;
always@(posedge clk) begin
if (wb_reset_o) begin
arb_state <= arb_state1;
wb_req <= 0;
end
else
case (arb_state)
arb_state1 : begin //arbitration is not needed: IDLE
wb_req <= 0;
if (arb_start == 1)
arb_state <= arb_state2;
end
arb_state2 : begin //arbitration is needed
wb_req <= 1;
if (arb_stop == 1)
arb_state <= arb_state1;
end
default : begin // Fault Recovery
arb_state <= arb_state1;
wb_req <= 0;
end
endcase
end
 
 
// -------------- wishbone state machine --------------------------------------------------
//write FIFO buffer:
reg [31:0] wb_wr_buf [5:0]; //64 Dwords wb write buffer: wb_wr_buf[index] <= value;
reg [3:0] wb_wr_sel_buf [5:0]; //select lines, write buffer: wb_wr_buf[index] <= value;
reg [31:0] fifo_start_wb_addr;
reg [31:0] fifo_act_wb_addr;
reg [5:0] fifo_max_count;
reg [5:0] fifo_wb_counter;
reg [5:0] fifo_wb_counter_o;
reg fifo_flush; //wb output mux control
reg fifo_flush_start; //start pulse
reg fifo_fill; //disable wb during filling fifo
reg [3:0] wbw_timeout_count_new;
reg [1:0] wbw_phase;
//read FIFO buffer:
reg [31:0] wb_rd_buf [5:0]; //64 Dwords wb read buffer: wb_rd_buf[index] <= value;
reg [3:0] wb_rd_sel_buf [5:0]; //select lines, write buffer: wb_wr_buf[index] <= value;
reg [31:0] fifo_start_wb_addr_rd;
reg [31:0] fifo_act_wb_addr_rd;
reg [5:0] fifo_max_count_rd;
reg [5:0] fifo_wb_counter_rd;
reg [5:0] fifo_wb_counter_o_rd;
reg fifo_flush_rd; //wb output mux control
reg fifo_fill_start_rd; //start pulse
reg fifo_fill_rd; //disable wb during filling fifo
reg [3:0] wbr_timeout_count_new;
reg [1:0] wbr_phase;
//
reg wb_cyc_o;
reg wb_stb_o;
reg wb_wr_o;
reg [31:0] wb_address;
reg [3:0] wb_sel_o;
reg [31:0] wb_dat_o;
reg machinereset;
reg mastering;
//assign wb_req = mastering;
 
 
parameter machine_waiting = 2'b00;
parameter machine_flushing = 2'b01;
parameter machine_read_filling = 2'b11;
reg [1:0] wbwf_state = machine_waiting;
always@(posedge wb_clk_o)
if (wb_reset_o) begin
wbwf_state <= machine_waiting;
wbw_phase <= 0;
wbw_timeout_count_new <= 0;
fifo_wb_counter_o<=0;
fifo_flush <= 0;
wb_cyc_o <= 0;
wb_stb_o <= 0;
wb_wr_o <= 0;
wbr_phase <= 0;
wbr_timeout_count_new <= 0;
fifo_wb_counter_o_rd<=0;
fifo_fill_rd <= 0;
wb_address[31:0] = 32'b0;
wb_sel_o = 4'b0;
wb_dat_o = 32'b0;
pci_read_reg <= 0;
mastering <= 0;
arb_stop <= 0;
failed_addr_reg <= 0;
end
else
case (wbwf_state)
machine_waiting : begin //no operation on Wishbone bus **************
wbw_phase <= 0;
wbw_timeout_count_new <= 0;
wbr_phase <= 0;
wbr_timeout_count_new <= 0;
wb_address[31:0] = 32'b0;
wb_cyc_o <= 0;
wb_stb_o <= 0;
wb_wr_o <= 0;
wb_sel_o = 4'b0;
wb_dat_o = 32'b0;
arb_stop <= 0;
if (fifo_flush_start == 1)
begin fifo_flush <= 1; wbwf_state <= machine_flushing; fifo_wb_counter_o<=0; mastering <= 1; end
else if (fifo_fill_start_rd == 1)
begin fifo_fill_rd <= 1; wbwf_state <= machine_read_filling; fifo_wb_counter_o_rd<=0; mastering <= 1; end
end
machine_flushing : begin //wr-FIFO flushing: wb write***********************
wb_sel_o = pci_write_sel_reg;
wb_dat_o = pci_write_reg; //wb_wr_buf[fifo_wb_counter_o];
wb_address[31:0] = fifo_start_wb_addr; //[31:0]+fifo_wb_counter_o ;
if ( wbw_phase== 0 ) begin //phase 0: setup
wb_cyc_o <= 0;
wb_stb_o <= 0;
wb_wr_o <= 0;
wbw_phase <= wbw_phase + 1;
//address and data also changes now, from FIFO
end
else if ( wbw_phase== 1 ) begin //phase 1: access
wb_cyc_o <= 1;
wb_stb_o <= 1;
wb_wr_o <= 1;
wbw_phase <= wbw_phase + 1;
end
else if ( wbw_phase== 2 ) begin //phase 2: wait for ack
wbw_timeout_count_new <= wbw_timeout_count_new +1;
if ((wb_ack_i==1) | (wbw_timeout_count_new==15)) begin
wbw_phase <= wbw_phase + 1;
wb_cyc_o <= 0;
wb_stb_o <= 0;
wb_wr_o <= 0;
if (wbw_timeout_count_new==15) begin failed_addr_reg <= wb_address; end
end
else begin wb_cyc_o <= 1; wb_stb_o <= 1; wb_wr_o <= 1; end
end
else if ( wbw_phase== 3 ) begin //phase 3: hold (finish)
wb_cyc_o <= 0;
wb_stb_o <= 0;
wb_wr_o <= 0;
wbw_phase <= wbw_phase + 1;
wbw_timeout_count_new <=0;
fifo_wb_counter_o <= fifo_wb_counter_o + 1; //for next word
//if ((fifo_wb_counter_o == fifo_max_count-1)|(machinereset == 1)) begin
fifo_flush <= 0;
wbwf_state <= machine_waiting;
fifo_wb_counter_o<=0;
mastering <= 0;
arb_stop <= 1;
//end
end
end
machine_read_filling : begin //rd-FIFO filling: wb read********************
wb_sel_o = pci_read_sel_reg;
wb_dat_o = 32'b0;
wb_address[31:0] = fifo_start_wb_addr_rd; //[31:0]+fifo_wb_counter_o_rd ;
if ( wbr_phase== 0 ) begin //phase 0: setup
wb_cyc_o <= 0;
wb_stb_o <= 0;
wb_wr_o <= 0;
wbr_phase <= wbr_phase + 1;
//address and data also changes now, from FIFO
end
else if ( wbr_phase== 1 ) begin //phase 1: access
wb_cyc_o <= 1;
wb_stb_o <= 1;
wb_wr_o <= 0;
wbr_phase <= wbr_phase + 1;
end
else if ( wbr_phase== 2 ) begin //phase 2: wait for ack
wbr_timeout_count_new <= wbr_timeout_count_new +1;
if ((wb_ack_i==1) | (wbr_timeout_count_new==15)) begin
//wb_rd_buf[fifo_wb_counter_o_rd] <= wb_dat_i; //sampling
pci_read_reg <= wb_dat_i; //sampling
wbr_phase <= wbr_phase + 1;
wb_cyc_o <= 0;
wb_stb_o <= 0;
wb_wr_o <= 0;
if (wbw_timeout_count_new==15) begin failed_addr_reg <= wb_address; end
end
else begin wb_cyc_o <= 1; wb_stb_o <= 1; wb_wr_o <= 0; end
end
else if ( wbr_phase== 3 ) begin //phase 3: hold (finish)
wb_cyc_o <= 0;
wb_stb_o <= 0;
wb_wr_o <= 0;
wbr_phase <= wbw_phase + 1;
wbr_timeout_count_new <=0;
fifo_wb_counter_o_rd <= fifo_wb_counter_o_rd + 1; //for next word
//if ((fifo_wb_counter_o_rd == fifo_max_count_rd-1)|(machinereset == 1)) begin
fifo_fill_rd <= 0;
wbwf_state <= machine_waiting;
fifo_wb_counter_o_rd<=0;
mastering <= 0;
arb_stop <= 1;
//end
end
end
default : begin // Fault Recovery
wbwf_state <= machine_waiting;
end
endcase
 
 
 
 
 
 
 
// main PCI state machine: ---------------------------------------------------------------
always @(posedge clk)
begin
if (~reset) begin
state <= ST_IDLE;
enable <= EN_NONE;
baseaddr <= 0;
devsel <= 'bZ;
memen <= 0;
int_line <= 8'b0;
int_dis <= 0;
wb_baseaddr_reg <= 0;
wb_address_1[31:0] <= 0;
user_status_reg <= 0;
user_command_reg <= 0;
fifo_flush_start <= 0;
fifo_fill_start_rd <= 0;
fifo_wb_counter <= 0;
fifo_wb_counter_rd <= 0;
dummy_reg <= 0;
pci_write_reg <= 0;
machinereset <= 0;
led <= 0;
arb_start <= 0;
 
end
else begin
case (state)
ST_IDLE: begin
enable <= EN_NONE;
devsel <= 'bZ;
fifo_flush_start <= 0;
fifo_fill_start_rd <= 0;
fifo_wb_counter <= 0;
fifo_wb_counter_rd <= 0;
machinereset <= 0;
if (~frame) begin
address <= ad[7:2];
if (hit) begin
state <= {1'b1, cbe[3], cbe[0]};
if (addr_hit) begin arb_start <= 1; end
devsel <= 0;
wb_address_1[31:0] <= {wb_baseaddr_reg, ad[23:2]};
//if (wbwf_state == machine_waiting) begin //sample address, if FIFO is not busy
fifo_start_wb_addr <= {wb_baseaddr_reg, ad[23:2]};
fifo_start_wb_addr_rd <= {wb_baseaddr_reg, ad[23:2]};
//end
// pipeline the write enable
if (cbe[0])
enable <= EN_WR;
end
else begin
state <= ST_BUSY;
enable <= EN_NONE;
end
end
end
 
ST_BUSY: begin
devsel <= 'bZ;
enable <= EN_NONE;
arb_start <= 0;
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, 5'b0, int_stat, 8'b0, int_dis, 8'b0, memen, 1'b0};
2: data <= { DEVICE_CLASS, DEVICE_REV };
4: data <= { baseaddr, 12'b0, 8'b0, 4'b0000 }; // baseaddr + request mem < 1Mbyte
11: data <= {SUBSYSTEM_ID, SUBSYSTEM_VENDOR_ID };
15: data <= {16'b0, 7'b0, 1'b1, int_line}; //irq pin and line
16: data <= { 24'b0, baseaddr };
20: data <= { wb_baseaddr_reg, 22'b0}; //wb base address: for wb-local relocation
21: data <= user_status_reg;
22: data <= user_command_reg;
23: data <= failed_addr_reg; //actual addr, at a timeout
default: data <= 'h00000000;
endcase
address <= address + 1;
arb_start <= 0;
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[31:24]; // XXX examine cbe
1: begin memen <= ad[1]; int_dis <= ad[10]; end
15: int_line <= ad[7:0];
20: wb_baseaddr_reg <= ad[31:22];
22: user_command_reg <= ad[31:0];
24: machinereset <= 1; //resetting the wb state machine (60h)
default: ;
endcase
address <= address + 1;
arb_start <= 0;
if (frame) begin
devsel <= 1;
state <= ST_IDLE;
enable <= EN_TR;
end
end
end
 
ST_MEMREAD: begin
enable <= EN_RD;
arb_start <= 0;
if (~irdy || trdy) begin
address <= address + 1;
data <= pci_read_reg;
pci_read_sel_reg <= ~cbe;
end
if (frame && ~irdy && ~trdy) begin
devsel <= 1;
state <= ST_IDLE;
enable <= EN_TR;
fifo_fill_rd<=0;
//if (wbwf_state == machine_waiting) begin
fifo_fill_start_rd <= 1;
//end
end
end
 
ST_MEMWRITE: begin
enable <= EN_WR;
arb_start <= 0;
if (~irdy) begin
led <= ad[3:0];
pci_write_reg <= ad[31:0];
pci_write_sel_reg <= ~cbe;
address <= address + 1;
if (frame) begin
devsel <= 1;
state <= ST_IDLE;
enable <= EN_TR;
fifo_fill<=0;
//if (wbwf_state == machine_waiting) begin
fifo_flush_start <= 1;
//end
end
end
 
end
 
endcase
end
end
endmodule
/pci_mini-34_timing_constraints.sdc
0,0 → 1,68
# Synopsys, Inc. constraint file
# Written on Wed Apr 13 17:34:51 2011
# by Synplify Pro, D-2009.12A Scope Editor
 
#
# Collections
#
 
#
# Clocks
#
 
define_clock {pciclk} -name {pciclk} -freq 33 -clockgroup default_clkgroup_2
 
 
#
# Clock to Clock
#
 
 
#
# Inputs/Outputs
#
define_input_delay {serr} 7.00 -improve 0.00 -route 0.00 -ref {pciclk:r}
define_input_delay {perr} 7.00 -improve 0.00 -route 0.00 -ref {pciclk:r}
define_input_delay {idsel} 7.00 -improve 0.00 -route 0.00 -ref {pciclk:r}
define_input_delay {stop} 7.00 -improve 0.00 -route 0.00 -ref {pciclk:r}
define_input_delay {devsel} 7.00 -improve 0.00 -route 0.00 -ref {pciclk:r}
define_input_delay {trdy} 7.00 -improve 0.00 -route 0.00 -ref {pciclk:r}
define_input_delay {irdy} 7.00 -improve 0.00 -route 0.00 -ref {pciclk:r}
define_input_delay {frame} 7.00 -improve 0.00 -route 0.00 -ref {pciclk:r}
define_input_delay {par} 7.00 -improve 0.00 -route 0.00 -ref {pciclk:r}
define_input_delay {cbe[3:0]} 7.00 -improve 0.00 -route 0.00 -ref {pciclk:r}
define_input_delay {AD[31:0]} 7.00 -improve 0.00 -route 0.00 -ref {pciclk:r}
 
define_output_delay {serr} 22.00 -improve 0.00 -route 0.00 -ref {pciclk:r}
define_output_delay {perr} 22.00 -improve 0.00 -route 0.00 -ref {pciclk:r}
define_output_delay {stop} 22.00 -improve 0.00 -route 0.00 -ref {pciclk:r}
define_output_delay {devsel} 22.00 -improve 0.00 -route 0.00 -ref {pciclk:r}
define_output_delay {trdy} 22.00 -improve 0.00 -route 0.00 -ref {pciclk:r}
define_output_delay {par} 22.00 -improve 0.00 -route 0.00 -ref {pciclk:r}
define_output_delay {AD[31:0]} 22.00 -improve 0.00 -route 0.00 -ref {pciclk:r}
 
 
#
# Registers
#
 
#
# Delay Paths
#
 
#
# Attributes
#
 
#
# I/O Standards
#
 
 
#
# Compile Points
#
 
#
# Other
#
/PCI_Mini_IP_core_Datasheet2.0_oc.pdf Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream
PCI_Mini_IP_core_Datasheet2.0_oc.pdf Property changes : Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: pci-33.v =================================================================== --- pci-33.v (nonexistent) +++ pci-33.v (revision 7) @@ -0,0 +1,629 @@ +// *************************************************************** // +// // +// PCI_TARGET-Wishbone_MASTER INTERFACE MODULE (PCI-mini) // +// v2.0 // +// // +// The original PCI module is from: Ben Jackson // +// http://www.ben.com/minipci/verilog.php // +// // +// Redesigned for wishbone : Istvan Nagy, buenos@freemail.hu // +// PEC Products, Industrial Technologies // +// // +// *************************************************************** // + +// The core implements a 16MB relocable memory image. Relocable on the +// wb bus. the wb address = 4M*wb_baseaddr_reg + PCI_addr[23:2] +// Only Dword aligned Dword accesses allowed on the PCI. This way +// we can access to the 4GB wb-space through a 16MB PCI-window. +// The addressing on the wb-bus, is Dword addressing, while on the +// PCI bus, the addressing is byte addressing. A(pci)=A(wb)*4 +// The PCI address is increasing by 4, and we get 4 bytes. The wb +// address is increasing by 1, and we get 1 Dword (= 4 bytes also). +// The wb_baseaddr_reg is the wb image relocation register, can be +// accessed at 50h address in the PCI configuration space. +// Other bridge status and command is at the 54h and 58h addresses. +// if access fails with timeout, then the address will be in the +// wb address will be stored in the failed_addr_reg at 5Ch address. +// +// Wishbone compatibility: +// Wishbone signals: wb_address, wb_dat_o, wb_dat_i, wb_sel_o, wb_cyc_o, +// wb_stb_o, wb_wr_o, wb_reset_o, wb_clk_o, wb_ack_i. +// Not implemented wb signals: error, lock, retry, tag-signals. +// The peripheral has to response with ack in 16 clk cycles. +// The core has wishbone clk and reset outputs, just like a Syscon module. +// The core generates single reads/writes. These are made of 4 phases, so +// dont write new data, until internal data movement finishes: about 300...500ns +// +// PCI compatibility: +// Only single DWORD reads/writes are supported. between them, the software has +// to wait 300...500nsec, to prevent data corrupting. STOP signaling is not +// implemented, so target terminations also not. +// Single Byte access is NOT supported! It may cause corrupt data. +// The core uses INTA interrupt signal. There are some special PCI config +// registers, from 50h...60h config-space addresses. +// PCI-parity: it generates parity, but doesnt check incoming parity. +// Because of the PC chipset, if you read a value and write it back, +// the chipset will not write anything, because it can see the data is not +// changed. This is important at some peripherals, where you write, to control. +// Device specific PCI config header registers: +// name: addr: function: +// wb_baseaddr_reg; 50h A(wb)=(A(pci)-BAR0)/4 + wb_baseaddr_reg +// user_status_reg; 54h not used yet +// user_command_reg; 58h not used yet +// failed_addr_reg; 5Ch address, when timeout occurs on the wb bus. +// +// Local bus arbitration: +// This is not really wishbone compatible, but needed for the PCI. +// The method is: "brute force". it means if the PCI interface wants to +// be mastering on the local (wishbone) bus, then it will be mastering, +// so, the other master(s) must stop anything immediately. The req signal +// goes high when there is an Address hit on teh PCI bus. so the other +// master has few clk cycles to finish. +// Restrictions: the peripherals have to be fast: If the other master +// starts a transaction before req goes high, the ack has to arrive before +// the PCI interface starts its own transaction. (max 4clk ACK delay) +// The other master or the bus unit must sense the req, and give bus +// mastering to the PCI-IF immediatelly, not just when the other master +// finished everything, like at normal arbitration schemes. +// +// Buffering: +// There is a single Dword buffering only. +// +// The led_out interface: +// only for system-debug: we can write to the LEDs, at any address. +// (in the same time there is a wishbone write also) +// +// Changes since original version: wishbone interface, +// bigger memory-image, parity-generation, +// interrupt handling. Code size is 3x bigger. New registers, +// +// *************************************************************** // + + + +module pci(reset,clk,frame,irdy,trdy,devsel,idsel,ad,cbe,par,stop,inta,serr,perr,led_out, wb_address, wb_dat_o, wb_dat_i, wb_sel_o, wb_cyc_o, wb_stb_o, wb_wr_o, wb_reset_o, wb_clk_o, wb_ack_i, wb_irq, wb_req, wb_gnt, wb_req_other, contr_o); + input reset; + input clk; + input frame; + input irdy; + output trdy; + output devsel; + input idsel; + inout [31:0] ad; + input [3:0] cbe; + inout par; + output stop; + output inta; + output serr; + output perr; + output [3:0] led_out; + output [31:0] wb_address; + output [31:0] wb_dat_o; + input [31:0] wb_dat_i; + output [3:0] wb_sel_o; + output wb_cyc_o; + output wb_stb_o; + output wb_wr_o; + output wb_reset_o; + output wb_clk_o; + input wb_ack_i; + input wb_irq; + output wb_req; + input wb_gnt; + input wb_req_other; + output [7:0] contr_o; + + + +parameter DEVICE_ID = 16'h9500; +parameter VENDOR_ID = 16'h10EE; // 16'h10EE=xilinx, 16'h106d; // Sequent! +parameter DEVICE_CLASS = 24'h068000; // Bridge device - other_bridge_type (original:FF0000 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 [2:0] state; +reg [31:0] data; + +reg [1:0] enable; +parameter EN_NONE = 0; +parameter EN_RD = 1; +parameter EN_WR = 2; +parameter EN_TR = 3; + +reg memen; // respond to baseaddr? +reg [7:0] baseaddr; +reg [5:0] address; + +reg [9:0] wb_baseaddr_reg; //remap the image on the wishbone bus +reg [31:0] wb_address_1; +reg [31:0] user_status_reg; +reg [31:0] user_command_reg; +reg [31:0] failed_addr_reg; +reg [31:0] dummy_reg; +reg [31:0] pci_read_reg; +reg [31:0] pci_write_reg; +reg [31:0] wb_read_reg; +reg [31:0] wb_write_reg; +reg [3:0] pci_read_sel_reg; +reg [3:0] pci_write_sel_reg; +reg [3:0] wb_read_sel_reg; +reg [3:0] wb_write_sel_reg; + +assign contr_o = user_command_reg [7:0]; + +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 [3:0] led; +`endif + +`undef STATE_DEBUG_LED +`ifdef STATE_DEBUG_LED +assign led_out = ~state; +`else +`ifdef LED +assign led_out = ~led; +`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; +assign serr = 1'bZ; +assign perr = 1'bZ; + + +wire cfg_hit = ((cbe == CFGREAD || cbe == CFGWRITE) && idsel && ad[1:0] == 2'b00); +wire addr_hit = ((cbe == MEMREAD || cbe == MEMWRITE) && memen && ad[31:24] == {baseaddr}); +wire hit = cfg_hit | addr_hit; + +// Wishbone SYSCON: output signals------------------------------------ +assign wb_reset_o = ~reset; +assign wb_clk_o = clk; +//reg wb_clk_o; + //always @(posedge clk) + //wb_clk_o = wb_clk_o+ 1; + + +// PCI parity generation:--------------------------------------------- +// during read, the parity on AD, and delayen by one clk. +reg par_en; +reg par_latched; +reg EN_RDd; +wire data_par = (data[31] ^ data[30] ^ data[29] ^ data[28]) ^ + (data[27] ^ data[26] ^ data[25] ^ data[24]) ^ + (data[23] ^ data[22] ^ data[21] ^ data[20]) ^ + (data[19] ^ data[18] ^ data[17] ^ data[16]) ^ + (data[15] ^ data[14] ^ data[13] ^ data[12]) ^ + (data[11] ^ data[10] ^ data[9] ^ data[8]) ^ + (data[7] ^ data[6] ^ data[5] ^ data[4]) ^ + (cbe[3] ^ cbe[2] ^ cbe[1] ^ cbe[0]) ^ + (data[3] ^ data[2] ^ data[1] ^ data[0]) ; + + always @(posedge clk) //delaying of parity + if ((enable == EN_RD)|(enable == EN_TR)) begin + par_latched = data_par; end + else + begin par_latched = 0; end + + always @(posedge clk) //delaying of EN_RD + EN_RDd = EN_RD; + + //assign par = (enable == EN_RD) ? 0 : 'bZ; + assign par = ((enable == EN_RD)|(enable == EN_RDd)) ? par_latched : 'bZ; //output control + + + +// Interrupt handling:-------------------------------------------------------------------- +reg int_dis; +wire int_stat; +reg [7:0] int_line; +assign inta = ((wb_irq == 1) && (int_dis == 0)) ? 1'b0 : 1'bZ; +assign int_stat = wb_irq; + + + +// WB bus arbitration:-------------------------------------------------------------------- +//assign wb_req = mastering; +reg arb_start; +reg arb_stop; +reg wb_req; + + parameter arb_state1 = 2'b00; + parameter arb_state2 = 2'b01; + reg arb_state = arb_state1; + always@(posedge clk) begin + if (wb_reset_o) begin + arb_state <= arb_state1; + wb_req <= 0; + end + else + case (arb_state) + arb_state1 : begin //arbitration is not needed: IDLE + wb_req <= 0; + if (arb_start == 1) + arb_state <= arb_state2; + end + arb_state2 : begin //arbitration is needed + wb_req <= 1; + if (arb_stop == 1) + arb_state <= arb_state1; + end + default : begin // Fault Recovery + arb_state <= arb_state1; + wb_req <= 0; + end + endcase + end + + + +// -------------- wishbone state machine -------------------------------------------------- +//write FIFO buffer: +reg [31:0] wb_wr_buf [5:0]; //64 Dwords wb write buffer: wb_wr_buf[index] <= value; +reg [3:0] wb_wr_sel_buf [5:0]; //select lines, write buffer: wb_wr_buf[index] <= value; +reg [31:0] fifo_start_wb_addr; +reg [31:0] fifo_act_wb_addr; +reg [5:0] fifo_max_count; +reg [5:0] fifo_wb_counter; +reg [5:0] fifo_wb_counter_o; +reg fifo_flush; //wb output mux control +reg fifo_flush_start; //start pulse +reg fifo_fill; //disable wb during filling fifo +reg [3:0] wbw_timeout_count_new; +reg [1:0] wbw_phase; +//read FIFO buffer: +reg [31:0] wb_rd_buf [5:0]; //64 Dwords wb read buffer: wb_rd_buf[index] <= value; +reg [3:0] wb_rd_sel_buf [5:0]; //select lines, write buffer: wb_wr_buf[index] <= value; +reg [31:0] fifo_start_wb_addr_rd; +reg [31:0] fifo_act_wb_addr_rd; +reg [5:0] fifo_max_count_rd; +reg [5:0] fifo_wb_counter_rd; +reg [5:0] fifo_wb_counter_o_rd; +reg fifo_flush_rd; //wb output mux control +reg fifo_fill_start_rd; //start pulse +reg fifo_fill_rd; //disable wb during filling fifo +reg [3:0] wbr_timeout_count_new; +reg [1:0] wbr_phase; +// +reg wb_cyc_o; +reg wb_stb_o; +reg wb_wr_o; +reg [31:0] wb_address; +reg [3:0] wb_sel_o; +reg [31:0] wb_dat_o; +reg machinereset; +reg mastering; +//assign wb_req = mastering; + + + parameter machine_waiting = 2'b00; + parameter machine_flushing = 2'b01; + parameter machine_read_filling = 2'b11; + reg [1:0] wbwf_state = machine_waiting; + + always@(posedge wb_clk_o) + if (wb_reset_o) begin + wbwf_state <= machine_waiting; + wbw_phase <= 0; + wbw_timeout_count_new <= 0; + fifo_wb_counter_o<=0; + fifo_flush <= 0; + wb_cyc_o <= 0; + wb_stb_o <= 0; + wb_wr_o <= 0; + wbr_phase <= 0; + wbr_timeout_count_new <= 0; + fifo_wb_counter_o_rd<=0; + fifo_fill_rd <= 0; + wb_address[31:0] = 32'b0; + wb_sel_o = 4'b0; + wb_dat_o = 32'b0; + pci_read_reg <= 0; + mastering <= 0; + arb_stop <= 0; + failed_addr_reg <= 0; + end + else + case (wbwf_state) + + machine_waiting : begin //no operation on Wishbone bus ************** + wbw_phase <= 0; + wbw_timeout_count_new <= 0; + wbr_phase <= 0; + wbr_timeout_count_new <= 0; + wb_address[31:0] = 32'b0; + wb_cyc_o <= 0; + wb_stb_o <= 0; + wb_wr_o <= 0; + wb_sel_o = 4'b0; + wb_dat_o = 32'b0; + arb_stop <= 0; + if (fifo_flush_start == 1) + begin fifo_flush <= 1; wbwf_state <= machine_flushing; fifo_wb_counter_o<=0; mastering <= 1; end + else if (fifo_fill_start_rd == 1) + begin fifo_fill_rd <= 1; wbwf_state <= machine_read_filling; fifo_wb_counter_o_rd<=0; mastering <= 1; end + end + + machine_flushing : begin //wr-FIFO flushing: wb write*********************** + wb_sel_o = pci_write_sel_reg; + wb_dat_o = pci_write_reg; //wb_wr_buf[fifo_wb_counter_o]; + wb_address[31:0] = fifo_start_wb_addr; //[31:0]+fifo_wb_counter_o ; + if ( wbw_phase== 0 ) begin //phase 0: setup + wb_cyc_o <= 0; + wb_stb_o <= 0; + wb_wr_o <= 0; + wbw_phase <= wbw_phase + 1; + //address and data also changes now, from FIFO + end + else if ( wbw_phase== 1 ) begin //phase 1: access + wb_cyc_o <= 1; + wb_stb_o <= 1; + wb_wr_o <= 1; + wbw_phase <= wbw_phase + 1; + end + else if ( wbw_phase== 2 ) begin //phase 2: wait for ack + wbw_timeout_count_new <= wbw_timeout_count_new +1; + if ((wb_ack_i==1) | (wbw_timeout_count_new==15)) begin + wbw_phase <= wbw_phase + 1; + wb_cyc_o <= 0; + wb_stb_o <= 0; + wb_wr_o <= 0; + if (wbw_timeout_count_new==15) begin failed_addr_reg <= wb_address; end + end + else begin wb_cyc_o <= 1; wb_stb_o <= 1; wb_wr_o <= 1; end + end + else if ( wbw_phase== 3 ) begin //phase 3: hold (finish) + wb_cyc_o <= 0; + wb_stb_o <= 0; + wb_wr_o <= 0; + wbw_phase <= wbw_phase + 1; + wbw_timeout_count_new <=0; + fifo_wb_counter_o <= fifo_wb_counter_o + 1; //for next word + //if ((fifo_wb_counter_o == fifo_max_count-1)|(machinereset == 1)) begin + fifo_flush <= 0; + wbwf_state <= machine_waiting; + fifo_wb_counter_o<=0; + mastering <= 0; + arb_stop <= 1; + //end + end + end + + machine_read_filling : begin //rd-FIFO filling: wb read******************** + wb_sel_o = pci_read_sel_reg; + wb_dat_o = 32'b0; + wb_address[31:0] = fifo_start_wb_addr_rd; //[31:0]+fifo_wb_counter_o_rd ; + if ( wbr_phase== 0 ) begin //phase 0: setup + wb_cyc_o <= 0; + wb_stb_o <= 0; + wb_wr_o <= 0; + wbr_phase <= wbr_phase + 1; + //address and data also changes now, from FIFO + end + else if ( wbr_phase== 1 ) begin //phase 1: access + wb_cyc_o <= 1; + wb_stb_o <= 1; + wb_wr_o <= 0; + wbr_phase <= wbr_phase + 1; + end + else if ( wbr_phase== 2 ) begin //phase 2: wait for ack + wbr_timeout_count_new <= wbr_timeout_count_new +1; + if ((wb_ack_i==1) | (wbr_timeout_count_new==15)) begin + //wb_rd_buf[fifo_wb_counter_o_rd] <= wb_dat_i; //sampling + pci_read_reg <= wb_dat_i; //sampling + wbr_phase <= wbr_phase + 1; + wb_cyc_o <= 0; + wb_stb_o <= 0; + wb_wr_o <= 0; + if (wbw_timeout_count_new==15) begin failed_addr_reg <= wb_address; end + end + else begin wb_cyc_o <= 1; wb_stb_o <= 1; wb_wr_o <= 0; end + end + else if ( wbr_phase== 3 ) begin //phase 3: hold (finish) + wb_cyc_o <= 0; + wb_stb_o <= 0; + wb_wr_o <= 0; + wbr_phase <= wbw_phase + 1; + wbr_timeout_count_new <=0; + fifo_wb_counter_o_rd <= fifo_wb_counter_o_rd + 1; //for next word + //if ((fifo_wb_counter_o_rd == fifo_max_count_rd-1)|(machinereset == 1)) begin + fifo_fill_rd <= 0; + wbwf_state <= machine_waiting; + fifo_wb_counter_o_rd<=0; + mastering <= 0; + arb_stop <= 1; + //end + end + end + + default : begin // Fault Recovery + wbwf_state <= machine_waiting; + end + + + endcase + + + + + + + +// main PCI state machine: --------------------------------------------------------------- +always @(posedge clk) +begin + if (~reset) begin + state <= ST_IDLE; + enable <= EN_NONE; + baseaddr <= 0; + devsel <= 'bZ; + memen <= 0; + int_line <= 8'b0; + int_dis <= 0; + wb_baseaddr_reg <= 0; + wb_address_1[31:0] <= 0; + user_status_reg <= 0; + user_command_reg <= 0; + fifo_flush_start <= 0; + fifo_fill_start_rd <= 0; + fifo_wb_counter <= 0; + fifo_wb_counter_rd <= 0; + dummy_reg <= 0; + pci_write_reg <= 0; + machinereset <= 0; + led <= 0; + arb_start <= 0; + + end + else begin + + case (state) + ST_IDLE: begin + enable <= EN_NONE; + devsel <= 'bZ; + fifo_flush_start <= 0; + fifo_fill_start_rd <= 0; + fifo_wb_counter <= 0; + fifo_wb_counter_rd <= 0; + machinereset <= 0; + if (~frame) begin + address <= ad[7:2]; + if (hit) begin + state <= {1'b1, cbe[3], cbe[0]}; + if (addr_hit) begin arb_start <= 1; end + devsel <= 0; + wb_address_1[31:0] <= {wb_baseaddr_reg, ad[23:2]}; + //if (wbwf_state == machine_waiting) begin //sample address, if FIFO is not busy + fifo_start_wb_addr <= {wb_baseaddr_reg, ad[23:2]}; + fifo_start_wb_addr_rd <= {wb_baseaddr_reg, ad[23:2]}; + //end + // pipeline the write enable + if (cbe[0]) + enable <= EN_WR; + end + else begin + state <= ST_BUSY; + enable <= EN_NONE; + end + end + end + + ST_BUSY: begin + devsel <= 'bZ; + enable <= EN_NONE; + arb_start <= 0; + 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, 5'b0, int_stat, 8'b0, int_dis, 8'b0, memen, 1'b0}; + 2: data <= { DEVICE_CLASS, DEVICE_REV }; + 4: data <= { baseaddr, 12'b0, 8'b0, 4'b0000 }; // baseaddr + request mem < 1Mbyte + 11: data <= {SUBSYSTEM_ID, SUBSYSTEM_VENDOR_ID }; + 15: data <= {16'b0, 7'b0, 1'b1, int_line}; //irq pin and line + 16: data <= { 24'b0, baseaddr }; + 20: data <= { wb_baseaddr_reg, 22'b0}; //wb base address: for wb-local relocation + 21: data <= user_status_reg; + 22: data <= user_command_reg; + 23: data <= failed_addr_reg; //actual addr, at a timeout + default: data <= 'h00000000; + endcase + address <= address + 1; + arb_start <= 0; + 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[31:24]; // XXX examine cbe + 1: begin memen <= ad[1]; int_dis <= ad[10]; end + 15: int_line <= ad[7:0]; + 20: wb_baseaddr_reg <= ad[31:22]; + 22: user_command_reg <= ad[31:0]; + 24: machinereset <= 1; //resetting the wb state machine (60h) + default: ; + endcase + address <= address + 1; + arb_start <= 0; + if (frame) begin + devsel <= 1; + state <= ST_IDLE; + enable <= EN_TR; + end + end + end + + ST_MEMREAD: begin + enable <= EN_RD; + arb_start <= 0; + if (~irdy || trdy) begin + address <= address + 1; + data <= pci_read_reg; + pci_read_sel_reg <= ~cbe; + end + if (frame && ~irdy && ~trdy) begin + devsel <= 1; + state <= ST_IDLE; + enable <= EN_TR; + fifo_fill_rd<=0; + //if (wbwf_state == machine_waiting) begin + fifo_fill_start_rd <= 1; + //end + end + end + + ST_MEMWRITE: begin + enable <= EN_WR; + arb_start <= 0; + if (~irdy) begin + led <= ad[3:0]; + pci_write_reg <= ad[31:0]; + pci_write_sel_reg <= ~cbe; + address <= address + 1; + if (frame) begin + devsel <= 1; + state <= ST_IDLE; + enable <= EN_TR; + fifo_fill<=0; + //if (wbwf_state == machine_waiting) begin + fifo_flush_start <= 1; + //end + end + end + + end + + endcase + end +end +endmodule Index: sample_testbench.GIF =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: sample_testbench.GIF =================================================================== --- sample_testbench.GIF (nonexistent) +++ sample_testbench.GIF (revision 7)
sample_testbench.GIF Property changes : Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: sample_timing_constraints.ucf.txt =================================================================== --- sample_timing_constraints.ucf.txt (nonexistent) +++ sample_timing_constraints.ucf.txt (revision 7) @@ -0,0 +1,80 @@ +# -------------------------------------------------------------- +# +# Sample Constraints file for pci-mini project +# +# Istvan Nagy, PEC Products, Industrial Technologies, 2007 +# +# +# The signal names are coming from a used project's top-level +# signals. These will be different in your project. So, rename +# them. and copy them into your ucf file, if you use xilinx-ISE. +# -------------------------------------------------------------- + + +#--------------User_Timing ------------------------------------ +NET "extPCICLK" PERIOD = 30 ns HIGH 50 %; +OFFSET = OUT 23 ns AFTER "extPCICLK" ; +TIMESPEC "TS_P2P" = FROM "PADS" TO "PADS" 23 ns; +#TIMESPEC TS_extPCICLK=PERIOD extPCICLK 30 HIGH 15 +# from the pci-opencores. +NET "extPCI_devsel" OFFSET = IN 7 ns BEFORE "extPCICLK" ; +NET "extPCI_devsel" OFFSET = OUT 11 ns AFTER "extPCICLK" ; +NET "extPCI_frame" OFFSET = IN 7 ns BEFORE "extPCICLK" ; +NET "extPCI_frame" OFFSET = OUT 11 ns AFTER "extPCICLK" ; +#INST "FRAME.PAD" TNM = "PCI_CTRL" +#INST "GNT.PAD" TNM = "PCI_GNT" +NET "extPCI_irdy" OFFSET = IN 7 ns BEFORE "extPCICLK" ; +NET "extPCI_irdy" OFFSET = OUT 11 ns AFTER "extPCICLK" ; +#INST "IRDY.PAD" TNM="PCI_CTRL" +NET "extPCI_par" OFFSET = IN 7 ns BEFORE "extPCICLK" ; +NET "extPCI_par" OFFSET = OUT 11 ns AFTER "extPCICLK" ; +#INST "PAR.PAD" TNM = "PCI_CTRL" +##NET "extPCI_perr" OFFSET = IN 7 ns BEFORE "extPCICLK" ; +##NET "extPCI_perr" OFFSET = OUT 11 ns AFTER "extPCICLK" ; +#INST "PERR.PAD" TNM = "PCI_CTRL" +#INST "REQ.PAD" TNM = "PCI_REQ" +##NET "extPCI_serr" OFFSET = OUT 11 ns AFTER "extPCICLK" ; +#INST "SERR.PAD" TNM = "PCI_CTRL" +#INST "STOP.PAD" TNM = "PCI_CTRL" +NET "extPCI_stop" OFFSET = IN 7 ns BEFORE "extPCICLK" ; +NET "extPCI_stop" OFFSET = OUT 11 ns AFTER "extPCICLK" ; +#INST "TRDY.PAD" TNM = "PCI_CTRL" +#NET "extPCI_idsel" OFFSET = IN 7 ns BEFORE "extPCICLK" ; +NET "extPCICLK" TNM_NET = "extPCICLK"; + +INST "extPCI_AD<6>" TNM = "extPCI_AD"; +INST "extPCI_AD<7>" TNM = "extPCI_AD"; +INST "extPCI_AD<8>" TNM = "extPCI_AD"; +INST "extPCI_AD<9>" TNM = "extPCI_AD"; +INST "extPCI_AD<10>" TNM = "extPCI_AD"; +INST "extPCI_AD<11>" TNM = "extPCI_AD"; +INST "extPCI_AD<12>" TNM = "extPCI_AD"; +INST "extPCI_AD<13>" TNM = "extPCI_AD"; +INST "extPCI_AD<14>" TNM = "extPCI_AD"; +INST "extPCI_AD<15>" TNM = "extPCI_AD"; +INST "extPCI_AD<20>" TNM = "extPCI_AD"; +INST "extPCI_AD<16>" TNM = "extPCI_AD"; +INST "extPCI_AD<21>" TNM = "extPCI_AD"; +INST "extPCI_AD<17>" TNM = "extPCI_AD"; +INST "extPCI_AD<22>" TNM = "extPCI_AD"; +INST "extPCI_AD<18>" TNM = "extPCI_AD"; +INST "extPCI_AD<23>" TNM = "extPCI_AD"; +INST "extPCI_AD<19>" TNM = "extPCI_AD"; +INST "extPCI_AD<24>" TNM = "extPCI_AD"; +INST "extPCI_AD<25>" TNM = "extPCI_AD"; +INST "extPCI_AD<30>" TNM = "extPCI_AD"; +INST "extPCI_AD<26>" TNM = "extPCI_AD"; +INST "extPCI_AD<31>" TNM = "extPCI_AD"; +INST "extPCI_AD<27>" TNM = "extPCI_AD"; +INST "extPCI_AD<28>" TNM = "extPCI_AD"; +INST "extPCI_AD<29>" TNM = "extPCI_AD"; +INST "extPCI_AD<0>" TNM = "extPCI_AD"; +INST "extPCI_AD<1>" TNM = "extPCI_AD"; +INST "extPCI_AD<2>" TNM = "extPCI_AD"; +INST "extPCI_AD<3>" TNM = "extPCI_AD"; +INST "extPCI_AD<4>" TNM = "extPCI_AD"; +INST "extPCI_AD<5>" TNM = "extPCI_AD"; + +TIMEGRP "extPCI_AD" OFFSET = IN 7 ns BEFORE "extPCICLK"; +TIMEGRP "extPCI_AD" OFFSET = OUT 11 ns AFTER "extPCICLK"; +

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.