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

Subversion Repositories openrisc

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /openrisc/trunk/orpsocv2/boards/xilinx/ml501/rtl
    from Rev 69 to Rev 412
    Reverse comparison

Rev 69 → Rev 412

/ml501_startup.v File deleted
/ml501_ddr2_wb_if.v File deleted
/reset_debounce.v File deleted
/ml501_ddr2_params.vh File deleted
/ml501_gpio.v File deleted
/eth_defines.v File deleted \ No newline at end of file
/ml501_ddr2_wb_if_cache.v File deleted \ No newline at end of file
/usr_rst.v File deleted
/ml501_mc.v File deleted
/ssram_controller.v File deleted
/ml501_ddr2_wb_if.v.prev File deleted \ No newline at end of file
/dummy_slave.v File deleted
/or1200_defines.v File deleted
/wb_lfsr.v File deleted
/ml501.v File deleted
/uart_defines.v File deleted
/ml501_defines.v File deleted
/wb_conbus_defines.v File deleted
/ddr2_mig/ddr2_ctrl.v File deleted
/ddr2_mig/ddr2_usr_top.v File deleted \ No newline at end of file
/ddr2_mig/ddr2_mig.v File deleted
/ddr2_mig/ddr2_top.v File deleted
/ddr2_mig/ddr2_chipscope.v File deleted \ No newline at end of file
/verilog/xilinx_ssram/xilinx_ssram.v
0,0 → 1,300
//////////////////////////////////////////////////////////////////////
//// ////
//// Xilinx ML501 SSRAM controller with Wishbone Interface ////
//// ////
//// Description ////
//// ZBT SSRAM controller for ML501 board part (or any ZBT RAM) ////
//// Timing relies on definition of multi-cycle paths during ////
//// synthesis. ////
//// ////
//// To Do: ////
//// ////
//// Author(s): ////
//// - Julius Baxter, julius.baxter@orsoc.se ////
//// ////
//// ////
//////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2010 Authors and OPENCORES.ORG ////
//// ////
//// This source file may be used and distributed without ////
//// restriction provided that this copyright statement is not ////
//// removed from the file and that any derivative work contains ////
//// the original copyright notice and the associated disclaimer. ////
//// ////
//// This source file is free software; you can redistribute it ////
//// and/or modify it under the terms of the GNU Lesser General ////
//// Public License as published by the Free Software Foundation; ////
//// either version 2.1 of the License, or (at your option) any ////
//// later version. ////
//// ////
//// This source is distributed in the hope that it will be ////
//// useful, but WITHOUT ANY WARRANTY; without even the implied ////
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ////
//// PURPOSE. See the GNU Lesser General Public License for more ////
//// details. ////
//// ////
//// You should have received a copy of the GNU Lesser General ////
//// Public License along with this source; if not, download it ////
//// from http://www.opencores.org/lgpl.shtml ////
//// ////
//////////////////////////////////////////////////////////////////////
/*
* Controller for ZBT synchronous SRAM (ISSI IS61NLP25636A-200TQL)
* Explicitly uses Xilinx primitives
* Currently configured for a 1/4 ratio between bus/ssram clocks: 50 / 200 MHz
* Requires declaration of some multi-cycle paths during synthesis.
*
* Note: clk_200 and bus clock should be in phase (from same DCM)
*
* Clocking/phase counting scheme (to change it to higher/lower ratio):
*
* We run a phase counter, checking the bus on the last cycle before we hit another multiple of the SSRAM clock to the bus clock (so cycle 3 if ratio is 4, or a 50MHz system bus and 200MHz SRAM), this gives the system bus signals almost another whole cycle to reach our 200MHz regs (and where we define one of the multi-cycle paths). Once we have the stuff registered it's business as usual on the bus to the SRAM. Then we let it sit in our register for a clock or two
*/
module xilinx_ssram
(
// WB ports
input [31:0] wb_adr_i,
input wb_stb_i,
input wb_cyc_i,
input wb_we_i,
input [3:0] wb_sel_i,
input [31:0] wb_dat_i,
output [31:0] wb_dat_o,
output wb_ack_o,
input wb_clk,
input wb_rst,
 
// SSRAM interface
input clk_200,
output wire sram_clk,
input sram_clk_fb,
output reg [21:1] sram_addr,
inout [31:0] sram_dq_io,
output reg sram_ce_l,
output reg sram_oe_l,
output reg sram_we_l,
output reg [3:0] sram_bw_l,
output reg sram_adv_ld_l,
output sram_mode
);
 
wire [31:0] sram_dq_i;
reg [31:0] sram_dq_o;
reg ssram_controller_oe_l;
wire dcm0_clk0_prebufg, dcm0_clk0;
wire dcm0_locked;
 
wire dcms_locked;
 
reg wb_clk_r = 1'b0;
reg wb_clk_r_d;
wire wb_clk_edge;
 
reg wb_ack_write;
reg [2:0] wb_ack_read_shiftreg;
reg [2:0] clk_200_phase;
reg [4:0] clk_200_cycle_counter;
reg [31:0] data_rd;
wire [3:0] we;
reg write_cycle;
reg [3:0] we_r;
reg reg_from_bus_domain, reg_from_bus_domain_r;
 
assign dcms_locked = dcm0_locked;
assign we = wb_sel_i & {4{wb_cyc_i & wb_stb_i & wb_we_i}};
assign sram_clk = dcm0_clk0;
 
// Do wb_clk edge detection with this
assign wb_clk_edge = wb_clk_r & ~wb_clk_r_d;
assign sram_mode = 0;
initial begin
$display("* SSRAM controller instantiated at %m.");
end
 
// We ACK writes after one cycle
always @(posedge wb_clk)
wb_ack_write <= wb_cyc_i & wb_stb_i & wb_we_i & !wb_ack_write;
 
// We ACK reads after 3
always @(posedge wb_clk)
wb_ack_read_shiftreg <= {wb_ack_read_shiftreg[1:0], wb_cyc_i & wb_stb_i & !wb_we_i & !(|wb_ack_read_shiftreg)};
assign wb_ack_o = wb_we_i ? wb_ack_write : wb_ack_read_shiftreg[2];
 
// Push the bus clock through a register
always @(posedge wb_clk) begin
wb_clk_r <= ~wb_clk_r;
end
// Sample this with the 150 MHz clock
always @(posedge clk_200) begin
wb_clk_r_d <= wb_clk_r;
end
// Maintain a phase count, it goes 0->7 (8 phases, to be clear)
always @(posedge clk_200) begin
if (wb_clk_edge) begin
// Will be at 1 next cycle
clk_200_phase <= 3'd1;
end else if (clk_200_phase < 3'd7 & dcms_locked) begin
clk_200_phase <= clk_200_phase + 1;
end else begin
clk_200_phase <= 3'd0;
end
end
// Multicycle trickery
// Reads will happen like this:
// * Read address is given 3 clk_200 cycles to settle
// * It is put onto the bus for two cycles
// * Read data is then registered
// * It then has several phases to make it back to the bus register
// Number of cycles we preload counter with, depending on access
`define WRITE_CYCLES 5'h04
`define READ_CYCLES 5'h0c
// We let the commands settle for 2 cycles (0, 1) and then sample
// *but* data could have come on either cycle 0 _or_ 3, so check both
`define REQ_CHECK_CYCLE ((clk_200_phase == 3'd3)||(clk_200_phase == 3'd7))
// Write OE - whole time, doesn't matter so much
`define WRITE_OE_CYCLE (|clk_200_cycle_counter)
// Read OE, just the first two cycles
//`define READ_OE_CYCLE (clk_200_cycle_counter > (`READ_CYCLES - 5'h4))
`define READ_OE_CYCLE (|clk_200_cycle_counter)
// Sample data from RAM 2 cycles after we sample the addr from system bus
`define RAM_DATA_SAMPLE_CYCLE (!(|we_r) && clk_200_cycle_counter == (`READ_CYCLES - 5'h5))
// Cycle when we pull sram_we_l low
`define WRITE_CE_CYCLE (reg_from_bus_domain & (|we))
// Cycle when we ouptut the CE
`define READ_CE_CYCLE (reg_from_bus_domain & !(|we))
 
// Register stuff when we've just loaded the counter
`define REG_FROM_BUS_DOMAIN reg_from_bus_domain
 
// CE 2 cycles dring writes, only one during reads
always @(posedge clk_200)
sram_ce_l <= 0;
//sram_ce_l <= ~((`WRITE_CE_CYCLE) || (`READ_CE_CYCLE ));
 
always @(posedge clk_200)
sram_adv_ld_l <= 0;
//sram_adv_ld_l <= ~((`WRITE_CE_CYCLE) || (`READ_CE_CYCLE ));
 
always @(posedge clk_200)
sram_we_l <= ~(`WRITE_CE_CYCLE);
 
always @(posedge clk_200)
if (`REG_FROM_BUS_DOMAIN)
sram_addr[21:1] <= wb_adr_i[22:2];
 
always @(posedge clk_200)
if (`REG_FROM_BUS_DOMAIN)
sram_dq_o <= wb_dat_i;
always @(posedge clk_200)
if (`REG_FROM_BUS_DOMAIN)
sram_bw_l <= ~we;
always @(posedge clk_200)
sram_oe_l <= ~((`READ_OE_CYCLE) & !(|(we_r | we)));
 
always @(posedge clk_200)
ssram_controller_oe_l = ~((`WRITE_OE_CYCLE) & (|we_r));
// Register data from SSRAM
always @(posedge clk_200)
if (`RAM_DATA_SAMPLE_CYCLE)
data_rd[31:0] <= sram_dq_i[31:0];
 
assign wb_dat_o = data_rd;
// Determine if we've got a request
// This logic means the bus' control signals are slightly
// more constrained than the data and address.
always @(posedge clk_200)
begin
if (|clk_200_cycle_counter)
clk_200_cycle_counter <= clk_200_cycle_counter - 1;
else if (`REQ_CHECK_CYCLE)
if (wb_cyc_i & wb_stb_i)
clk_200_cycle_counter <= wb_we_i ?
`WRITE_CYCLES : `READ_CYCLES;
else
clk_200_cycle_counter <= 0;
end // always @ (posedge clk_200)
 
always @(posedge clk_200)
begin
reg_from_bus_domain <= ((`REQ_CHECK_CYCLE) & wb_cyc_i & wb_stb_i & !(|clk_200_cycle_counter));
reg_from_bus_domain_r <= reg_from_bus_domain;
end
 
// Must clear
always @(posedge clk_200)
if (`REG_FROM_BUS_DOMAIN)
we_r <= we;
else if (!(|clk_200_cycle_counter))
we_r <= 0;
/* SSRAM Clocking configuration */
 
/* DCM de-skewing SSRAM clock via external trace */
DCM_BASE dcm0
(/*AUTOINST*/
// Outputs
.CLK0 (dcm0_clk0_prebufg),
.CLK180 (),
.CLK270 (),
.CLK2X180 (),
.CLK2X (),
.CLK90 (),
.CLKDV (),
.CLKFX180 (),
.CLKFX (),
.LOCKED (dcm0_locked),
// Inputs
.CLKFB (sram_clk_fb),
.CLKIN (clk_200),
.RST (wb_rst));
BUFG dcm0_clk0_bufg
(// Outputs
.O (dcm0_clk0),
// Inputs
.I (dcm0_clk0_prebufg));
 
/* Generate the DQ bus tristate buffers */
genvar i;
generate
for (i=0; i<32; i=i+1) begin: SSRAM_DQ_TRISTATE
IOBUF U (.O(sram_dq_i[i]),
.IO(sram_dq_io[i]),
.I(sram_dq_o[i]),
.T(ssram_controller_oe_l));
end
endgenerate
endmodule // xilinx_ssram
 
// Local Variables:
// verilog-library-directories:(".")
// verilog-library-extensions:(".v" ".h")
// End:
/verilog/clkgen/clkgen.v
0,0 → 1,205
/*
*
* Clock, reset generation unit for ML501 board
*
* Implements clock generation according to design defines
*
*/
//////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2009, 2010 Authors and OPENCORES.ORG ////
//// ////
//// This source file may be used and distributed without ////
//// restriction provided that this copyright statement is not ////
//// removed from the file and that any derivative work contains ////
//// the original copyright notice and the associated disclaimer. ////
//// ////
//// This source file is free software; you can redistribute it ////
//// and/or modify it under the terms of the GNU Lesser General ////
//// Public License as published by the Free Software Foundation; ////
//// either version 2.1 of the License, or (at your option) any ////
//// later version. ////
//// ////
//// This source is distributed in the hope that it will be ////
//// useful, but WITHOUT ANY WARRANTY; without even the implied ////
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ////
//// PURPOSE. See the GNU Lesser General Public License for more ////
//// details. ////
//// ////
//// You should have received a copy of the GNU Lesser General ////
//// Public License along with this source; if not, download it ////
//// from http://www.opencores.org/lgpl.shtml ////
//// ////
//////////////////////////////////////////////////////////////////////
 
`include "orpsoc-defines.v"
`include "synthesis-defines.v"
 
module clkgen
(
// Main clocks in, depending on board
sys_clk_in_p, sys_clk_in_n,
 
// Wishbone clock and reset out
wb_clk_o,
wb_rst_o,
 
// JTAG clock
`ifdef JTAG_DEBUG
tck_pad_i,
dbg_tck_o,
`endif
// Main memory clocks
`ifdef XILINX_DDR2
ddr2_if_clk_o,
ddr2_if_rst_o,
clk200_o,
`endif
 
// Asynchronous, active low reset in
rst_n_pad_i
);
 
input sys_clk_in_p,sys_clk_in_n;
 
output wb_rst_o;
output wb_clk_o;
 
`ifdef JTAG_DEBUG
input tck_pad_i;
output dbg_tck_o;
`endif
`ifdef XILINX_DDR2
output ddr2_if_clk_o;
output ddr2_if_rst_o;
output clk200_o;
`endif
 
// Asynchronous, active low reset (pushbutton, typically)
input rst_n_pad_i;
// First, deal with the asychronous reset
wire async_rst;
wire async_rst_n;
 
// Xilinx synthesis tools appear cluey enough to instantiate buffers when and
// where they're needed, so we do simple assigns for this tech.
assign async_rst_n = rst_n_pad_i;
 
// Everyone likes active-high reset signals...
assign async_rst = ~async_rst_n;
`ifdef JTAG_DEBUG
assign dbg_tck_o = tck_pad_i;
`endif
 
//
// Declare synchronous reset wires here
//
// An active-low synchronous reset signal (usually a PLL lock signal)
wire sync_rst_n;
 
// An active-low synchronous reset from ethernet PLL
wire sync_eth_rst_n;
wire sys_clk_in_200;
/* DCM0 wires */
wire dcm0_clk0_prebufg, dcm0_clk0;
wire dcm0_clkfx_prebufg, dcm0_clkfx;
wire dcm0_clkdv_prebufg, dcm0_clkdv;
wire dcm0_locked;
 
/* Dif. input buffer for 200MHz board clock, generate SE 200MHz */
IBUFGDS_LVPECL_25 sys_clk_in_ibufds
(
.O(sys_clk_in_200),
.I(sys_clk_in_p),
.IB(sys_clk_in_n));
/* DCM providing main system/Wishbone clock */
DCM_BASE dcm0
(
// Outputs
.CLK0 (dcm0_clk0_prebufg),
.CLK180 (),
.CLK270 (),
.CLK2X180 (),
.CLK2X (),
.CLK90 (),
.CLKDV (dcm0_clkdv_prebufg),
.CLKFX180 (),
.CLKFX (dcm0_clkfx_prebufg),
.LOCKED (dcm0_locked),
// Inputs
.CLKFB (dcm0_clk0),
.CLKIN (sys_clk_in_200),
.RST (1'b0));
// Generate 266 MHz from CLKFX
defparam dcm0.CLKFX_MULTIPLY = 4;
defparam dcm0.CLKFX_DIVIDE = 3;
 
// Generate 50 MHz from CLKDV
defparam dcm0.CLKDV_DIVIDE = 4.0;
 
BUFG dcm0_clk0_bufg
(// Outputs
.O (dcm0_clk0),
// Inputs
.I (dcm0_clk0_prebufg));
 
BUFG dcm0_clkfx_bufg
(// Outputs
.O (dcm0_clkfx),
// Inputs
.I (dcm0_clkfx_prebufg));
 
BUFG dcm0_clkdv_bufg
(// Outputs
.O (dcm0_clkdv),
// Inputs
.I (dcm0_clkdv_prebufg));
 
assign wb_clk_o = dcm0_clkdv;
assign sync_rst_n = dcm0_locked;
 
`ifdef XILINX_DDR2
assign ddr2_if_clk_o = dcm0_clkfx; // 266MHz
assign clk200_o = dcm0_clk0; // 200MHz
`endif
//
// Reset generation
//
//
 
// Reset generation for wishbone
reg [15:0] wb_rst_shr;
always @(posedge wb_clk_o or posedge async_rst)
if (async_rst)
wb_rst_shr <= 16'hffff;
else
wb_rst_shr <= {wb_rst_shr[14:0], ~(sync_rst_n)};
assign wb_rst_o = wb_rst_shr[15];
 
`ifdef XILINX_DDR2
// Reset generation for DDR2 controller
reg [15:0] ddr2_if_rst_shr;
always @(posedge ddr2_if_clk_o or posedge async_rst)
if (async_rst)
ddr2_if_rst_shr <= 16'hffff;
else
ddr2_if_rst_shr <= {ddr2_if_rst_shr[14:0], ~(sync_rst_n)};
assign ddr2_if_rst_o = ddr2_if_rst_shr[15];
`endif
endmodule // clkgen
/verilog/include/ethmac_defines.v
0,0 → 1,255
//////////////////////////////////////////////////////////////////////
//// ////
//// eth_defines.v ////
//// ////
//// This file is part of the Ethernet IP core project ////
//// http://opencores.org/project,ethmac ////
//// ////
//// Author(s): ////
//// - Igor Mohor (igorM@opencores.org) ////
//// ////
//// Modified by: ////
//// - Julius Baxter (julius@opencores.org) ////
//// ////
//////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2001, 2002 Authors ////
//// ////
//// This source file may be used and distributed without ////
//// restriction provided that this copyright statement is not ////
//// removed from the file and that any derivative work contains ////
//// the original copyright notice and the associated disclaimer. ////
//// ////
//// This source file is free software; you can redistribute it ////
//// and/or modify it under the terms of the GNU Lesser General ////
//// Public License as published by the Free Software Foundation; ////
//// either version 2.1 of the License, or (at your option) any ////
//// later version. ////
//// ////
//// This source is distributed in the hope that it will be ////
//// useful, but WITHOUT ANY WARRANTY; without even the implied ////
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ////
//// PURPOSE. See the GNU Lesser General Public License for more ////
//// details. ////
//// ////
//// You should have received a copy of the GNU Lesser General ////
//// Public License along with this source; if not, download it ////
//// from http://www.opencores.org/lgpl.shtml ////
//// ////
//////////////////////////////////////////////////////////////////////
 
 
 
//`define ETH_BIST // Bist for usage with Virtual Silicon RAMS
 
`define ETH_MBIST_CTRL_WIDTH 3 // width of MBIST control bus
 
// Generic FIFO implementation - hopefully synthesizable with Synplify
`define ETH_FIFO_GENERIC
// Ethernet implemented in Xilinx Chips (uncomment following lines)
// `define ETH_FIFO_XILINX // Use Xilinx distributed ram for tx and rx fifo
// `define ETH_XILINX_RAMB4 // Selection of the used memory for Buffer descriptors
// Core is going to be implemented in Virtex FPGA and contains Virtex
// specific elements.
 
// Ethernet implemented in Altera Chips (uncomment following lines)
//`define ETH_ALTERA_ALTSYNCRAM
 
// Ethernet implemented in ASIC with Virtual Silicon RAMs
// `define ETH_VIRTUAL_SILICON_RAM // Virtual Silicon RAMS used storing buffer decriptors (ASIC implementation)
 
// Ethernet implemented in ASIC with Artisan RAMs
// `define ETH_ARTISAN_RAM // Artisan RAMS used storing buffer decriptors (ASIC implementation)
 
// Uncomment when Avalon bus is used
//`define ETH_AVALON_BUS
 
`define ETH_MODER_ADR 8'h0 // 0x0
`define ETH_INT_SOURCE_ADR 8'h1 // 0x4
`define ETH_INT_MASK_ADR 8'h2 // 0x8
`define ETH_IPGT_ADR 8'h3 // 0xC
`define ETH_IPGR1_ADR 8'h4 // 0x10
`define ETH_IPGR2_ADR 8'h5 // 0x14
`define ETH_PACKETLEN_ADR 8'h6 // 0x18
`define ETH_COLLCONF_ADR 8'h7 // 0x1C
`define ETH_TX_BD_NUM_ADR 8'h8 // 0x20
`define ETH_CTRLMODER_ADR 8'h9 // 0x24
`define ETH_MIIMODER_ADR 8'hA // 0x28
`define ETH_MIICOMMAND_ADR 8'hB // 0x2C
`define ETH_MIIADDRESS_ADR 8'hC // 0x30
`define ETH_MIITX_DATA_ADR 8'hD // 0x34
`define ETH_MIIRX_DATA_ADR 8'hE // 0x38
`define ETH_MIISTATUS_ADR 8'hF // 0x3C
`define ETH_MAC_ADDR0_ADR 8'h10 // 0x40
`define ETH_MAC_ADDR1_ADR 8'h11 // 0x44
`define ETH_HASH0_ADR 8'h12 // 0x48
`define ETH_HASH1_ADR 8'h13 // 0x4C
`define ETH_TX_CTRL_ADR 8'h14 // 0x50
`define ETH_RX_CTRL_ADR 8'h15 // 0x54
`define ETH_DBG_ADR 8'h16 // 0x58
 
 
`define ETH_MODER_DEF_0 8'h00
`define ETH_MODER_DEF_1 8'hA0
`define ETH_MODER_DEF_2 1'h0
`define ETH_INT_MASK_DEF_0 7'h0
`define ETH_IPGT_DEF_0 7'h12
`define ETH_IPGR1_DEF_0 7'h0C
`define ETH_IPGR2_DEF_0 7'h12
`define ETH_PACKETLEN_DEF_0 8'h00
`define ETH_PACKETLEN_DEF_1 8'h06
`define ETH_PACKETLEN_DEF_2 8'h40
`define ETH_PACKETLEN_DEF_3 8'h00
`define ETH_COLLCONF_DEF_0 6'h3f
`define ETH_COLLCONF_DEF_2 4'hF
`define ETH_TX_BD_NUM_DEF_0 8'h40
`define ETH_CTRLMODER_DEF_0 3'h0
`define ETH_MIIMODER_DEF_0 8'h64
`define ETH_MIIMODER_DEF_1 1'h0
`define ETH_MIIADDRESS_DEF_0 5'h00
`define ETH_MIIADDRESS_DEF_1 5'h00
`define ETH_MIITX_DATA_DEF_0 8'h00
`define ETH_MIITX_DATA_DEF_1 8'h00
`define ETH_MIIRX_DATA_DEF 16'h0000 // not written from WB
`define ETH_MAC_ADDR0_DEF_0 8'h00
`define ETH_MAC_ADDR0_DEF_1 8'h00
`define ETH_MAC_ADDR0_DEF_2 8'h00
`define ETH_MAC_ADDR0_DEF_3 8'h00
`define ETH_MAC_ADDR1_DEF_0 8'h00
`define ETH_MAC_ADDR1_DEF_1 8'h00
`define ETH_HASH0_DEF_0 8'h00
`define ETH_HASH0_DEF_1 8'h00
`define ETH_HASH0_DEF_2 8'h00
`define ETH_HASH0_DEF_3 8'h00
`define ETH_HASH1_DEF_0 8'h00
`define ETH_HASH1_DEF_1 8'h00
`define ETH_HASH1_DEF_2 8'h00
`define ETH_HASH1_DEF_3 8'h00
`define ETH_TX_CTRL_DEF_0 8'h00 //
`define ETH_TX_CTRL_DEF_1 8'h00 //
`define ETH_TX_CTRL_DEF_2 1'h0 //
`define ETH_RX_CTRL_DEF_0 8'h00
`define ETH_RX_CTRL_DEF_1 8'h00
 
 
`define ETH_MODER_WIDTH_0 8
`define ETH_MODER_WIDTH_1 8
`define ETH_MODER_WIDTH_2 1
`define ETH_INT_SOURCE_WIDTH_0 7
`define ETH_INT_MASK_WIDTH_0 7
`define ETH_IPGT_WIDTH_0 7
`define ETH_IPGR1_WIDTH_0 7
`define ETH_IPGR2_WIDTH_0 7
`define ETH_PACKETLEN_WIDTH_0 8
`define ETH_PACKETLEN_WIDTH_1 8
`define ETH_PACKETLEN_WIDTH_2 8
`define ETH_PACKETLEN_WIDTH_3 8
`define ETH_COLLCONF_WIDTH_0 6
`define ETH_COLLCONF_WIDTH_2 4
`define ETH_TX_BD_NUM_WIDTH_0 8
`define ETH_CTRLMODER_WIDTH_0 3
`define ETH_MIIMODER_WIDTH_0 8
`define ETH_MIIMODER_WIDTH_1 1
`define ETH_MIICOMMAND_WIDTH_0 3
`define ETH_MIIADDRESS_WIDTH_0 5
`define ETH_MIIADDRESS_WIDTH_1 5
`define ETH_MIITX_DATA_WIDTH_0 8
`define ETH_MIITX_DATA_WIDTH_1 8
`define ETH_MIIRX_DATA_WIDTH 16 // not written from WB
`define ETH_MIISTATUS_WIDTH 3 // not written from WB
`define ETH_MAC_ADDR0_WIDTH_0 8
`define ETH_MAC_ADDR0_WIDTH_1 8
`define ETH_MAC_ADDR0_WIDTH_2 8
`define ETH_MAC_ADDR0_WIDTH_3 8
`define ETH_MAC_ADDR1_WIDTH_0 8
`define ETH_MAC_ADDR1_WIDTH_1 8
`define ETH_HASH0_WIDTH_0 8
`define ETH_HASH0_WIDTH_1 8
`define ETH_HASH0_WIDTH_2 8
`define ETH_HASH0_WIDTH_3 8
`define ETH_HASH1_WIDTH_0 8
`define ETH_HASH1_WIDTH_1 8
`define ETH_HASH1_WIDTH_2 8
`define ETH_HASH1_WIDTH_3 8
`define ETH_TX_CTRL_WIDTH_0 8
`define ETH_TX_CTRL_WIDTH_1 8
`define ETH_TX_CTRL_WIDTH_2 1
`define ETH_RX_CTRL_WIDTH_0 8
`define ETH_RX_CTRL_WIDTH_1 8
 
 
// Outputs are registered (uncomment when needed)
`define ETH_REGISTERED_OUTPUTS
 
// Settings for TX FIFO
`define ETH_TX_FIFO_DATA_WIDTH 32
 
// Defines for ethernet TX fifo size - impacts FPGA resource usage
//`define ETH_TX_FULL_PACKET_FIFO // Full 1500 byte TX buffer - uncomment this
//`define ETH_TX_256BYTE_FIFO // 256 byte TX buffer - uncomment this
//`define ETH_TX_512BYTE_FIFO // 512 byte TX buffer - uncomment this
`define ETH_TX_1KBYTE_FIFO // 1024 byte TX buffer - uncomment this
 
`ifdef ETH_TX_FULL_PACKET_FIFO
`define ETH_TX_FIFO_CNT_WIDTH 11
`define ETH_TX_FIFO_DEPTH 375
`else
`ifdef ETH_TX_1KBYTE_FIFO
`define ETH_TX_FIFO_CNT_WIDTH 9
`define ETH_TX_FIFO_DEPTH 256
`else
`ifdef ETH_TX_512BYTE_FIFO
`define ETH_TX_FIFO_CNT_WIDTH 8
`define ETH_TX_FIFO_DEPTH 128
`else
`ifdef ETH_TX_256BYTE_FIFO
`define ETH_TX_FIFO_CNT_WIDTH 7
`define ETH_TX_FIFO_DEPTH 64
`else
// Default is 64 bytes
`define ETH_TX_FIFO_CNT_WIDTH 5
`define ETH_TX_FIFO_DEPTH 16
`endif
`endif
`endif // !`ifdef ETH_TX_512BYTE_FIFO
`endif // !`ifdef ETH_TX_FULL_PACKET_FIFO
 
 
 
// Settings for RX FIFO
`define ETH_RX_FIFO_CNT_WIDTH 9
`define ETH_RX_FIFO_DEPTH 256
//`define ETH_RX_FIFO_CNT_WIDTH 8
//`define ETH_RX_FIFO_DEPTH 128
//`define ETH_RX_FIFO_CNT_WIDTH 7
//`define ETH_RX_FIFO_DEPTH 64
//`define ETH_RX_FIFO_CNT_WIDTH 6
//`define ETH_RX_FIFO_DEPTH 32
//`define ETH_RX_FIFO_CNT_WIDTH 5
//`define ETH_RX_FIFO_DEPTH 16
 
`define ETH_RX_FIFO_DATA_WIDTH 32
 
// Burst length
`define BURST_4BEAT
`ifdef BURST_4BEAT
`define ETH_BURST_LENGTH 4 // Change also ETH_BURST_CNT_WIDTH
`define ETH_BURST_CNT_WIDTH 3 // The counter must be width enough to count to ETH_BURST_LENGTH
`endif
 
//`define ETH_BURST_LENGTH 32 // Change also ETH_BURST_CNT_WIDTH
//`define ETH_BURST_CNT_WIDTH 7 // The counter must be width enough to count to ETH_BURST_LENGTH
 
// Undefine this to enable bursting for RX (writing to memory)
`define ETH_RX_BURST_EN
 
 
// WISHBONE interface is Revision B3 compliant (uncomment when needed)
`define ETH_WISHBONE_B3
 
// Hack where the transmit logic polls each of the TX buffers instead of having to keep track of what's going on
//`define TXBD_POLL
 
// Define this to allow reading of the Wishbone control state machine on reg
// address 0x58
`define WISHBONE_DEBUG
/verilog/include/i2c_master_slave_defines.v
0,0 → 1,66
/////////////////////////////////////////////////////////////////////
//// ////
//// WISHBONE rev.B2 compliant I2C Master controller defines ////
//// ////
//// ////
//// Author: Richard Herveille ////
//// richard@asics.ws ////
//// www.asics.ws ////
//// ////
//// Downloaded from: http://www.opencores.org/projects/i2c/ ////
//// ////
/////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2001 Richard Herveille ////
//// richard@asics.ws ////
//// ////
//// This source file may be used and distributed without ////
//// restriction provided that this copyright statement is not ////
//// removed from the file and that any derivative work contains ////
//// the original copyright notice and the associated disclaimer.////
//// ////
//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY ////
//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED ////
//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS ////
//// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR ////
//// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, ////
//// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ////
//// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE ////
//// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR ////
//// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF ////
//// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ////
//// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT ////
//// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ////
//// POSSIBILITY OF SUCH DAMAGE. ////
//// ////
/////////////////////////////////////////////////////////////////////
 
// CVS Log
//
// $Id: i2c_master_defines.v,v 1.3 2001-11-05 11:59:25 rherveille Exp $
//
// $Date: 2001-11-05 11:59:25 $
// $Revision: 1.3 $
// $Author: rherveille $
// $Locker: $
// $State: Exp $
//
// Change History:
// $Log: not supported by cvs2svn $
 
 
// I2C registers wishbone addresses
 
// bitcontroller states
`define I2C_CMD_NOP 4'b0000
`define I2C_CMD_START 4'b0001
`define I2C_CMD_STOP 4'b0010
`define I2C_CMD_WRITE 4'b0100
`define I2C_CMD_READ 4'b1000
 
`define I2C_SLAVE_CMD_WRITE 2'b01
`define I2C_SLAVE_CMD_READ 2'b10
`define I2C_SLAVE_CMD_NOP 2'b00
 
 
 
/verilog/include/dbg_cpu_defines.v
0,0 → 1,85
//////////////////////////////////////////////////////////////////////
//// ////
//// dbg_cpu_defines.v ////
//// ////
//// ////
//// This file is part of the SoC Debug Interface. ////
//// http://www.opencores.org/projects/DebugInterface/ ////
//// ////
//// Author(s): ////
//// Igor Mohor (igorm@opencores.org) ////
//// ////
//// ////
//// All additional information is avaliable in the README.txt ////
//// file. ////
//// ////
//////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2000 - 2004 Authors ////
//// ////
//// This source file may be used and distributed without ////
//// restriction provided that this copyright statement is not ////
//// removed from the file and that any derivative work contains ////
//// the original copyright notice and the associated disclaimer. ////
//// ////
//// This source file is free software; you can redistribute it ////
//// and/or modify it under the terms of the GNU Lesser General ////
//// Public License as published by the Free Software Foundation; ////
//// either version 2.1 of the License, or (at your option) any ////
//// later version. ////
//// ////
//// This source is distributed in the hope that it will be ////
//// useful, but WITHOUT ANY WARRANTY; without even the implied ////
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ////
//// PURPOSE. See the GNU Lesser General Public License for more ////
//// details. ////
//// ////
//// You should have received a copy of the GNU Lesser General ////
//// Public License along with this source; if not, download it ////
//// from http://www.opencores.org/lgpl.shtml ////
//// ////
//////////////////////////////////////////////////////////////////////
 
// Defining length of the command
`define DBG_CPU_CMD_LEN 3'd4
`define DBG_CPU_CMD_CNT_WIDTH 3
 
// Defining length of the access_type field
`define DBG_CPU_ACC_TYPE_LEN 4
 
// Defining length of the address
`define DBG_CPU_ADR_LEN 32
 
// Defining length of the length register
`define DBG_CPU_LEN_LEN 16
 
// Defining total length of the DR needed
`define DBG_CPU_DR_LEN (`DBG_CPU_ACC_TYPE_LEN + `DBG_CPU_ADR_LEN + `DBG_CPU_LEN_LEN)
// Defining length of the CRC
`define DBG_CPU_CRC_LEN 6'd32
`define DBG_CPU_CRC_CNT_WIDTH 6
 
// Defining length of status
`define DBG_CPU_STATUS_LEN 3'd4
`define DBG_CPU_STATUS_CNT_WIDTH 3
 
// Defining length of the data
//define DBG_CPU_DATA_CNT_WIDTH `DBG_CPU_LEN_LEN + 3
`define DBG_CPU_DATA_CNT_WIDTH 19
//define DBG_CPU_DATA_CNT_LIM_WIDTH `DBG_CPU_LEN_LEN
`define DBG_CPU_DATA_CNT_LIM_WIDTH 16
// Defining length of the control register
`define DBG_CPU_CTRL_LEN 2
 
//Defining commands
`define DBG_CPU_GO 4'h0
`define DBG_CPU_RD_COMM 4'h1
`define DBG_CPU_WR_COMM 4'h2
`define DBG_CPU_RD_CTRL 4'h3
`define DBG_CPU_WR_CTRL 4'h4
 
// Defining access types for wishbone
`define DBG_CPU_WRITE 4'h2
`define DBG_CPU_READ 4'h6
 
 
/verilog/include/or1200_defines.v
0,0 → 1,1732
//////////////////////////////////////////////////////////////////////
//// ////
//// OR1200's definitions ////
//// ////
//// This file is part of the OpenRISC 1200 project ////
//// http://opencores.org/project,or1k ////
//// ////
//// Description ////
//// Defines for the OR1200 core ////
//// ////
//// To Do: ////
//// - add parameters that are missing ////
//// ////
//// Author(s): ////
//// - Damjan Lampret, lampret@opencores.org ////
//// ////
//////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2000 Authors and OPENCORES.ORG ////
//// ////
//// This source file may be used and distributed without ////
//// restriction provided that this copyright statement is not ////
//// removed from the file and that any derivative work contains ////
//// the original copyright notice and the associated disclaimer. ////
//// ////
//// This source file is free software; you can redistribute it ////
//// and/or modify it under the terms of the GNU Lesser General ////
//// Public License as published by the Free Software Foundation; ////
//// either version 2.1 of the License, or (at your option) any ////
//// later version. ////
//// ////
//// This source is distributed in the hope that it will be ////
//// useful, but WITHOUT ANY WARRANTY; without even the implied ////
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ////
//// PURPOSE. See the GNU Lesser General Public License for more ////
//// details. ////
//// ////
//// You should have received a copy of the GNU Lesser General ////
//// Public License along with this source; if not, download it ////
//// from http://www.opencores.org/lgpl.shtml ////
//// ////
//////////////////////////////////////////////////////////////////////
//
// $Log: or1200_defines.v,v $
// Revision 2.0 2010/06/30 11:00:00 ORSoC
// Minor update:
// Defines added, bugs fixed.
 
//
// Dump VCD
//
//`define OR1200_VCD_DUMP
 
//
// Generate debug messages during simulation
//
//`define OR1200_VERBOSE
 
// `define OR1200_ASIC
////////////////////////////////////////////////////////
//
// Typical configuration for an ASIC
//
`ifdef OR1200_ASIC
 
//
// Target ASIC memories
//
//`define OR1200_ARTISAN_SSP
//`define OR1200_ARTISAN_SDP
//`define OR1200_ARTISAN_STP
`define OR1200_VIRTUALSILICON_SSP
//`define OR1200_VIRTUALSILICON_STP_T1
//`define OR1200_VIRTUALSILICON_STP_T2
 
//
// Do not implement Data cache
//
//`define OR1200_NO_DC
 
//
// Do not implement Insn cache
//
//`define OR1200_NO_IC
 
//
// Do not implement Data MMU
//
//`define OR1200_NO_DMMU
 
//
// Do not implement Insn MMU
//
//`define OR1200_NO_IMMU
 
//
// Select between ASIC optimized and generic multiplier
//
//`define OR1200_ASIC_MULTP2_32X32
`define OR1200_GENERIC_MULTP2_32X32
 
//
// Size/type of insn/data cache if implemented
//
// `define OR1200_IC_1W_512B
// `define OR1200_IC_1W_4KB
`define OR1200_IC_1W_8KB
// `define OR1200_DC_1W_4KB
`define OR1200_DC_1W_8KB
 
`else
 
 
/////////////////////////////////////////////////////////
//
// Typical configuration for an FPGA
//
 
//
// Target FPGA memories
//
//`define OR1200_ALTERA_LPM
//`define OR1200_XILINX_RAMB16
//`define OR1200_XILINX_RAMB4
//`define OR1200_XILINX_RAM32X1D
//`define OR1200_USE_RAM16X1D_FOR_RAM32X1D
// Generic models should infer RAM blocks at synthesis time (not only effects
// single port ram.)
`define OR1200_GENERIC
 
//
// Do not implement Data cache
//
//`define OR1200_NO_DC
 
//
// Do not implement Insn cache
//
//`define OR1200_NO_IC
 
//
// Do not implement Data MMU
//
//`define OR1200_NO_DMMU
 
//
// Do not implement Insn MMU
//
//`define OR1200_NO_IMMU
 
//
// Select between ASIC and generic multiplier
//
// (Generic seems to trigger a bug in the Cadence Ncsim simulator)
//
//`define OR1200_ASIC_MULTP2_32X32
`define OR1200_GENERIC_MULTP2_32X32
 
//
// Size/type of insn/data cache if implemented
// (consider available FPGA memory resources)
//
//`define OR1200_IC_1W_512B
//`define OR1200_IC_1W_4KB
`define OR1200_IC_1W_8KB
//`define OR1200_DC_1W_4KB
`define OR1200_DC_1W_8KB
 
`endif
 
 
//////////////////////////////////////////////////////////
//
// Do not change below unless you know what you are doing
//
 
//
// Reset active low
//
//`define OR1200_RST_ACT_LOW
 
//
// Enable RAM BIST
//
// At the moment this only works for Virtual Silicon
// single port RAMs. For other RAMs it has not effect.
// Special wrapper for VS RAMs needs to be provided
// with scan flops to facilitate bist scan.
//
//`define OR1200_BIST
 
//
// Register OR1200 WISHBONE outputs
// (must be defined/enabled)
//
`define OR1200_REGISTERED_OUTPUTS
 
//
// Register OR1200 WISHBONE inputs
//
// (must be undefined/disabled)
//
//`define OR1200_REGISTERED_INPUTS
 
//
// Disable bursts if they are not supported by the
// memory subsystem (only affect cache line fill)
//
//`define OR1200_NO_BURSTS
//
 
//
// WISHBONE retry counter range
//
// 2^value range for retry counter. Retry counter
// is activated whenever *wb_rty_i is asserted and
// until retry counter expires, corresponding
// WISHBONE interface is deactivated.
//
// To disable retry counters and *wb_rty_i all together,
// undefine this macro.
//
//`define OR1200_WB_RETRY 7
 
//
// WISHBONE Consecutive Address Burst
//
// This was used prior to WISHBONE B3 specification
// to identify bursts. It is no longer needed but
// remains enabled for compatibility with old designs.
//
// To remove *wb_cab_o ports undefine this macro.
//
//`define OR1200_WB_CAB
 
//
// WISHBONE B3 compatible interface
//
// This follows the WISHBONE B3 specification.
// It is not enabled by default because most
// designs still don't use WB b3.
//
// To enable *wb_cti_o/*wb_bte_o ports,
// define this macro.
//
`define OR1200_WB_B3
 
//
// LOG all WISHBONE accesses
//
`define OR1200_LOG_WB_ACCESS
 
//
// Enable additional synthesis directives if using
// _Synopsys_ synthesis tool
//
//`define OR1200_ADDITIONAL_SYNOPSYS_DIRECTIVES
 
//
// Enables default statement in some case blocks
// and disables Synopsys synthesis directive full_case
//
// By default it is enabled. When disabled it
// can increase clock frequency.
//
`define OR1200_CASE_DEFAULT
 
//
// Operand width / register file address width
//
// (DO NOT CHANGE)
//
`define OR1200_OPERAND_WIDTH 32
`define OR1200_REGFILE_ADDR_WIDTH 5
 
//
// l.add/l.addi/l.and and optional l.addc/l.addic
// also set (compare) flag when result of their
// operation equals zero
//
// At the time of writing this, default or32
// C/C++ compiler doesn't generate code that
// would benefit from this optimization.
//
// By default this optimization is disabled to
// save area.
//
//`define OR1200_ADDITIONAL_FLAG_MODIFIERS
 
//
// Implement l.addc/l.addic instructions
//
// By default implementation of l.addc/l.addic
// instructions is enabled in case you need them.
// If you don't use them, then disable implementation
// to save area.
//
//`define OR1200_IMPL_ADDC
 
//
// Implement l.sub instruction
//
// By default implementation of l.sub instructions
// is enabled to be compliant with the simulator.
// If you don't use carry bit, then disable
// implementation to save area.
//
`define OR1200_IMPL_SUB
 
//
// Implement carry bit SR[CY]
//
//
// By default implementation of SR[CY] is enabled
// to be compliant with the simulator. However SR[CY]
// is explicitly only used by l.addc/l.addic/l.sub
// instructions and if these three insns are not
// implemented there is not much point having SR[CY].
//
//`define OR1200_IMPL_CY
 
//
// Implement rotate in the ALU
//
// At the time of writing this, or32
// C/C++ compiler doesn't generate rotate
// instructions. However or32 assembler
// can assemble code that uses rotate insn.
// This means that rotate instructions
// must be used manually inserted.
//
// By default implementation of rotate
// is disabled to save area and increase
// clock frequency.
//
//`define OR1200_IMPL_ALU_ROTATE
 
//
// Type of ALU compare to implement
//
// Try either one to find what yields
// higher clock frequencyin your case.
//
//`define OR1200_IMPL_ALU_COMP1
`define OR1200_IMPL_ALU_COMP2
 
//
// Implement Find First/Last '1'
//
`define OR1200_IMPL_ALU_FFL1
 
//
// Implement multiplier
//
// By default multiplier is implemented
//
`define OR1200_MULT_IMPLEMENTED
 
//
// Implement multiply-and-accumulate
//
// By default MAC is implemented. To
// implement MAC, multiplier needs to be
// implemented.
//
`define OR1200_MAC_IMPLEMENTED
 
//
// Implement optional l.div/l.divu instructions
//
// By default divide instructions are not implemented
// to save area and increase clock frequency. or32 C/C++
// compiler can use soft library for division.
//
// To implement divide, both multiplier and MAC needs to be implemented.
//
`define OR1200_DIV_IMPLEMENTED
 
//
// Low power, slower multiplier
//
// Select between low-power (larger) multiplier
// and faster multiplier. The actual difference
// is only AND logic that prevents distribution
// of operands into the multiplier when instruction
// in execution is not multiply instruction
//
//`define OR1200_LOWPWR_MULT
 
//
// Implement HW Single Precision FPU
//
`define OR1200_FPU_IMPLEMENTED
 
 
//
// Clock ratio RISC clock versus WB clock
//
// If you plan to run WB:RISC clock fixed to 1:1, disable
// both defines
//
// For WB:RISC 1:2 or 1:1, enable OR1200_CLKDIV_2_SUPPORTED
// and use clmode to set ratio
//
// For WB:RISC 1:4, 1:2 or 1:1, enable both defines and use
// clmode to set ratio
//
//`define OR1200_CLKDIV_2_SUPPORTED
//`define OR1200_CLKDIV_4_SUPPORTED
 
//
// Type of register file RAM
//
// Memory macro w/ two ports (see or1200_tpram_32x32.v)
//`define OR1200_RFRAM_TWOPORT
//
// Memory macro dual port (see or1200_dpram.v)
`define OR1200_RFRAM_DUALPORT
 
//
// Generic (flip-flop based) register file (see or1200_rfram_generic.v)
//`define OR1200_RFRAM_GENERIC
// Generic register file supports - 16 registers
`ifdef OR1200_RFRAM_GENERIC
// `define OR1200_RFRAM_16REG
`endif
 
//
// Type of mem2reg aligner to implement.
//
// Once OR1200_IMPL_MEM2REG2 yielded faster
// circuit, however with today tools it will
// most probably give you slower circuit.
//
`define OR1200_IMPL_MEM2REG1
//`define OR1200_IMPL_MEM2REG2
 
//
// Reset value and event
//
`ifdef OR1200_RST_ACT_LOW
`define OR1200_RST_VALUE (1'b0)
`define OR1200_RST_EVENT negedge
`else
`define OR1200_RST_VALUE (1'b1)
`define OR1200_RST_EVENT posedge
`endif
 
//
// ALUOPs
//
`define OR1200_ALUOP_WIDTH 4
`define OR1200_ALUOP_NOP 4'd4
/* Order defined by arith insns that have two source operands both in regs
(see binutils/include/opcode/or32.h) */
`define OR1200_ALUOP_ADD 4'd0
`define OR1200_ALUOP_ADDC 4'd1
`define OR1200_ALUOP_SUB 4'd2
`define OR1200_ALUOP_AND 4'd3
`define OR1200_ALUOP_OR 4'd4
`define OR1200_ALUOP_XOR 4'd5
`define OR1200_ALUOP_MUL 4'd6
`define OR1200_ALUOP_CUST5 4'd7
`define OR1200_ALUOP_SHROT 4'd8
`define OR1200_ALUOP_DIV 4'd9
`define OR1200_ALUOP_DIVU 4'd10
/* Order not specifically defined. */
`define OR1200_ALUOP_IMM 4'd11
`define OR1200_ALUOP_MOVHI 4'd12
`define OR1200_ALUOP_COMP 4'd13
`define OR1200_ALUOP_MTSR 4'd14
`define OR1200_ALUOP_MFSR 4'd15
`define OR1200_ALUOP_CMOV 4'd14
`define OR1200_ALUOP_FFL1 4'd15
 
 
// ALU instructions second opcode field (previously multicycle field in
// machine word)
`define OR1200_ALUOP2_POS 9:8
`define OR1200_ALUOP2_WIDTH 2
 
 
//
// MACOPs
//
`define OR1200_MACOP_WIDTH 3
`define OR1200_MACOP_NOP 3'b000
`define OR1200_MACOP_MAC 3'b001
`define OR1200_MACOP_MSB 3'b010
 
//
// Shift/rotate ops
//
`define OR1200_SHROTOP_WIDTH 2
`define OR1200_SHROTOP_NOP 2'd0
`define OR1200_SHROTOP_SLL 2'd0
`define OR1200_SHROTOP_SRL 2'd1
`define OR1200_SHROTOP_SRA 2'd2
`define OR1200_SHROTOP_ROR 2'd3
 
// Execution cycles per instruction
`define OR1200_MULTICYCLE_WIDTH 3
`define OR1200_ONE_CYCLE 3'd0
`define OR1200_TWO_CYCLES 3'd1
 
// Execution control which will "wait on" a module to finish
`define OR1200_WAIT_ON_WIDTH 2
`define OR1200_WAIT_ON_FPU `OR1200_WAIT_ON_WIDTH'd1
`define OR1200_WAIT_ON_MTSPR `OR1200_WAIT_ON_WIDTH'd2
 
// Operand MUX selects
`define OR1200_SEL_WIDTH 2
`define OR1200_SEL_RF 2'd0
`define OR1200_SEL_IMM 2'd1
`define OR1200_SEL_EX_FORW 2'd2
`define OR1200_SEL_WB_FORW 2'd3
 
//
// BRANCHOPs
//
`define OR1200_BRANCHOP_WIDTH 3
`define OR1200_BRANCHOP_NOP 3'd0
`define OR1200_BRANCHOP_J 3'd1
`define OR1200_BRANCHOP_JR 3'd2
`define OR1200_BRANCHOP_BAL 3'd3
`define OR1200_BRANCHOP_BF 3'd4
`define OR1200_BRANCHOP_BNF 3'd5
`define OR1200_BRANCHOP_RFE 3'd6
 
//
// LSUOPs
//
// Bit 0: sign extend
// Bits 1-2: 00 doubleword, 01 byte, 10 halfword, 11 singleword
// Bit 3: 0 load, 1 store
`define OR1200_LSUOP_WIDTH 4
`define OR1200_LSUOP_NOP 4'b0000
`define OR1200_LSUOP_LBZ 4'b0010
`define OR1200_LSUOP_LBS 4'b0011
`define OR1200_LSUOP_LHZ 4'b0100
`define OR1200_LSUOP_LHS 4'b0101
`define OR1200_LSUOP_LWZ 4'b0110
`define OR1200_LSUOP_LWS 4'b0111
`define OR1200_LSUOP_LD 4'b0001
`define OR1200_LSUOP_SD 4'b1000
`define OR1200_LSUOP_SB 4'b1010
`define OR1200_LSUOP_SH 4'b1100
`define OR1200_LSUOP_SW 4'b1110
 
// Number of bits of load/store EA precalculated in ID stage
// for balancing ID and EX stages.
//
// Valid range: 2,3,...,30,31
`define OR1200_LSUEA_PRECALC 2
 
// FETCHOPs
`define OR1200_FETCHOP_WIDTH 1
`define OR1200_FETCHOP_NOP 1'b0
`define OR1200_FETCHOP_LW 1'b1
 
//
// Register File Write-Back OPs
//
// Bit 0: register file write enable
// Bits 3-1: write-back mux selects
//
`define OR1200_RFWBOP_WIDTH 4
`define OR1200_RFWBOP_NOP 4'b0000
`define OR1200_RFWBOP_ALU 3'b000
`define OR1200_RFWBOP_LSU 3'b001
`define OR1200_RFWBOP_SPRS 3'b010
`define OR1200_RFWBOP_LR 3'b011
`define OR1200_RFWBOP_FPU 3'b100
 
// Compare instructions
`define OR1200_COP_SFEQ 3'b000
`define OR1200_COP_SFNE 3'b001
`define OR1200_COP_SFGT 3'b010
`define OR1200_COP_SFGE 3'b011
`define OR1200_COP_SFLT 3'b100
`define OR1200_COP_SFLE 3'b101
`define OR1200_COP_X 3'b111
`define OR1200_SIGNED_COMPARE 'd3
`define OR1200_COMPOP_WIDTH 4
 
//
// FP OPs
//
// MSbit indicates FPU operation valid
//
`define OR1200_FPUOP_WIDTH 8
// FPU unit from Usselman takes 5 cycles from decode, so 4 ex. cycles
`define OR1200_FPUOP_CYCLES 3'd4
// FP instruction is double precision if bit 4 is set. We're a 32-bit
// implementation thus do not support double precision FP
`define OR1200_FPUOP_DOUBLE_BIT 4
`define OR1200_FPUOP_ADD 8'b0000_0000
`define OR1200_FPUOP_SUB 8'b0000_0001
`define OR1200_FPUOP_MUL 8'b0000_0010
`define OR1200_FPUOP_DIV 8'b0000_0011
`define OR1200_FPUOP_ITOF 8'b0000_0100
`define OR1200_FPUOP_FTOI 8'b0000_0101
`define OR1200_FPUOP_REM 8'b0000_0110
`define OR1200_FPUOP_RESERVED 8'b0000_0111
// FP Compare instructions
`define OR1200_FPCOP_SFEQ 8'b0000_1000
`define OR1200_FPCOP_SFNE 8'b0000_1001
`define OR1200_FPCOP_SFGT 8'b0000_1010
`define OR1200_FPCOP_SFGE 8'b0000_1011
`define OR1200_FPCOP_SFLT 8'b0000_1100
`define OR1200_FPCOP_SFLE 8'b0000_1101
 
//
// TAGs for instruction bus
//
`define OR1200_ITAG_IDLE 4'h0 // idle bus
`define OR1200_ITAG_NI 4'h1 // normal insn
`define OR1200_ITAG_BE 4'hb // Bus error exception
`define OR1200_ITAG_PE 4'hc // Page fault exception
`define OR1200_ITAG_TE 4'hd // TLB miss exception
 
//
// TAGs for data bus
//
`define OR1200_DTAG_IDLE 4'h0 // idle bus
`define OR1200_DTAG_ND 4'h1 // normal data
`define OR1200_DTAG_AE 4'ha // Alignment exception
`define OR1200_DTAG_BE 4'hb // Bus error exception
`define OR1200_DTAG_PE 4'hc // Page fault exception
`define OR1200_DTAG_TE 4'hd // TLB miss exception
 
 
//////////////////////////////////////////////
//
// ORBIS32 ISA specifics
//
 
// SHROT_OP position in machine word
`define OR1200_SHROTOP_POS 7:6
 
//
// Instruction opcode groups (basic)
//
`define OR1200_OR32_J 6'b000000
`define OR1200_OR32_JAL 6'b000001
`define OR1200_OR32_BNF 6'b000011
`define OR1200_OR32_BF 6'b000100
`define OR1200_OR32_NOP 6'b000101
`define OR1200_OR32_MOVHI 6'b000110
`define OR1200_OR32_XSYNC 6'b001000
`define OR1200_OR32_RFE 6'b001001
/* */
`define OR1200_OR32_JR 6'b010001
`define OR1200_OR32_JALR 6'b010010
`define OR1200_OR32_MACI 6'b010011
/* */
`define OR1200_OR32_LWZ 6'b100001
`define OR1200_OR32_LBZ 6'b100011
`define OR1200_OR32_LBS 6'b100100
`define OR1200_OR32_LHZ 6'b100101
`define OR1200_OR32_LHS 6'b100110
`define OR1200_OR32_ADDI 6'b100111
`define OR1200_OR32_ADDIC 6'b101000
`define OR1200_OR32_ANDI 6'b101001
`define OR1200_OR32_ORI 6'b101010
`define OR1200_OR32_XORI 6'b101011
`define OR1200_OR32_MULI 6'b101100
`define OR1200_OR32_MFSPR 6'b101101
`define OR1200_OR32_SH_ROTI 6'b101110
`define OR1200_OR32_SFXXI 6'b101111
/* */
`define OR1200_OR32_MTSPR 6'b110000
`define OR1200_OR32_MACMSB 6'b110001
`define OR1200_OR32_FLOAT 6'b110010
/* */
`define OR1200_OR32_SW 6'b110101
`define OR1200_OR32_SB 6'b110110
`define OR1200_OR32_SH 6'b110111
`define OR1200_OR32_ALU 6'b111000
`define OR1200_OR32_SFXX 6'b111001
//`define OR1200_OR32_CUST5 6'b111100
 
 
/////////////////////////////////////////////////////
//
// Exceptions
//
 
//
// Exception vectors per OR1K architecture:
// 0xPPPPP100 - reset
// 0xPPPPP200 - bus error
// ... etc
// where P represents exception prefix.
//
// Exception vectors can be customized as per
// the following formula:
// 0xPPPPPNVV - exception N
//
// P represents exception prefix
// N represents exception N
// VV represents length of the individual vector space,
// usually it is 8 bits wide and starts with all bits zero
//
 
//
// PPPPP and VV parts
//
// Sum of these two defines needs to be 28
//
`define OR1200_EXCEPT_EPH0_P 20'h00000
`define OR1200_EXCEPT_EPH1_P 20'hF0000
`define OR1200_EXCEPT_V 8'h00
 
//
// N part width
//
`define OR1200_EXCEPT_WIDTH 4
 
//
// Definition of exception vectors
//
// To avoid implementation of a certain exception,
// simply comment out corresponding line
//
`define OR1200_EXCEPT_UNUSED `OR1200_EXCEPT_WIDTH'hf
`define OR1200_EXCEPT_TRAP `OR1200_EXCEPT_WIDTH'he
`define OR1200_EXCEPT_FLOAT `OR1200_EXCEPT_WIDTH'hd
`define OR1200_EXCEPT_SYSCALL `OR1200_EXCEPT_WIDTH'hc
`define OR1200_EXCEPT_RANGE `OR1200_EXCEPT_WIDTH'hb
`define OR1200_EXCEPT_ITLBMISS `OR1200_EXCEPT_WIDTH'ha
`define OR1200_EXCEPT_DTLBMISS `OR1200_EXCEPT_WIDTH'h9
`define OR1200_EXCEPT_INT `OR1200_EXCEPT_WIDTH'h8
`define OR1200_EXCEPT_ILLEGAL `OR1200_EXCEPT_WIDTH'h7
`define OR1200_EXCEPT_ALIGN `OR1200_EXCEPT_WIDTH'h6
`define OR1200_EXCEPT_TICK `OR1200_EXCEPT_WIDTH'h5
`define OR1200_EXCEPT_IPF `OR1200_EXCEPT_WIDTH'h4
`define OR1200_EXCEPT_DPF `OR1200_EXCEPT_WIDTH'h3
`define OR1200_EXCEPT_BUSERR `OR1200_EXCEPT_WIDTH'h2
`define OR1200_EXCEPT_RESET `OR1200_EXCEPT_WIDTH'h1
`define OR1200_EXCEPT_NONE `OR1200_EXCEPT_WIDTH'h0
 
 
/////////////////////////////////////////////////////
//
// SPR groups
//
 
// Bits that define the group
`define OR1200_SPR_GROUP_BITS 15:11
 
// Width of the group bits
`define OR1200_SPR_GROUP_WIDTH 5
 
// Bits that define offset inside the group
`define OR1200_SPR_OFS_BITS 10:0
 
// List of groups
`define OR1200_SPR_GROUP_SYS 5'd00
`define OR1200_SPR_GROUP_DMMU 5'd01
`define OR1200_SPR_GROUP_IMMU 5'd02
`define OR1200_SPR_GROUP_DC 5'd03
`define OR1200_SPR_GROUP_IC 5'd04
`define OR1200_SPR_GROUP_MAC 5'd05
`define OR1200_SPR_GROUP_DU 5'd06
`define OR1200_SPR_GROUP_PM 5'd08
`define OR1200_SPR_GROUP_PIC 5'd09
`define OR1200_SPR_GROUP_TT 5'd10
`define OR1200_SPR_GROUP_FPU 5'd11
 
/////////////////////////////////////////////////////
//
// System group
//
 
//
// System registers
//
`define OR1200_SPR_CFGR 7'd0
`define OR1200_SPR_RF 6'd32 // 1024 >> 5
`define OR1200_SPR_NPC 11'd16
`define OR1200_SPR_SR 11'd17
`define OR1200_SPR_PPC 11'd18
`define OR1200_SPR_FPCSR 11'd20
`define OR1200_SPR_EPCR 11'd32
`define OR1200_SPR_EEAR 11'd48
`define OR1200_SPR_ESR 11'd64
 
//
// SR bits
//
`define OR1200_SR_WIDTH 17
`define OR1200_SR_SM 0
`define OR1200_SR_TEE 1
`define OR1200_SR_IEE 2
`define OR1200_SR_DCE 3
`define OR1200_SR_ICE 4
`define OR1200_SR_DME 5
`define OR1200_SR_IME 6
`define OR1200_SR_LEE 7
`define OR1200_SR_CE 8
`define OR1200_SR_F 9
`define OR1200_SR_CY 10 // Unused
`define OR1200_SR_OV 11 // Unused
`define OR1200_SR_OVE 12 // Unused
`define OR1200_SR_DSX 13 // Unused
`define OR1200_SR_EPH 14
`define OR1200_SR_FO 15
`define OR1200_SR_TED 16
`define OR1200_SR_CID 31:28 // Unimplemented
 
//
// Bits that define offset inside the group
//
`define OR1200_SPROFS_BITS 10:0
 
//
// Default Exception Prefix
//
// 1'b0 - OR1200_EXCEPT_EPH0_P (0x0000_0000)
// 1'b1 - OR1200_EXCEPT_EPH1_P (0xF000_0000)
//
`define OR1200_SR_EPH_DEF 1'b0
 
 
//
// FPCSR bits
//
`define OR1200_FPCSR_WIDTH 12
`define OR1200_FPCSR_FPEE 0
`define OR1200_FPCSR_RM 2:1
`define OR1200_FPCSR_OVF 3
`define OR1200_FPCSR_UNF 4
`define OR1200_FPCSR_SNF 5
`define OR1200_FPCSR_QNF 6
`define OR1200_FPCSR_ZF 7
`define OR1200_FPCSR_IXF 8
`define OR1200_FPCSR_IVF 9
`define OR1200_FPCSR_INF 10
`define OR1200_FPCSR_DZF 11
`define OR1200_FPCSR_RES 31:12
 
/////////////////////////////////////////////////////
//
// Power Management (PM)
//
 
// Define it if you want PM implemented
//`define OR1200_PM_IMPLEMENTED
 
// Bit positions inside PMR (don't change)
`define OR1200_PM_PMR_SDF 3:0
`define OR1200_PM_PMR_DME 4
`define OR1200_PM_PMR_SME 5
`define OR1200_PM_PMR_DCGE 6
`define OR1200_PM_PMR_UNUSED 31:7
 
// PMR offset inside PM group of registers
`define OR1200_PM_OFS_PMR 11'b0
 
// PM group
`define OR1200_SPRGRP_PM 5'd8
 
// Define if PMR can be read/written at any address inside PM group
`define OR1200_PM_PARTIAL_DECODING
 
// Define if reading PMR is allowed
`define OR1200_PM_READREGS
 
// Define if unused PMR bits should be zero
`define OR1200_PM_UNUSED_ZERO
 
 
/////////////////////////////////////////////////////
//
// Debug Unit (DU)
//
 
// Define it if you want DU implemented
`define OR1200_DU_IMPLEMENTED
 
//
// Define if you want HW Breakpoints
// (if HW breakpoints are not implemented
// only default software trapping is
// possible with l.trap insn - this is
// however already enough for use
// with or32 gdb)
//
//`define OR1200_DU_HWBKPTS
 
// Number of DVR/DCR pairs if HW breakpoints enabled
// Comment / uncomment DU_DVRn / DU_DCRn pairs bellow according to this number !
// DU_DVR0..DU_DVR7 should be uncommented for 8 DU_DVRDCR_PAIRS
`define OR1200_DU_DVRDCR_PAIRS 8
 
// Define if you want trace buffer
// (for now only available for Xilinx Virtex FPGAs)
//`define OR1200_DU_TB_IMPLEMENTED
 
 
//
// Address offsets of DU registers inside DU group
//
// To not implement a register, doq not define its address
//
`ifdef OR1200_DU_HWBKPTS
`define OR1200_DU_DVR0 11'd0
`define OR1200_DU_DVR1 11'd1
`define OR1200_DU_DVR2 11'd2
`define OR1200_DU_DVR3 11'd3
`define OR1200_DU_DVR4 11'd4
`define OR1200_DU_DVR5 11'd5
`define OR1200_DU_DVR6 11'd6
`define OR1200_DU_DVR7 11'd7
`define OR1200_DU_DCR0 11'd8
`define OR1200_DU_DCR1 11'd9
`define OR1200_DU_DCR2 11'd10
`define OR1200_DU_DCR3 11'd11
`define OR1200_DU_DCR4 11'd12
`define OR1200_DU_DCR5 11'd13
`define OR1200_DU_DCR6 11'd14
`define OR1200_DU_DCR7 11'd15
`endif
`define OR1200_DU_DMR1 11'd16
`ifdef OR1200_DU_HWBKPTS
`define OR1200_DU_DMR2 11'd17
`define OR1200_DU_DWCR0 11'd18
`define OR1200_DU_DWCR1 11'd19
`endif
`define OR1200_DU_DSR 11'd20
`define OR1200_DU_DRR 11'd21
`ifdef OR1200_DU_TB_IMPLEMENTED
`define OR1200_DU_TBADR 11'h0ff
`define OR1200_DU_TBIA 11'h1??
`define OR1200_DU_TBIM 11'h2??
`define OR1200_DU_TBAR 11'h3??
`define OR1200_DU_TBTS 11'h4??
`endif
 
// Position of offset bits inside SPR address
`define OR1200_DUOFS_BITS 10:0
 
// DCR bits
`define OR1200_DU_DCR_DP 0
`define OR1200_DU_DCR_CC 3:1
`define OR1200_DU_DCR_SC 4
`define OR1200_DU_DCR_CT 7:5
 
// DMR1 bits
`define OR1200_DU_DMR1_CW0 1:0
`define OR1200_DU_DMR1_CW1 3:2
`define OR1200_DU_DMR1_CW2 5:4
`define OR1200_DU_DMR1_CW3 7:6
`define OR1200_DU_DMR1_CW4 9:8
`define OR1200_DU_DMR1_CW5 11:10
`define OR1200_DU_DMR1_CW6 13:12
`define OR1200_DU_DMR1_CW7 15:14
`define OR1200_DU_DMR1_CW8 17:16
`define OR1200_DU_DMR1_CW9 19:18
`define OR1200_DU_DMR1_CW10 21:20
`define OR1200_DU_DMR1_ST 22
`define OR1200_DU_DMR1_BT 23
`define OR1200_DU_DMR1_DXFW 24
`define OR1200_DU_DMR1_ETE 25
 
// DMR2 bits
`define OR1200_DU_DMR2_WCE0 0
`define OR1200_DU_DMR2_WCE1 1
`define OR1200_DU_DMR2_AWTC 12:2
`define OR1200_DU_DMR2_WGB 23:13
 
// DWCR bits
`define OR1200_DU_DWCR_COUNT 15:0
`define OR1200_DU_DWCR_MATCH 31:16
 
// DSR bits
`define OR1200_DU_DSR_WIDTH 14
`define OR1200_DU_DSR_RSTE 0
`define OR1200_DU_DSR_BUSEE 1
`define OR1200_DU_DSR_DPFE 2
`define OR1200_DU_DSR_IPFE 3
`define OR1200_DU_DSR_TTE 4
`define OR1200_DU_DSR_AE 5
`define OR1200_DU_DSR_IIE 6
`define OR1200_DU_DSR_IE 7
`define OR1200_DU_DSR_DME 8
`define OR1200_DU_DSR_IME 9
`define OR1200_DU_DSR_RE 10
`define OR1200_DU_DSR_SCE 11
`define OR1200_DU_DSR_FPE 12
`define OR1200_DU_DSR_TE 13
 
// DRR bits
`define OR1200_DU_DRR_RSTE 0
`define OR1200_DU_DRR_BUSEE 1
`define OR1200_DU_DRR_DPFE 2
`define OR1200_DU_DRR_IPFE 3
`define OR1200_DU_DRR_TTE 4
`define OR1200_DU_DRR_AE 5
`define OR1200_DU_DRR_IIE 6
`define OR1200_DU_DRR_IE 7
`define OR1200_DU_DRR_DME 8
`define OR1200_DU_DRR_IME 9
`define OR1200_DU_DRR_RE 10
`define OR1200_DU_DRR_SCE 11
`define OR1200_DU_DRR_FPE 12
`define OR1200_DU_DRR_TE 13
 
// Define if reading DU regs is allowed
`define OR1200_DU_READREGS
 
// Define if unused DU registers bits should be zero
`define OR1200_DU_UNUSED_ZERO
 
// Define if IF/LSU status is not needed by devel i/f
`define OR1200_DU_STATUS_UNIMPLEMENTED
 
/////////////////////////////////////////////////////
//
// Programmable Interrupt Controller (PIC)
//
 
// Define it if you want PIC implemented
`define OR1200_PIC_IMPLEMENTED
 
// Define number of interrupt inputs (2-31)
`define OR1200_PIC_INTS 31
 
// Address offsets of PIC registers inside PIC group
`define OR1200_PIC_OFS_PICMR 2'd0
`define OR1200_PIC_OFS_PICSR 2'd2
 
// Position of offset bits inside SPR address
`define OR1200_PICOFS_BITS 1:0
 
// Define if you want these PIC registers to be implemented
`define OR1200_PIC_PICMR
`define OR1200_PIC_PICSR
 
// Define if reading PIC registers is allowed
`define OR1200_PIC_READREGS
 
// Define if unused PIC register bits should be zero
`define OR1200_PIC_UNUSED_ZERO
 
 
/////////////////////////////////////////////////////
//
// Tick Timer (TT)
//
 
// Define it if you want TT implemented
`define OR1200_TT_IMPLEMENTED
 
// Address offsets of TT registers inside TT group
`define OR1200_TT_OFS_TTMR 1'd0
`define OR1200_TT_OFS_TTCR 1'd1
 
// Position of offset bits inside SPR group
`define OR1200_TTOFS_BITS 0
 
// Define if you want these TT registers to be implemented
`define OR1200_TT_TTMR
`define OR1200_TT_TTCR
 
// TTMR bits
`define OR1200_TT_TTMR_TP 27:0
`define OR1200_TT_TTMR_IP 28
`define OR1200_TT_TTMR_IE 29
`define OR1200_TT_TTMR_M 31:30
 
// Define if reading TT registers is allowed
`define OR1200_TT_READREGS
 
 
//////////////////////////////////////////////
//
// MAC
//
`define OR1200_MAC_ADDR 0 // MACLO 0xxxxxxxx1, MACHI 0xxxxxxxx0
`define OR1200_MAC_SPR_WE // Define if MACLO/MACHI are SPR writable
 
//
// Shift {MACHI,MACLO} into destination register when executing l.macrc
//
// According to architecture manual there is no shift, so default value is 0.
// However the implementation has deviated in this from the arch manual and had
// hard coded shift by 28 bits which is a useful optimization for MP3 decoding
// (if using libmad fixed point library). Shifts are no longer default setup,
// but if you need to remain backward compatible, define your shift bits, which
// were normally
// dest_GPR = {MACHI,MACLO}[59:28]
`define OR1200_MAC_SHIFTBY 0 // 0 = According to arch manual, 28 = obsolete backward compatibility
 
 
//////////////////////////////////////////////
//
// Data MMU (DMMU)
//
 
//
// Address that selects between TLB TR and MR
//
`define OR1200_DTLB_TM_ADDR 7
 
//
// DTLBMR fields
//
`define OR1200_DTLBMR_V_BITS 0
`define OR1200_DTLBMR_CID_BITS 4:1
`define OR1200_DTLBMR_RES_BITS 11:5
`define OR1200_DTLBMR_VPN_BITS 31:13
 
//
// DTLBTR fields
//
`define OR1200_DTLBTR_CC_BITS 0
`define OR1200_DTLBTR_CI_BITS 1
`define OR1200_DTLBTR_WBC_BITS 2
`define OR1200_DTLBTR_WOM_BITS 3
`define OR1200_DTLBTR_A_BITS 4
`define OR1200_DTLBTR_D_BITS 5
`define OR1200_DTLBTR_URE_BITS 6
`define OR1200_DTLBTR_UWE_BITS 7
`define OR1200_DTLBTR_SRE_BITS 8
`define OR1200_DTLBTR_SWE_BITS 9
`define OR1200_DTLBTR_RES_BITS 11:10
`define OR1200_DTLBTR_PPN_BITS 31:13
 
//
// DTLB configuration
//
`define OR1200_DMMU_PS 13 // 13 for 8KB page size
`define OR1200_DTLB_INDXW 6 // 6 for 64 entry DTLB 7 for 128 entries
`define OR1200_DTLB_INDXL `OR1200_DMMU_PS // 13 13
`define OR1200_DTLB_INDXH `OR1200_DMMU_PS+`OR1200_DTLB_INDXW-1 // 18 19
`define OR1200_DTLB_INDX `OR1200_DTLB_INDXH:`OR1200_DTLB_INDXL // 18:13 19:13
`define OR1200_DTLB_TAGW 32-`OR1200_DTLB_INDXW-`OR1200_DMMU_PS // 13 12
`define OR1200_DTLB_TAGL `OR1200_DTLB_INDXH+1 // 19 20
`define OR1200_DTLB_TAG 31:`OR1200_DTLB_TAGL // 31:19 31:20
`define OR1200_DTLBMRW `OR1200_DTLB_TAGW+1 // +1 because of V bit
`define OR1200_DTLBTRW 32-`OR1200_DMMU_PS+5 // +5 because of protection bits and CI
 
//
// Cache inhibit while DMMU is not enabled/implemented
//
// cache inhibited 0GB-4GB 1'b1
// cache inhibited 0GB-2GB !dcpu_adr_i[31]
// cache inhibited 0GB-1GB 2GB-3GB !dcpu_adr_i[30]
// cache inhibited 1GB-2GB 3GB-4GB dcpu_adr_i[30]
// cache inhibited 2GB-4GB (default) dcpu_adr_i[31]
// cached 0GB-4GB 1'b0
//
`define OR1200_DMMU_CI dcpu_adr_i[31]
 
 
//////////////////////////////////////////////
//
// Insn MMU (IMMU)
//
 
//
// Address that selects between TLB TR and MR
//
`define OR1200_ITLB_TM_ADDR 7
 
//
// ITLBMR fields
//
`define OR1200_ITLBMR_V_BITS 0
`define OR1200_ITLBMR_CID_BITS 4:1
`define OR1200_ITLBMR_RES_BITS 11:5
`define OR1200_ITLBMR_VPN_BITS 31:13
 
//
// ITLBTR fields
//
`define OR1200_ITLBTR_CC_BITS 0
`define OR1200_ITLBTR_CI_BITS 1
`define OR1200_ITLBTR_WBC_BITS 2
`define OR1200_ITLBTR_WOM_BITS 3
`define OR1200_ITLBTR_A_BITS 4
`define OR1200_ITLBTR_D_BITS 5
`define OR1200_ITLBTR_SXE_BITS 6
`define OR1200_ITLBTR_UXE_BITS 7
`define OR1200_ITLBTR_RES_BITS 11:8
`define OR1200_ITLBTR_PPN_BITS 31:13
 
//
// ITLB configuration
//
`define OR1200_IMMU_PS 13 // 13 for 8KB page size
`define OR1200_ITLB_INDXW 6 // 6 for 64 entry ITLB 7 for 128 entries
`define OR1200_ITLB_INDXL `OR1200_IMMU_PS // 13 13
`define OR1200_ITLB_INDXH `OR1200_IMMU_PS+`OR1200_ITLB_INDXW-1 // 18 19
`define OR1200_ITLB_INDX `OR1200_ITLB_INDXH:`OR1200_ITLB_INDXL // 18:13 19:13
`define OR1200_ITLB_TAGW 32-`OR1200_ITLB_INDXW-`OR1200_IMMU_PS // 13 12
`define OR1200_ITLB_TAGL `OR1200_ITLB_INDXH+1 // 19 20
`define OR1200_ITLB_TAG 31:`OR1200_ITLB_TAGL // 31:19 31:20
`define OR1200_ITLBMRW `OR1200_ITLB_TAGW+1 // +1 because of V bit
`define OR1200_ITLBTRW 32-`OR1200_IMMU_PS+3 // +3 because of protection bits and CI
 
//
// Cache inhibit while IMMU is not enabled/implemented
// Note: all combinations that use icpu_adr_i cause async loop
//
// cache inhibited 0GB-4GB 1'b1
// cache inhibited 0GB-2GB !icpu_adr_i[31]
// cache inhibited 0GB-1GB 2GB-3GB !icpu_adr_i[30]
// cache inhibited 1GB-2GB 3GB-4GB icpu_adr_i[30]
// cache inhibited 2GB-4GB (default) icpu_adr_i[31]
// cached 0GB-4GB 1'b0
//
`define OR1200_IMMU_CI 1'b0
 
 
/////////////////////////////////////////////////
//
// Insn cache (IC)
//
 
// 3 for 8 bytes, 4 for 16 bytes etc
`define OR1200_ICLS 4
 
//
// IC configurations
//
`ifdef OR1200_IC_1W_512B
`define OR1200_ICSIZE 9 // 512
`define OR1200_ICINDX `OR1200_ICSIZE-2 // 7
`define OR1200_ICINDXH `OR1200_ICSIZE-1 // 8
`define OR1200_ICTAGL `OR1200_ICINDXH+1 // 9
`define OR1200_ICTAG `OR1200_ICSIZE-`OR1200_ICLS // 5
`define OR1200_ICTAG_W 24
`endif
`ifdef OR1200_IC_1W_4KB
`define OR1200_ICSIZE 12 // 4096
`define OR1200_ICINDX `OR1200_ICSIZE-2 // 10
`define OR1200_ICINDXH `OR1200_ICSIZE-1 // 11
`define OR1200_ICTAGL `OR1200_ICINDXH+1 // 12
`define OR1200_ICTAG `OR1200_ICSIZE-`OR1200_ICLS // 8
`define OR1200_ICTAG_W 21
`endif
`ifdef OR1200_IC_1W_8KB
`define OR1200_ICSIZE 13 // 8192
`define OR1200_ICINDX `OR1200_ICSIZE-2 // 11
`define OR1200_ICINDXH `OR1200_ICSIZE-1 // 12
`define OR1200_ICTAGL `OR1200_ICINDXH+1 // 13
`define OR1200_ICTAG `OR1200_ICSIZE-`OR1200_ICLS // 9
`define OR1200_ICTAG_W 20
`endif
 
 
/////////////////////////////////////////////////
//
// Data cache (DC)
//
 
// 3 for 8 bytes, 4 for 16 bytes etc
`define OR1200_DCLS 4
 
// Define to enable default behavior of cache as write through
// Turning this off enabled write back statergy
//
`define OR1200_DC_WRITETHROUGH
 
// Define to enable stores from the stack not doing writethrough.
// EXPERIMENTAL
//`define OR1200_DC_NOSTACKWRITETHROUGH
 
// Data cache SPR definitions
`define OR1200_SPRGRP_DC_ADR_WIDTH 3
// Data cache group SPR addresses
`define OR1200_SPRGRP_DC_DCCR 3'd0 // Not implemented
`define OR1200_SPRGRP_DC_DCBPR 3'd1 // Not implemented
`define OR1200_SPRGRP_DC_DCBFR 3'd2
`define OR1200_SPRGRP_DC_DCBIR 3'd3
`define OR1200_SPRGRP_DC_DCBWR 3'd4 // Not implemented
`define OR1200_SPRGRP_DC_DCBLR 3'd5 // Not implemented
 
//
// DC configurations
//
`ifdef OR1200_DC_1W_4KB
`define OR1200_DCSIZE 12 // 4096
`define OR1200_DCINDX `OR1200_DCSIZE-2 // 10
`define OR1200_DCINDXH `OR1200_DCSIZE-1 // 11
`define OR1200_DCTAGL `OR1200_DCINDXH+1 // 12
`define OR1200_DCTAG `OR1200_DCSIZE-`OR1200_DCLS // 8
`define OR1200_DCTAG_W 21
`endif
`ifdef OR1200_DC_1W_8KB
`define OR1200_DCSIZE 13 // 8192
`define OR1200_DCINDX `OR1200_DCSIZE-2 // 11
`define OR1200_DCINDXH `OR1200_DCSIZE-1 // 12
`define OR1200_DCTAGL `OR1200_DCINDXH+1 // 13
`define OR1200_DCTAG `OR1200_DCSIZE-`OR1200_DCLS // 9
`define OR1200_DCTAG_W 20
`endif
 
 
/////////////////////////////////////////////////
//
// Store buffer (SB)
//
 
//
// Store buffer
//
// It will improve performance by "caching" CPU stores
// using store buffer. This is most important for function
// prologues because DC can only work in write though mode
// and all stores would have to complete external WB writes
// to memory.
// Store buffer is between DC and data BIU.
// All stores will be stored into store buffer and immediately
// completed by the CPU, even though actual external writes
// will be performed later. As a consequence store buffer masks
// all data bus errors related to stores (data bus errors
// related to loads are delivered normally).
// All pending CPU loads will wait until store buffer is empty to
// ensure strict memory model. Right now this is necessary because
// we don't make destinction between cached and cache inhibited
// address space, so we simply empty store buffer until loads
// can begin.
//
// It makes design a bit bigger, depending what is the number of
// entries in SB FIFO. Number of entries can be changed further
// down.
//
//`define OR1200_SB_IMPLEMENTED
 
//
// Number of store buffer entries
//
// Verified number of entries are 4 and 8 entries
// (2 and 3 for OR1200_SB_LOG). OR1200_SB_ENTRIES must
// always match 2**OR1200_SB_LOG.
// To disable store buffer, undefine
// OR1200_SB_IMPLEMENTED.
//
`define OR1200_SB_LOG 2 // 2 or 3
`define OR1200_SB_ENTRIES 4 // 4 or 8
 
 
/////////////////////////////////////////////////
//
// Quick Embedded Memory (QMEM)
//
 
//
// Quick Embedded Memory
//
// Instantiation of dedicated insn/data memory (RAM or ROM).
// Insn fetch has effective throughput 1insn / clock cycle.
// Data load takes two clock cycles / access, data store
// takes 1 clock cycle / access (if there is no insn fetch)).
// Memory instantiation is shared between insn and data,
// meaning if insn fetch are performed, data load/store
// performance will be lower.
//
// Main reason for QMEM is to put some time critical functions
// into this memory and to have predictable and fast access
// to these functions. (soft fpu, context switch, exception
// handlers, stack, etc)
//
// It makes design a bit bigger and slower. QMEM sits behind
// IMMU/DMMU so all addresses are physical (so the MMUs can be
// used with QMEM and QMEM is seen by the CPU just like any other
// memory in the system). IC/DC are sitting behind QMEM so the
// whole design timing might be worse with QMEM implemented.
//
//`define OR1200_QMEM_IMPLEMENTED
 
//
// Base address and mask of QMEM
//
// Base address defines first address of QMEM. Mask defines
// QMEM range in address space. Actual size of QMEM is however
// determined with instantiated RAM/ROM. However bigger
// mask will reserve more address space for QMEM, but also
// make design faster, while more tight mask will take
// less address space but also make design slower. If
// instantiated RAM/ROM is smaller than space reserved with
// the mask, instatiated RAM/ROM will also be shadowed
// at higher addresses in reserved space.
//
`define OR1200_QMEM_IADDR 32'h0080_0000
`define OR1200_QMEM_IMASK 32'hfff0_0000 // Max QMEM size 1MB
`define OR1200_QMEM_DADDR 32'h0080_0000
`define OR1200_QMEM_DMASK 32'hfff0_0000 // Max QMEM size 1MB
 
//
// QMEM interface byte-select capability
//
// To enable qmem_sel* ports, define this macro.
//
//`define OR1200_QMEM_BSEL
 
//
// QMEM interface acknowledge
//
// To enable qmem_ack port, define this macro.
//
//`define OR1200_QMEM_ACK
 
/////////////////////////////////////////////////////
//
// VR, UPR and Configuration Registers
//
//
// VR, UPR and configuration registers are optional. If
// implemented, operating system can automatically figure
// out how to use the processor because it knows
// what units are available in the processor and how they
// are configured.
//
// This section must be last in or1200_defines.v file so
// that all units are already configured and thus
// configuration registers are properly set.
//
 
// Define if you want configuration registers implemented
`define OR1200_CFGR_IMPLEMENTED
 
// Define if you want full address decode inside SYS group
`define OR1200_SYS_FULL_DECODE
 
// Offsets of VR, UPR and CFGR registers
`define OR1200_SPRGRP_SYS_VR 4'h0
`define OR1200_SPRGRP_SYS_UPR 4'h1
`define OR1200_SPRGRP_SYS_CPUCFGR 4'h2
`define OR1200_SPRGRP_SYS_DMMUCFGR 4'h3
`define OR1200_SPRGRP_SYS_IMMUCFGR 4'h4
`define OR1200_SPRGRP_SYS_DCCFGR 4'h5
`define OR1200_SPRGRP_SYS_ICCFGR 4'h6
`define OR1200_SPRGRP_SYS_DCFGR 4'h7
 
// VR fields
`define OR1200_VR_REV_BITS 5:0
`define OR1200_VR_RES1_BITS 15:6
`define OR1200_VR_CFG_BITS 23:16
`define OR1200_VR_VER_BITS 31:24
 
// VR values
`define OR1200_VR_REV 6'h08
`define OR1200_VR_RES1 10'h000
`define OR1200_VR_CFG 8'h00
`define OR1200_VR_VER 8'h12
 
// UPR fields
`define OR1200_UPR_UP_BITS 0
`define OR1200_UPR_DCP_BITS 1
`define OR1200_UPR_ICP_BITS 2
`define OR1200_UPR_DMP_BITS 3
`define OR1200_UPR_IMP_BITS 4
`define OR1200_UPR_MP_BITS 5
`define OR1200_UPR_DUP_BITS 6
`define OR1200_UPR_PCUP_BITS 7
`define OR1200_UPR_PMP_BITS 8
`define OR1200_UPR_PICP_BITS 9
`define OR1200_UPR_TTP_BITS 10
`define OR1200_UPR_FPP_BITS 11
`define OR1200_UPR_RES1_BITS 23:12
`define OR1200_UPR_CUP_BITS 31:24
 
// UPR values
`define OR1200_UPR_UP 1'b1
`ifdef OR1200_NO_DC
`define OR1200_UPR_DCP 1'b0
`else
`define OR1200_UPR_DCP 1'b1
`endif
`ifdef OR1200_NO_IC
`define OR1200_UPR_ICP 1'b0
`else
`define OR1200_UPR_ICP 1'b1
`endif
`ifdef OR1200_NO_DMMU
`define OR1200_UPR_DMP 1'b0
`else
`define OR1200_UPR_DMP 1'b1
`endif
`ifdef OR1200_NO_IMMU
`define OR1200_UPR_IMP 1'b0
`else
`define OR1200_UPR_IMP 1'b1
`endif
`ifdef OR1200_MAC_IMPLEMENTED
`define OR1200_UPR_MP 1'b1
`else
`define OR1200_UPR_MP 1'b0
`endif
`ifdef OR1200_DU_IMPLEMENTED
`define OR1200_UPR_DUP 1'b1
`else
`define OR1200_UPR_DUP 1'b0
`endif
`define OR1200_UPR_PCUP 1'b0 // Performance counters not present
`ifdef OR1200_PM_IMPLEMENTED
`define OR1200_UPR_PMP 1'b1
`else
`define OR1200_UPR_PMP 1'b0
`endif
`ifdef OR1200_PIC_IMPLEMENTED
`define OR1200_UPR_PICP 1'b1
`else
`define OR1200_UPR_PICP 1'b0
`endif
`ifdef OR1200_TT_IMPLEMENTED
`define OR1200_UPR_TTP 1'b1
`else
`define OR1200_UPR_TTP 1'b0
`endif
`ifdef OR1200_FPU_IMPLEMENTED
`define OR1200_UPR_FPP 1'b1
`else
`define OR1200_UPR_FPP 1'b0
`endif
`define OR1200_UPR_RES1 12'h000
`define OR1200_UPR_CUP 8'h00
 
// CPUCFGR fields
`define OR1200_CPUCFGR_NSGF_BITS 3:0
`define OR1200_CPUCFGR_HGF_BITS 4
`define OR1200_CPUCFGR_OB32S_BITS 5
`define OR1200_CPUCFGR_OB64S_BITS 6
`define OR1200_CPUCFGR_OF32S_BITS 7
`define OR1200_CPUCFGR_OF64S_BITS 8
`define OR1200_CPUCFGR_OV64S_BITS 9
`define OR1200_CPUCFGR_RES1_BITS 31:10
 
// CPUCFGR values
`define OR1200_CPUCFGR_NSGF 4'h0
`ifdef OR1200_RFRAM_16REG
`define OR1200_CPUCFGR_HGF 1'b1
`else
`define OR1200_CPUCFGR_HGF 1'b0
`endif
`define OR1200_CPUCFGR_OB32S 1'b1
`define OR1200_CPUCFGR_OB64S 1'b0
`ifdef OR1200_FPU_IMPLEMENTED
`define OR1200_CPUCFGR_OF32S 1'b1
`else
`define OR1200_CPUCFGR_OF32S 1'b0
`endif
 
`define OR1200_CPUCFGR_OF64S 1'b0
`define OR1200_CPUCFGR_OV64S 1'b0
`define OR1200_CPUCFGR_RES1 22'h000000
 
// DMMUCFGR fields
`define OR1200_DMMUCFGR_NTW_BITS 1:0
`define OR1200_DMMUCFGR_NTS_BITS 4:2
`define OR1200_DMMUCFGR_NAE_BITS 7:5
`define OR1200_DMMUCFGR_CRI_BITS 8
`define OR1200_DMMUCFGR_PRI_BITS 9
`define OR1200_DMMUCFGR_TEIRI_BITS 10
`define OR1200_DMMUCFGR_HTR_BITS 11
`define OR1200_DMMUCFGR_RES1_BITS 31:12
 
// DMMUCFGR values
`ifdef OR1200_NO_DMMU
`define OR1200_DMMUCFGR_NTW 2'h0 // Irrelevant
`define OR1200_DMMUCFGR_NTS 3'h0 // Irrelevant
`define OR1200_DMMUCFGR_NAE 3'h0 // Irrelevant
`define OR1200_DMMUCFGR_CRI 1'b0 // Irrelevant
`define OR1200_DMMUCFGR_PRI 1'b0 // Irrelevant
`define OR1200_DMMUCFGR_TEIRI 1'b0 // Irrelevant
`define OR1200_DMMUCFGR_HTR 1'b0 // Irrelevant
`define OR1200_DMMUCFGR_RES1 20'h00000
`else
`define OR1200_DMMUCFGR_NTW 2'h0 // 1 TLB way
`define OR1200_DMMUCFGR_NTS 3'h`OR1200_DTLB_INDXW // Num TLB sets
`define OR1200_DMMUCFGR_NAE 3'h0 // No ATB entries
`define OR1200_DMMUCFGR_CRI 1'b0 // No control register
`define OR1200_DMMUCFGR_PRI 1'b0 // No protection reg
`define OR1200_DMMUCFGR_TEIRI 1'b1 // TLB entry inv reg impl.
`define OR1200_DMMUCFGR_HTR 1'b0 // No HW TLB reload
`define OR1200_DMMUCFGR_RES1 20'h00000
`endif
 
// IMMUCFGR fields
`define OR1200_IMMUCFGR_NTW_BITS 1:0
`define OR1200_IMMUCFGR_NTS_BITS 4:2
`define OR1200_IMMUCFGR_NAE_BITS 7:5
`define OR1200_IMMUCFGR_CRI_BITS 8
`define OR1200_IMMUCFGR_PRI_BITS 9
`define OR1200_IMMUCFGR_TEIRI_BITS 10
`define OR1200_IMMUCFGR_HTR_BITS 11
`define OR1200_IMMUCFGR_RES1_BITS 31:12
 
// IMMUCFGR values
`ifdef OR1200_NO_IMMU
`define OR1200_IMMUCFGR_NTW 2'h0 // Irrelevant
`define OR1200_IMMUCFGR_NTS 3'h0 // Irrelevant
`define OR1200_IMMUCFGR_NAE 3'h0 // Irrelevant
`define OR1200_IMMUCFGR_CRI 1'b0 // Irrelevant
`define OR1200_IMMUCFGR_PRI 1'b0 // Irrelevant
`define OR1200_IMMUCFGR_TEIRI 1'b0 // Irrelevant
`define OR1200_IMMUCFGR_HTR 1'b0 // Irrelevant
`define OR1200_IMMUCFGR_RES1 20'h00000
`else
`define OR1200_IMMUCFGR_NTW 2'h0 // 1 TLB way
`define OR1200_IMMUCFGR_NTS 3'h`OR1200_ITLB_INDXW // Num TLB sets
`define OR1200_IMMUCFGR_NAE 3'h0 // No ATB entry
`define OR1200_IMMUCFGR_CRI 1'b0 // No control reg
`define OR1200_IMMUCFGR_PRI 1'b0 // No protection reg
`define OR1200_IMMUCFGR_TEIRI 1'b1 // TLB entry inv reg impl
`define OR1200_IMMUCFGR_HTR 1'b0 // No HW TLB reload
`define OR1200_IMMUCFGR_RES1 20'h00000
`endif
 
// DCCFGR fields
`define OR1200_DCCFGR_NCW_BITS 2:0
`define OR1200_DCCFGR_NCS_BITS 6:3
`define OR1200_DCCFGR_CBS_BITS 7
`define OR1200_DCCFGR_CWS_BITS 8
`define OR1200_DCCFGR_CCRI_BITS 9
`define OR1200_DCCFGR_CBIRI_BITS 10
`define OR1200_DCCFGR_CBPRI_BITS 11
`define OR1200_DCCFGR_CBLRI_BITS 12
`define OR1200_DCCFGR_CBFRI_BITS 13
`define OR1200_DCCFGR_CBWBRI_BITS 14
`define OR1200_DCCFGR_RES1_BITS 31:15
 
// DCCFGR values
`ifdef OR1200_NO_DC
`define OR1200_DCCFGR_NCW 3'h0 // Irrelevant
`define OR1200_DCCFGR_NCS 4'h0 // Irrelevant
`define OR1200_DCCFGR_CBS 1'b0 // Irrelevant
`define OR1200_DCCFGR_CWS 1'b0 // Irrelevant
`define OR1200_DCCFGR_CCRI 1'b0 // Irrelevant
`define OR1200_DCCFGR_CBIRI 1'b0 // Irrelevant
`define OR1200_DCCFGR_CBPRI 1'b0 // Irrelevant
`define OR1200_DCCFGR_CBLRI 1'b0 // Irrelevant
`define OR1200_DCCFGR_CBFRI 1'b0 // Irrelevant
`define OR1200_DCCFGR_CBWBRI 1'b0 // Irrelevant
`define OR1200_DCCFGR_RES1 17'h00000
`else
`define OR1200_DCCFGR_NCW 3'h0 // 1 cache way
`define OR1200_DCCFGR_NCS (`OR1200_DCTAG) // Num cache sets
`define OR1200_DCCFGR_CBS `OR1200_DCLS==4 ? 1'b0 : 1'b1 // 16 byte cache block
`ifdef OR1200_DC_WRITETHROUGH
`define OR1200_DCCFGR_CWS 1'b0 // Write-through strategy
`else
`define OR1200_DCCFGR_CWS 1'b1 // Write-back strategy
`endif
`define OR1200_DCCFGR_CCRI 1'b1 // Cache control reg impl.
`define OR1200_DCCFGR_CBIRI 1'b1 // Cache block inv reg impl.
`define OR1200_DCCFGR_CBPRI 1'b0 // Cache block prefetch reg not impl.
`define OR1200_DCCFGR_CBLRI 1'b0 // Cache block lock reg not impl.
`define OR1200_DCCFGR_CBFRI 1'b1 // Cache block flush reg impl.
`ifdef OR1200_DC_WRITETHROUGH
`define OR1200_DCCFGR_CBWBRI 1'b0 // Cache block WB reg not impl.
`else
`define OR1200_DCCFGR_CBWBRI 1'b1 // Cache block WB reg impl.
`endif
`define OR1200_DCCFGR_RES1 17'h00000
`endif
 
// ICCFGR fields
`define OR1200_ICCFGR_NCW_BITS 2:0
`define OR1200_ICCFGR_NCS_BITS 6:3
`define OR1200_ICCFGR_CBS_BITS 7
`define OR1200_ICCFGR_CWS_BITS 8
`define OR1200_ICCFGR_CCRI_BITS 9
`define OR1200_ICCFGR_CBIRI_BITS 10
`define OR1200_ICCFGR_CBPRI_BITS 11
`define OR1200_ICCFGR_CBLRI_BITS 12
`define OR1200_ICCFGR_CBFRI_BITS 13
`define OR1200_ICCFGR_CBWBRI_BITS 14
`define OR1200_ICCFGR_RES1_BITS 31:15
 
// ICCFGR values
`ifdef OR1200_NO_IC
`define OR1200_ICCFGR_NCW 3'h0 // Irrelevant
`define OR1200_ICCFGR_NCS 4'h0 // Irrelevant
`define OR1200_ICCFGR_CBS 1'b0 // Irrelevant
`define OR1200_ICCFGR_CWS 1'b0 // Irrelevant
`define OR1200_ICCFGR_CCRI 1'b0 // Irrelevant
`define OR1200_ICCFGR_CBIRI 1'b0 // Irrelevant
`define OR1200_ICCFGR_CBPRI 1'b0 // Irrelevant
`define OR1200_ICCFGR_CBLRI 1'b0 // Irrelevant
`define OR1200_ICCFGR_CBFRI 1'b0 // Irrelevant
`define OR1200_ICCFGR_CBWBRI 1'b0 // Irrelevant
`define OR1200_ICCFGR_RES1 17'h00000
`else
`define OR1200_ICCFGR_NCW 3'h0 // 1 cache way
`define OR1200_ICCFGR_NCS (`OR1200_ICTAG) // Num cache sets
`define OR1200_ICCFGR_CBS `OR1200_ICLS==4 ? 1'b0: 1'b1 // 16 byte cache block
`define OR1200_ICCFGR_CWS 1'b0 // Irrelevant
`define OR1200_ICCFGR_CCRI 1'b1 // Cache control reg impl.
`define OR1200_ICCFGR_CBIRI 1'b1 // Cache block inv reg impl.
`define OR1200_ICCFGR_CBPRI 1'b0 // Cache block prefetch reg not impl.
`define OR1200_ICCFGR_CBLRI 1'b0 // Cache block lock reg not impl.
`define OR1200_ICCFGR_CBFRI 1'b1 // Cache block flush reg impl.
`define OR1200_ICCFGR_CBWBRI 1'b0 // Irrelevant
`define OR1200_ICCFGR_RES1 17'h00000
`endif
 
// DCFGR fields
`define OR1200_DCFGR_NDP_BITS 3:0
`define OR1200_DCFGR_WPCI_BITS 4
`define OR1200_DCFGR_RES1_BITS 31:5
 
// DCFGR values
`ifdef OR1200_DU_HWBKPTS
`define OR1200_DCFGR_NDP 4'h`OR1200_DU_DVRDCR_PAIRS // # of DVR/DCR pairs
`ifdef OR1200_DU_DWCR0
`define OR1200_DCFGR_WPCI 1'b1
`else
`define OR1200_DCFGR_WPCI 1'b0 // WP counters not impl.
`endif
`else
`define OR1200_DCFGR_NDP 4'h0 // Zero DVR/DCR pairs
`define OR1200_DCFGR_WPCI 1'b0 // WP counters not impl.
`endif
`define OR1200_DCFGR_RES1 27'd0
 
///////////////////////////////////////////////////////////////////////////////
// Boot Address Selection //
// This only changes where the initial reset occurs. EPH setting is still //
// used to determine where vectors are located. //
///////////////////////////////////////////////////////////////////////////////
// Boot from 0xf0000100
//`define OR1200_BOOT_PCREG_DEFAULT 30'h3c00003f
//`define OR1200_BOOT_ADR 32'hf0000100
// Boot from 0x100
`define OR1200_BOOT_PCREG_DEFAULT 30'h0000003f
`define OR1200_BOOT_ADR 32'h00000100
/verilog/include/orpsoc-defines.v
0,0 → 1,89
//////////////////////////////////////////////////////////////////////
//// ////
//// orpsoc-defines ////
//// ////
//// Top level ORPSoC defines file ////
//// ////
//// Included in toplevel and testbench ////
//// ////
//////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2009, 2010 Authors and OPENCORES.ORG ////
//// ////
//// This source file may be used and distributed without ////
//// restriction provided that this copyright statement is not ////
//// removed from the file and that any derivative work contains ////
//// the original copyright notice and the associated disclaimer. ////
//// ////
//// This source file is free software; you can redistribute it ////
//// and/or modify it under the terms of the GNU Lesser General ////
//// Public License as published by the Free Software Foundation; ////
//// either version 2.1 of the License, or (at your option) any ////
//// later version. ////
//// ////
//// This source is distributed in the hope that it will be ////
//// useful, but WITHOUT ANY WARRANTY; without even the implied ////
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ////
//// PURPOSE. See the GNU Lesser General Public License for more ////
//// details. ////
//// ////
//// You should have received a copy of the GNU Lesser General ////
//// Public License along with this source; if not, download it ////
//// from http://www.opencores.org/lgpl.shtml ////
//// ////
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
//
// Uncomment a `define BOARD_XYZ to configure design RTL for it.
//
// Mainly presets are for internal frequency settings, and what
// external oscillator is expected (ordb1's were made with various
// XTALs.)
//
//////////////////////////////////////////////////////////////////////
 
`define XILINX
`define XILINX_PLL
`define FPGA_BOARD_XILINX_ML501
`define IOCONFIG_XILINX_ML501
`define BOARD_CLOCK_PERIOD 5000 // 200MHz (pS accuracy for Xilinx sims.)
 
`define JTAG_DEBUG
// `define RAM_WB
// `define XILINX_SSRAM
`define XILINX_DDR2
`define UART0
`define GPIO0
`define SPI0
`define I2C0
`define I2C1
`define ETH0
`define ETH0_PHY_RST
 
// end of included module defines - keep this comment line here, scripts depend on it!!
 
 
//
// Arbiter defines
//
 
// Uncomment to register things through arbiter (hopefully quicker design)
// Instruction bus arbiter
//`define ARBITER_IBUS_REGISTERING
`define ARBITER_IBUS_WATCHDOG
// Watchdog timeout: 2^(ARBITER_IBUS_WATCHDOG_TIMER_WIDTH+1) cycles
`define ARBITER_IBUS_WATCHDOG_TIMER_WIDTH 12
 
// Data bus arbiter
 
//`define ARBITER_DBUS_REGISTERING
`define ARBITER_DBUS_WATCHDOG
// Watchdog timeout: 2^(ARBITER_DBUS_WATCHDOG_TIMER_WIDTH+1) cycles
`define ARBITER_DBUS_WATCHDOG_TIMER_WIDTH 12
 
// Byte bus (peripheral bus) arbiter
// Don't really need the watchdog here - the databus will pick it up
//`define ARBITER_BYTEBUS_WATCHDOG
// Watchdog timeout: 2^(ARBITER_BYTEBUS_WATCHDOG_TIMER_WIDTH+1) cycles
`define ARBITER_BYTEBUS_WATCHDOG_TIMER_WIDTH 9
 
/verilog/include/dbg_wb_defines.v
0,0 → 1,113
//////////////////////////////////////////////////////////////////////
//// ////
//// dbg_wb_defines.v ////
//// ////
//// ////
//// This file is part of the SoC Debug Interface. ////
//// http://www.opencores.org/projects/DebugInterface/ ////
//// ////
//// Author(s): ////
//// Igor Mohor (igorm@opencores.org) ////
//// ////
//// ////
//// All additional information is avaliable in the README.txt ////
//// file. ////
//// ////
//////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2000 - 2004 Authors ////
//// ////
//// This source file may be used and distributed without ////
//// restriction provided that this copyright statement is not ////
//// removed from the file and that any derivative work contains ////
//// the original copyright notice and the associated disclaimer. ////
//// ////
//// This source file is free software; you can redistribute it ////
//// and/or modify it under the terms of the GNU Lesser General ////
//// Public License as published by the Free Software Foundation; ////
//// either version 2.1 of the License, or (at your option) any ////
//// later version. ////
//// ////
//// This source is distributed in the hope that it will be ////
//// useful, but WITHOUT ANY WARRANTY; without even the implied ////
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ////
//// PURPOSE. See the GNU Lesser General Public License for more ////
//// details. ////
//// ////
//// You should have received a copy of the GNU Lesser General ////
//// Public License along with this source; if not, download it ////
//// from http://www.opencores.org/lgpl.shtml ////
//// ////
//////////////////////////////////////////////////////////////////////
//
// CVS Revision History
//
// $Log: dbg_wb_defines.v,v $
// Revision 1.7 2004/03/31 14:34:08 igorm
// data_cnt_lim length changed to reduce number of warnings.
//
// Revision 1.6 2004/03/28 20:27:02 igorm
// New release of the debug interface (3rd. release).
//
// Revision 1.5 2004/03/22 16:35:46 igorm
// Temp version before changing dbg interface.
//
// Revision 1.4 2004/01/16 14:51:33 mohor
// cpu registers added.
//
// Revision 1.3 2004/01/08 17:53:36 mohor
// tmp version.
//
// Revision 1.2 2004/01/06 17:15:19 mohor
// temp3 version.
//
// Revision 1.1 2003/12/23 15:09:04 mohor
// New directory structure. New version of the debug interface.
//
//
//
 
// Defining length of the command
`define DBG_WB_CMD_LEN 3'd4
`define DBG_WB_CMD_LEN_INT 4
`define DBG_WB_CMD_CNT_WIDTH 3
 
// Defining length of the access_type field
`define DBG_WB_ACC_TYPE_LEN 4
 
 
// Defining length of the address
`define DBG_WB_ADR_LEN 32
 
// Defining length of the length register
`define DBG_WB_LEN_LEN 16
 
// Defining total length of the DR needed
`define DBG_WB_DR_LEN (`DBG_WB_ACC_TYPE_LEN + `DBG_WB_ADR_LEN + `DBG_WB_LEN_LEN)
 
// Defining length of the CRC
`define DBG_WB_CRC_LEN 6'd32
`define DBG_WB_CRC_CNT_WIDTH 6
 
// Defining length of status
`define DBG_WB_STATUS_LEN 3'd4
`define DBG_WB_STATUS_CNT_WIDTH 3
 
// Defining length of the data
`define DBG_WB_DATA_CNT_WIDTH (`DBG_WB_LEN_LEN + 3)
`define DBG_WB_DATA_CNT_LIM_WIDTH `DBG_WB_LEN_LEN
 
//Defining commands
`define DBG_WB_GO 4'h0
`define DBG_WB_RD_COMM 4'h1
`define DBG_WB_WR_COMM 4'h2
 
// Defining access types for wishbone
`define DBG_WB_WRITE8 4'h0
`define DBG_WB_WRITE16 4'h1
`define DBG_WB_WRITE32 4'h2
`define DBG_WB_READ8 4'h4
`define DBG_WB_READ16 4'h5
`define DBG_WB_READ32 4'h6
 
 
/verilog/include/tap_defines.v
0,0 → 1,69
//////////////////////////////////////////////////////////////////////
//// ////
//// tap_defines.v ////
//// ////
//// ////
//// This file is part of the JTAG Test Access Port (TAP) ////
//// http://www.opencores.org/projects/jtag/ ////
//// ////
//// Author(s): ////
//// Igor Mohor (igorm@opencores.org) ////
//// ////
//// ////
//// All additional information is avaliable in the README.txt ////
//// file. ////
//// ////
//////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2000 - 2003 Authors ////
//// ////
//// This source file may be used and distributed without ////
//// restriction provided that this copyright statement is not ////
//// removed from the file and that any derivative work contains ////
//// the original copyright notice and the associated disclaimer. ////
//// ////
//// This source file is free software; you can redistribute it ////
//// and/or modify it under the terms of the GNU Lesser General ////
//// Public License as published by the Free Software Foundation; ////
//// either version 2.1 of the License, or (at your option) any ////
//// later version. ////
//// ////
//// This source is distributed in the hope that it will be ////
//// useful, but WITHOUT ANY WARRANTY; without even the implied ////
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ////
//// PURPOSE. See the GNU Lesser General Public License for more ////
//// details. ////
//// ////
//// You should have received a copy of the GNU Lesser General ////
//// Public License along with this source; if not, download it ////
//// from http://www.opencores.org/lgpl.shtml ////
//// ////
//////////////////////////////////////////////////////////////////////
//
// CVS Revision History
//
// $Log: tap_defines.v,v $
// Revision 1.2 2004/01/27 10:00:33 mohor
// Unused registers removed.
//
// Revision 1.1 2003/12/23 14:52:14 mohor
// Directory structure changed. New version of TAP.
//
//
//
 
 
// Define IDCODE Value
`define IDCODE_VALUE 32'h14951185
 
// Length of the Instruction register
`define IR_LENGTH 4
 
// Supported Instructions
`define EXTEST 4'b0000
`define SAMPLE_PRELOAD 4'b0001
`define IDCODE 4'b0010
`define DEBUG 4'b1000
`define MBIST 4'b1001
`define BYPASS 4'b1111
 
/verilog/include/orpsoc-params.v
0,0 → 1,165
//////////////////////////////////////////////////////////////////////
//// ////
//// orpsoc-params ////
//// ////
//// Top level ORPSoC parameters file ////
//// ////
//// Included in toplevel and testbench ////
//// ////
//////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2009, 2010 Authors and OPENCORES.ORG ////
//// ////
//// This source file may be used and distributed without ////
//// restriction provided that this copyright statement is not ////
//// removed from the file and that any derivative work contains ////
//// the original copyright notice and the associated disclaimer. ////
//// ////
//// This source file is free software; you can redistribute it ////
//// and/or modify it under the terms of the GNU Lesser General ////
//// Public License as published by the Free Software Foundation; ////
//// either version 2.1 of the License, or (at your option) any ////
//// later version. ////
//// ////
//// This source is distributed in the hope that it will be ////
//// useful, but WITHOUT ANY WARRANTY; without even the implied ////
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ////
//// PURPOSE. See the GNU Lesser General Public License for more ////
//// details. ////
//// ////
//// You should have received a copy of the GNU Lesser General ////
//// Public License along with this source; if not, download it ////
//// from http://www.opencores.org/lgpl.shtml ////
//// ////
//////////////////////////////////////////////////////////////////////
 
///////////////////////////
// //
// Peripheral parameters //
// //
///////////////////////////
 
// SPI 0 params
parameter spi0_ss_width = 1;
parameter spi0_wb_adr = 8'hb0;
parameter wbs_d_spi0_data_width = 8;
parameter spi0_wb_adr_width = 3;
 
// i2c master slave params
// Slave addresses
parameter HV0_SADR = 8'h44;
parameter HV1_SADR = 8'h45;
parameter HV2_SADR = 8'h46;
parameter HV3_SADR = 8'h47;
 
// i2c 0 params
parameter i2c_0_wb_adr = 8'ha0;
parameter i2c_0_wb_adr_width = 3;
parameter wbs_d_i2c0_data_width = 8;
 
// i2c 1 params
parameter i2c_1_wb_adr = 8'ha1;
parameter i2c_1_wb_adr_width = 3;
parameter wbs_d_i2c1_data_width = 8;
 
 
// GPIO 0 params
parameter wbs_d_gpio0_data_width = 8;
parameter gpio0_wb_adr_width = 3;
parameter gpio0_io_width = 24;
parameter gpio0_wb_adr = 8'h91;
parameter gpio0_dir_reset_val = 0;
parameter gpio0_o_reset_val = 0;
 
// UART 0 params
parameter wbs_d_uart0_data_width = 8;
parameter uart0_wb_adr = 8'h90;
parameter uart0_data_width = 8;
parameter uart0_addr_width = 3;
 
// ROM
parameter wbs_i_rom0_data_width = 32;
parameter wbs_i_rom0_addr_width = 6;
parameter rom0_wb_adr = 4'hf;
 
// MC0 (SDRAM, or other)
parameter wbs_i_mc0_data_width = 32;
parameter wbs_d_mc0_data_width = 32;
 
// ETH0 defines
parameter eth0_wb_adr = 8'h92;
parameter wbs_d_eth0_data_width = 32;
parameter wbs_d_eth0_addr_width = 12;
parameter wbm_eth0_data_width = 32;
parameter wbm_eth0_addr_width = 32;
 
// Memory sizing for synthesis (small)
parameter internal_sram_mem_span = 32'h0080_0000;
parameter internal_sram_adr_width_for_span = 23;
 
//////////////////////////////////////////////////////
// //
// Wishbone bus parameters //
// //
//////////////////////////////////////////////////////
 
////////////////////////
// //
// Arbiter parameters //
// //
////////////////////////
 
parameter wb_dw = 32; // Default Wishbone full word width
parameter wb_aw = 32; // Default Wishbone full address width
 
///////////////////////////
// //
// Instruction bus //
// //
///////////////////////////
parameter ibus_arb_addr_match_width = 4;
// Slave addresses
parameter ibus_arb_slave0_adr = rom0_wb_adr; // FLASH ROM
parameter ibus_arb_slave1_adr = 4'h0; // Main memory (SDRAM/FPGA SRAM)
 
///////////////////////////
// //
// Data bus //
// //
///////////////////////////
// Has auto foward to last slave when no address hits
parameter dbus_arb_wb_addr_match_width = 8;
parameter dbus_arb_wb_num_slaves = 5;
// Slave addresses
parameter dbus_arb_slave0_adr = 4'h0; // Main memory (SDRAM/FPGA SRAM)
parameter dbus_arb_slave1_adr = eth0_wb_adr; // Ethernet 0
 
///////////////////////////////
// //
// Byte-wide peripheral bus //
// //
///////////////////////////////
parameter bbus_arb_wb_addr_match_width = 8;
parameter bbus_arb_wb_num_slaves = 5; // Update this when changing slaves!
// Slave addresses
parameter bbus_arb_slave0_adr = uart0_wb_adr;
parameter bbus_arb_slave1_adr = gpio0_wb_adr;
parameter bbus_arb_slave2_adr = i2c_0_wb_adr;
parameter bbus_arb_slave3_adr = i2c_1_wb_adr;
parameter bbus_arb_slave4_adr = spi0_wb_adr;
parameter bbus_arb_slave5_adr = 0 /* UNASSIGNED */;
parameter bbus_arb_slave6_adr = 0 /* UNASSIGNED */;
parameter bbus_arb_slave7_adr = 0 /* UNASSIGNED */;
parameter bbus_arb_slave8_adr = 0 /* UNASSIGNED */;
parameter bbus_arb_slave9_adr = 0 /* UNASSIGNED */;
parameter bbus_arb_slave10_adr = 0 /* UNASSIGNED */;
parameter bbus_arb_slave11_adr = 0 /* UNASSIGNED */;
parameter bbus_arb_slave12_adr = 0 /* UNASSIGNED */;
parameter bbus_arb_slave13_adr = 0 /* UNASSIGNED */;
parameter bbus_arb_slave14_adr = 0 /* UNASSIGNED */;
parameter bbus_arb_slave15_adr = 0 /* UNASSIGNED */;
parameter bbus_arb_slave16_adr = 0 /* UNASSIGNED */;
 
 
 
 
/verilog/include/uart_defines.v
0,0 → 1,250
//////////////////////////////////////////////////////////////////////
//// ////
//// uart_defines.v ////
//// ////
//// ////
//// This file is part of the "UART 16550 compatible" project ////
//// http://www.opencores.org/cores/uart16550/ ////
//// ////
//// Documentation related to this project: ////
//// - http://www.opencores.org/cores/uart16550/ ////
//// ////
//// Projects compatibility: ////
//// - WISHBONE ////
//// RS232 Protocol ////
//// 16550D uart (mostly supported) ////
//// ////
//// Overview (main Features): ////
//// Defines of the Core ////
//// ////
//// Known problems (limits): ////
//// None ////
//// ////
//// To Do: ////
//// Nothing. ////
//// ////
//// Author(s): ////
//// - gorban@opencores.org ////
//// - Jacob Gorban ////
//// - Igor Mohor (igorm@opencores.org) ////
//// ////
//// Created: 2001/05/12 ////
//// Last Updated: 2001/05/17 ////
//// (See log for the revision history) ////
//// ////
//// ////
//////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2000, 2001 Authors ////
//// ////
//// This source file may be used and distributed without ////
//// restriction provided that this copyright statement is not ////
//// removed from the file and that any derivative work contains ////
//// the original copyright notice and the associated disclaimer. ////
//// ////
//// This source file is free software; you can redistribute it ////
//// and/or modify it under the terms of the GNU Lesser General ////
//// Public License as published by the Free Software Foundation; ////
//// either version 2.1 of the License, or (at your option) any ////
//// later version. ////
//// ////
//// This source is distributed in the hope that it will be ////
//// useful, but WITHOUT ANY WARRANTY; without even the implied ////
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ////
//// PURPOSE. See the GNU Lesser General Public License for more ////
//// details. ////
//// ////
//// You should have received a copy of the GNU Lesser General ////
//// Public License along with this source; if not, download it ////
//// from http://www.opencores.org/lgpl.shtml ////
//// ////
//////////////////////////////////////////////////////////////////////
//
// CVS Revision History
//
// $Log: not supported by cvs2svn $
// Revision 1.13 2003/06/11 16:37:47 gorban
// This fixes errors in some cases when data is being read and put to the FIFO at the same time. Patch is submitted by Scott Furman. Update is very recommended.
//
// Revision 1.12 2002/07/22 23:02:23 gorban
// Bug Fixes:
// * Possible loss of sync and bad reception of stop bit on slow baud rates fixed.
// Problem reported by Kenny.Tung.
// * Bad (or lack of ) loopback handling fixed. Reported by Cherry Withers.
//
// Improvements:
// * Made FIFO's as general inferrable memory where possible.
// So on FPGA they should be inferred as RAM (Distributed RAM on Xilinx).
// This saves about 1/3 of the Slice count and reduces P&R and synthesis times.
//
// * Added optional baudrate output (baud_o).
// This is identical to BAUDOUT* signal on 16550 chip.
// It outputs 16xbit_clock_rate - the divided clock.
// It's disabled by default. Define UART_HAS_BAUDRATE_OUTPUT to use.
//
// Revision 1.10 2001/12/11 08:55:40 mohor
// Scratch register define added.
//
// Revision 1.9 2001/12/03 21:44:29 gorban
// Updated specification documentation.
// Added full 32-bit data bus interface, now as default.
// Address is 5-bit wide in 32-bit data bus mode.
// Added wb_sel_i input to the core. It's used in the 32-bit mode.
// Added debug interface with two 32-bit read-only registers in 32-bit mode.
// Bits 5 and 6 of LSR are now only cleared on TX FIFO write.
// My small test bench is modified to work with 32-bit mode.
//
// Revision 1.8 2001/11/26 21:38:54 gorban
// Lots of fixes:
// Break condition wasn't handled correctly at all.
// LSR bits could lose their values.
// LSR value after reset was wrong.
// Timing of THRE interrupt signal corrected.
// LSR bit 0 timing corrected.
//
// Revision 1.7 2001/08/24 21:01:12 mohor
// Things connected to parity changed.
// Clock devider changed.
//
// Revision 1.6 2001/08/23 16:05:05 mohor
// Stop bit bug fixed.
// Parity bug fixed.
// WISHBONE read cycle bug fixed,
// OE indicator (Overrun Error) bug fixed.
// PE indicator (Parity Error) bug fixed.
// Register read bug fixed.
//
// Revision 1.5 2001/05/31 20:08:01 gorban
// FIFO changes and other corrections.
//
// Revision 1.4 2001/05/21 19:12:02 gorban
// Corrected some Linter messages.
//
// Revision 1.3 2001/05/17 18:34:18 gorban
// First 'stable' release. Should be sythesizable now. Also added new header.
//
// Revision 1.0 2001-05-17 21:27:11+02 jacob
// Initial revision
//
//
 
// remove comments to restore to use the new version with 8 data bit interface
// in 32bit-bus mode, the wb_sel_i signal is used to put data in correct place
// also, in 8-bit version there'll be no debugging features included
// CAUTION: doesn't work with current version of OR1200
`define DATA_BUS_WIDTH_8
 
`ifdef DATA_BUS_WIDTH_8
`define UART_ADDR_WIDTH 3
`define UART_DATA_WIDTH 8
`else
`define UART_ADDR_WIDTH 5
`define UART_DATA_WIDTH 32
`endif
 
// Uncomment this if you want your UART to have
// 16xBaudrate output port.
// If defined, the enable signal will be used to drive baudrate_o signal
// It's frequency is 16xbaudrate
 
// `define UART_HAS_BAUDRATE_OUTPUT
 
// Register addresses
`define UART_REG_RB `UART_ADDR_WIDTH'd0 // receiver buffer
`define UART_REG_TR `UART_ADDR_WIDTH'd0 // transmitter
`define UART_REG_IE `UART_ADDR_WIDTH'd1 // Interrupt enable
`define UART_REG_II `UART_ADDR_WIDTH'd2 // Interrupt identification
`define UART_REG_FC `UART_ADDR_WIDTH'd2 // FIFO control
`define UART_REG_LC `UART_ADDR_WIDTH'd3 // Line Control
`define UART_REG_MC `UART_ADDR_WIDTH'd4 // Modem control
`define UART_REG_LS `UART_ADDR_WIDTH'd5 // Line status
`define UART_REG_MS `UART_ADDR_WIDTH'd6 // Modem status
`define UART_REG_SR `UART_ADDR_WIDTH'd7 // Scratch register
`define UART_REG_DL1 `UART_ADDR_WIDTH'd0 // Divisor latch bytes (1-2)
`define UART_REG_DL2 `UART_ADDR_WIDTH'd1
 
// Interrupt Enable register bits
`define UART_IE_RDA 0 // Received Data available interrupt
`define UART_IE_THRE 1 // Transmitter Holding Register empty interrupt
`define UART_IE_RLS 2 // Receiver Line Status Interrupt
`define UART_IE_MS 3 // Modem Status Interrupt
 
// Interrupt Identification register bits
`define UART_II_IP 0 // Interrupt pending when 0
`define UART_II_II 3:1 // Interrupt identification
 
// Interrupt identification values for bits 3:1
`define UART_II_RLS 3'b011 // Receiver Line Status
`define UART_II_RDA 3'b010 // Receiver Data available
`define UART_II_TI 3'b110 // Timeout Indication
`define UART_II_THRE 3'b001 // Transmitter Holding Register empty
`define UART_II_MS 3'b000 // Modem Status
 
// FIFO Control Register bits
`define UART_FC_TL 1:0 // Trigger level
 
// FIFO trigger level values
`define UART_FC_1 2'b00
`define UART_FC_4 2'b01
`define UART_FC_8 2'b10
`define UART_FC_14 2'b11
 
// Line Control register bits
`define UART_LC_BITS 1:0 // bits in character
`define UART_LC_SB 2 // stop bits
`define UART_LC_PE 3 // parity enable
`define UART_LC_EP 4 // even parity
`define UART_LC_SP 5 // stick parity
`define UART_LC_BC 6 // Break control
`define UART_LC_DL 7 // Divisor Latch access bit
 
// Modem Control register bits
`define UART_MC_DTR 0
`define UART_MC_RTS 1
`define UART_MC_OUT1 2
`define UART_MC_OUT2 3
`define UART_MC_LB 4 // Loopback mode
 
// Line Status Register bits
`define UART_LS_DR 0 // Data ready
`define UART_LS_OE 1 // Overrun Error
`define UART_LS_PE 2 // Parity Error
`define UART_LS_FE 3 // Framing Error
`define UART_LS_BI 4 // Break interrupt
`define UART_LS_TFE 5 // Transmit FIFO is empty
`define UART_LS_TE 6 // Transmitter Empty indicator
`define UART_LS_EI 7 // Error indicator
 
// Modem Status Register bits
`define UART_MS_DCTS 0 // Delta signals
`define UART_MS_DDSR 1
`define UART_MS_TERI 2
`define UART_MS_DDCD 3
`define UART_MS_CCTS 4 // Complement signals
`define UART_MS_CDSR 5
`define UART_MS_CRI 6
`define UART_MS_CDCD 7
 
// FIFO parameter defines
 
`define UART_FIFO_WIDTH 8
`define UART_FIFO_DEPTH 16
`define UART_FIFO_POINTER_W 4
`define UART_FIFO_COUNTER_W 5
// receiver fifo has width 11 because it has break, parity and framing error bits
`define UART_FIFO_REC_WIDTH 11
 
 
`define VERBOSE_WB 0 // All activity on the WISHBONE is recorded
`define VERBOSE_LINE_STATUS 0 // Details about the lsr (line status register)
`define FAST_TEST 1 // 64/1024 packets are sent
 
// Defines hard baud prescaler register - uncomment to enable
`define PRESCALER_PRESET_HARD
// 115200 baud preset values
// 20MHz: prescaler 10.8 (11, rounded up)
//`define PRESCALER_HIGH_PRESET 8'd0
//`define PRESCALER_LOW_PRESET 8'd11
// 50MHz: prescaler 27.1
`define PRESCALER_HIGH_PRESET 8'd0
`define PRESCALER_LOW_PRESET 8'd27
/verilog/include/dbg_defines.v
0,0 → 1,153
//////////////////////////////////////////////////////////////////////
//// ////
//// dbg_defines.v ////
//// ////
//// ////
//// This file is part of the SoC Debug Interface. ////
//// http://www.opencores.org/projects/DebugInterface/ ////
//// ////
//// Author(s): ////
//// Igor Mohor (igorm@opencores.org) ////
//// ////
//// ////
//// All additional information is avaliable in the README.txt ////
//// file. ////
//// ////
//////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2000 - 2004 Authors ////
//// ////
//// This source file may be used and distributed without ////
//// restriction provided that this copyright statement is not ////
//// removed from the file and that any derivative work contains ////
//// the original copyright notice and the associated disclaimer. ////
//// ////
//// This source file is free software; you can redistribute it ////
//// and/or modify it under the terms of the GNU Lesser General ////
//// Public License as published by the Free Software Foundation; ////
//// either version 2.1 of the License, or (at your option) any ////
//// later version. ////
//// ////
//// This source is distributed in the hope that it will be ////
//// useful, but WITHOUT ANY WARRANTY; without even the implied ////
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ////
//// PURPOSE. See the GNU Lesser General Public License for more ////
//// details. ////
//// ////
//// You should have received a copy of the GNU Lesser General ////
//// Public License along with this source; if not, download it ////
//// from http://www.opencores.org/lgpl.shtml ////
//// ////
//////////////////////////////////////////////////////////////////////
//
// CVS Revision History
//
// $Log: dbg_defines.v,v $
// Revision 1.20 2004/04/01 11:56:59 igorm
// Port names and defines for the supported CPUs changed.
//
// Revision 1.19 2004/03/28 20:27:02 igorm
// New release of the debug interface (3rd. release).
//
// Revision 1.18 2004/03/22 16:35:46 igorm
// Temp version before changing dbg interface.
//
// Revision 1.17 2004/01/30 10:24:30 mohor
// Defines WISHBONE_SUPPORTED and CPU_SUPPORTED added. By default both are
// turned on.
//
// Revision 1.16 2004/01/20 14:23:45 mohor
// Define name changed.
//
// Revision 1.15 2003/12/23 15:07:34 mohor
// New directory structure. New version of the debug interface.
// Files that are not needed removed.
//
// Revision 1.14 2003/10/23 16:17:00 mohor
// CRC logic changed.
//
// Revision 1.13 2003/10/21 09:48:31 simons
// Mbist support added.
//
// Revision 1.12 2003/09/17 14:38:57 simons
// WB_CNTL register added, some syncronization fixes.
//
// Revision 1.11 2003/08/28 13:55:21 simons
// Three more chains added for cpu debug access.
//
// Revision 1.10 2003/07/31 12:19:49 simons
// Multiple cpu support added.
//
// Revision 1.9 2002/05/07 14:43:59 mohor
// mon_cntl_o signals that controls monitor mux added.
//
// Revision 1.8 2002/01/25 07:58:34 mohor
// IDCODE bug fixed, chains reused to decreas size of core. Data is shifted-in
// not filled-in. Tested in hw.
//
// Revision 1.7 2001/12/06 10:08:06 mohor
// Warnings from synthesys tools fixed.
//
// Revision 1.6 2001/11/28 09:38:30 mohor
// Trace disabled by default.
//
// Revision 1.5 2001/10/15 09:55:47 mohor
// Wishbone interface added, few fixes for better performance,
// hooks for boundary scan testing added.
//
// Revision 1.4 2001/09/24 14:06:42 mohor
// Changes connected to the OpenRISC access (SPR read, SPR write).
//
// Revision 1.3 2001/09/20 10:11:25 mohor
// Working version. Few bugs fixed, comments added.
//
// Revision 1.2 2001/09/18 14:13:47 mohor
// Trace fixed. Some registers changed, trace simplified.
//
// Revision 1.1.1.1 2001/09/13 13:49:19 mohor
// Initial official release.
//
// Revision 1.3 2001/06/01 22:22:35 mohor
// This is a backup. It is not a fully working version. Not for use, yet.
//
// Revision 1.2 2001/05/18 13:10:00 mohor
// Headers changed. All additional information is now avaliable in the README.txt file.
//
// Revision 1.1.1.1 2001/05/18 06:35:08 mohor
// Initial release
//
//
 
 
// Length of the MODULE ID register
`define DBG_TOP_MODULE_ID_LENGTH 4
 
// Length of data
`define DBG_TOP_MODULE_DATA_LEN `DBG_TOP_MODULE_ID_LENGTH + 1
`define DBG_TOP_DATA_CNT 3
 
// Length of status
`define DBG_TOP_STATUS_LEN 3'd4
`define DBG_TOP_STATUS_CNT_WIDTH 3
 
// Length of the CRC
`define DBG_TOP_CRC_LEN 32
`define DBG_TOP_CRC_CNT 6
 
// Chains
`define DBG_TOP_WISHBONE_DEBUG_MODULE 4'h0
`define DBG_TOP_CPU0_DEBUG_MODULE 4'h1
`define DBG_TOP_CPU1_DEBUG_MODULE 4'h2
 
// If WISHBONE sub-module is supported uncomment the folowing line
`define DBG_WISHBONE_SUPPORTED
 
// If CPU_0 sub-module is supported uncomment the folowing line
`define DBG_CPU0_SUPPORTED
 
// If CPU_1 sub-module is supported uncomment the folowing line
//`define DBG_CPU1_SUPPORTED
 
// If more debug info is needed, uncomment the follofing line
//`define DBG_MORE_INFO
 
/verilog/include/xilinx_ddr2_params.v
0,0 → 1,53
 
// memory controller parameters
parameter BANK_WIDTH = 2; // # of memory bank addr bits
parameter CKE_WIDTH = 2; // # of memory clock enable outputs
parameter CLK_WIDTH = 2; // # of clock outputs
parameter CLK_TYPE = "SINGLE_ENDED"; // # of clock type
parameter COL_WIDTH = 10; // # of memory column bits
parameter CS_NUM = 1; // # of separate memory chip selects
parameter CS_WIDTH = 2; // # of total memory chip selects
parameter CS_BITS = 0; // set to log2(CS_NUM) (rounded up)
parameter DM_WIDTH = 8; // # of data mask bits
parameter DQ_WIDTH = 64; // # of data width
parameter DQ_PER_DQS = 8; // # of DQ data bits per strobe
parameter DQS_WIDTH = 8; // # of DQS strobes
parameter DQ_BITS = 6; // set to log2(DQS_WIDTH*DQ_PER_DQS)
parameter DQS_BITS = 3; // set to log2(DQS_WIDTH)
parameter HIGH_PERFORMANCE_MODE = "TRUE"; // Sets the performance mode for IODELAY elements
parameter ODT_WIDTH = 2; // # of memory on-die term enables
parameter ROW_WIDTH = 13; // # of memory row & # of addr bits
// Can't change this!!
parameter APPDATA_WIDTH = 128; // # of usr read/write data bus bits
//parameter APPDATA_WIDTH = 32; // # of usr read/write data bus bits
 
parameter ADDITIVE_LAT = 0; // additive write latency
// Controller with cache!
parameter BURST_LEN = 8; // burst length (in double words)
// Old controller
// parameter BURST_LEN = 4; // burst length (in double words)
parameter BURST_TYPE = 0; // burst type (=0 seq; =1 interlved)
parameter CAS_LAT = 4; // CAS latency
parameter ECC_ENABLE = 0; // enable ECC (=1 enable)
parameter MULTI_BANK_EN = 1; // enable bank management
parameter TWO_T_TIME_EN = 1; // 2t timing for unbuffered dimms
parameter ODT_TYPE = 1; // ODT (=0(none),=1(75),=2(150),=3(50))
parameter REDUCE_DRV = 0; // reduced strength mem I/O (=1 yes)
parameter REG_ENABLE = 0; // registered addr/ctrl (=1 yes)
parameter TREFI_NS = 7800; // auto refresh interval (ns)
parameter TRAS = 40000; // active->precharge delay
parameter TRCD = 15000; // active->read/write delay
parameter TRFC = 105000; // ref->ref, ref->active delay
parameter TRP = 15000; // precharge->command delay
parameter TRTP = 7500; // read->precharge delay
parameter TWR = 15000; // used to determine wr->prech
parameter TWTR = 7500; // write->read delay
// Synthesize with this set to one if running post-synthesis simulations (don't have to wait forever for powerup delay on DDR2 controller)
// parameter SIM_ONLY = 1; // = 0 to allow power up delay
parameter SIM_ONLY = 0; // = 0 to allow power up delay
parameter DEBUG_EN = 0; // Enable debug signals/controls
parameter RST_ACT_LOW = 0; // =1 for active low reset, =0 for active high
parameter DLL_FREQ_MODE = "HIGH"; // DCM Frequency range
parameter CLK_PERIOD = 3750; // 266MHz Core/Mem clk period (in ps)
// parameter CLK_PERIOD = 5000; // 200MHz Core/Mem clk period (in ps)
 
/verilog/lfsr/lfsr.v
0,0 → 1,118
//////////////////////////////////////////////////////////////////////
//// ////
//// Linear feedback shift register with Wishbone interface ////
//// ////
//// Description ////
//// Simple LFSR module (feedback hardcoded) ////
//// Two accessible registers: ////
//// Address 0: LFSR Register (R/W) ////
//// Address 4: Control register, active high, self resetting (WO)////
//// Bit[0]: lfsr shift enable ////
//// Bit[1]: lfsr reset ////
//// ////
//// To Do: ////
//// Perhaps make feedback parameterisable ////
//// ////
//// Author(s): ////
//// - Julius Baxter, julius.baxter@orsoc.se ////
//// ////
//// ////
//////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2010 Authors and OPENCORES.ORG ////
//// ////
//// This source file may be used and distributed without ////
//// restriction provided that this copyright statement is not ////
//// removed from the file and that any derivative work contains ////
//// the original copyright notice and the associated disclaimer. ////
//// ////
//// This source file is free software; you can redistribute it ////
//// and/or modify it under the terms of the GNU Lesser General ////
//// Public License as published by the Free Software Foundation; ////
//// either version 2.1 of the License, or (at your option) any ////
//// later version. ////
//// ////
//// This source is distributed in the hope that it will be ////
//// useful, but WITHOUT ANY WARRANTY; without even the implied ////
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ////
//// PURPOSE. See the GNU Lesser General Public License for more ////
//// details. ////
//// ////
//// You should have received a copy of the GNU Lesser General ////
//// Public License along with this source; if not, download it ////
//// from http://www.opencores.org/lgpl.shtml ////
//// ////
//////////////////////////////////////////////////////////////////////
module wb_lfsr( wb_clk, wb_rst, wb_adr_i, wb_dat_i, wb_cyc_i, wb_stb_i, wb_we_i,
wb_dat_o, wb_ack_o);
parameter width = 32;
parameter lfsr_rst_value = 32'b0011_0001_0000_1010;
input wb_clk;
input wb_rst;
input [2:0] wb_adr_i;
input [width-1:0] wb_dat_i;
input wb_cyc_i, wb_stb_i, wb_we_i;
output [width-1:0] wb_dat_o;
output reg wb_ack_o;
wire wb_req;
assign wb_req = wb_stb_i & wb_cyc_i;
reg [width-1:0] lfsr;
wire lfsr_feedback;
 
assign wb_dat_o = lfsr;
 
// Only 2 registers here, the lfsr itself and
wire lfsr_sel;
assign lfsr_sel = !wb_adr_i[2];
wire lfsr_control_reg_sel;
assign lfsr_control_reg_sel = wb_adr_i[2];
 
// [0]: shift enable, [1]: reset
reg [1:0] lfsr_control_reg;
wire lfsr_control_enable;
wire lfsr_control_rst;
 
// Load the control reg when required,
always @(posedge wb_clk)
begin
if (wb_rst)
lfsr_control_reg <= 0;
else if (wb_req & wb_we_i & lfsr_control_reg_sel & wb_ack_o)
lfsr_control_reg <= wb_dat_i;
if (lfsr_control_reg[0])
lfsr_control_reg[0] <= 0;
if (lfsr_control_reg[1])
lfsr_control_reg[1] <= 0;
end // always @ (posedge wb_clk)
 
assign lfsr_control_enable = lfsr_control_reg[0];
assign lfsr_control_rst = lfsr_control_reg[1];
assign lfsr_feedback = !(((lfsr[27] ^ lfsr[13]) ^ lfsr[8]) ^ lfsr[5]);
always @(posedge wb_clk)
if (wb_rst)
lfsr <= lfsr_rst_value;
else if (lfsr_control_rst)
lfsr <= lfsr_rst_value;
else if (wb_req & wb_we_i & lfsr_sel & wb_ack_o) // Set lfsr
lfsr <= wb_dat_i;
else if (lfsr_control_enable)
lfsr <= {lfsr[width-2:0], lfsr_feedback};
always @(posedge wb_clk)
if (wb_rst)
wb_ack_o <= 0;
else if (wb_req & !wb_ack_o)
wb_ack_o <= 1;
else if (wb_ack_o)
wb_ack_o <= 0;
 
endmodule // lfsr
/verilog/xilinx_ddr2/ddr2_phy_dqs_iob.v
0,0 → 1,263
//*****************************************************************************
// DISCLAIMER OF LIABILITY
//
// This file contains proprietary and confidential information of
// Xilinx, Inc. ("Xilinx"), that is distributed under a license
// from Xilinx, and may be used, copied and/or disclosed only
// pursuant to the terms of a valid license agreement with Xilinx.
//
// XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION
// ("MATERIALS") "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
// EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING WITHOUT
// LIMITATION, ANY WARRANTY WITH RESPECT TO NONINFRINGEMENT,
// MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE. Xilinx
// does not warrant that functions included in the Materials will
// meet the requirements of Licensee, or that the operation of the
// Materials will be uninterrupted or error-free, or that defects
// in the Materials will be corrected. Furthermore, Xilinx does
// not warrant or make any representations regarding use, or the
// results of the use, of the Materials in terms of correctness,
// accuracy, reliability or otherwise.
//
// Xilinx products are not designed or intended to be fail-safe,
// or for use in any application requiring fail-safe performance,
// such as life-support or safety devices or systems, Class III
// medical devices, nuclear facilities, applications related to
// the deployment of airbags, or any other applications that could
// lead to death, personal injury or severe property or
// environmental damage (individually and collectively, "critical
// applications"). Customer assumes the sole risk and liability
// of any use of Xilinx products in critical applications,
// subject only to applicable laws and regulations governing
// limitations on product liability.
//
// Copyright 2006, 2007, 2008 Xilinx, Inc.
// All rights reserved.
//
// This disclaimer and copyright notice must be retained as part
// of this file at all times.
//*****************************************************************************
// ____ ____
// / /\/ /
// /___/ \ / Vendor: Xilinx
// \ \ \/ Version: 3.0
// \ \ Application: MIG
// / / Filename: ddr2_phy_dqs_iob.v
// /___/ /\ Date Last Modified: $Date: 2008/12/23 14:26:00 $
// \ \ / \ Date Created: Wed Aug 16 2006
// \___\/\___\
//
//Device: Virtex-5
//Design Name: DDR2
//Purpose:
// This module places the data strobes in the IOBs.
//Reference:
//Revision History:
// Rev 1.1 - Parameter HIGH_PERFORMANCE_MODE added. PK. 7/10/08
// Rev 1.2 - Parameter IODELAY_GRP added and constraint IODELAY_GROUP added
// on IODELAY primitives. PK. 11/27/08
//*****************************************************************************
 
`timescale 1ns/1ps
 
module ddr2_phy_dqs_iob #
(
// Following parameters are for 72-bit RDIMM design (for ML561 Reference
// board design). Actual values may be different. Actual parameters values
// are passed from design top module ddr2_mig module. Please refer to
// the ddr2_mig module for actual values.
parameter DDR_TYPE = 1,
parameter HIGH_PERFORMANCE_MODE = "TRUE",
parameter IODELAY_GRP = "IODELAY_MIG"
)
(
input clk0,
input clkdiv0,
input rst0,
input dlyinc_dqs,
input dlyce_dqs,
input dlyrst_dqs,
input dlyinc_gate,
input dlyce_gate,
input dlyrst_gate,
input dqs_oe_n,
input dqs_rst_n,
input en_dqs,
inout ddr_dqs,
inout ddr_dqs_n,
output dq_ce,
output delayed_dqs
);
 
wire clk180;
wire dqs_bufio;
 
wire dqs_ibuf;
wire dqs_idelay;
wire dqs_oe_n_delay;
wire dqs_oe_n_r;
wire dqs_rst_n_delay;
reg dqs_rst_n_r /* synthesis syn_preserve = 1*/;
wire dqs_out;
wire en_dqs_sync /* synthesis syn_keep = 1 */;
 
// for simulation only. Synthesis should ignore this delay
localparam DQS_NET_DELAY = 0.8;
 
assign clk180 = ~clk0;
 
// add delta delay to inputs clocked by clk180 to avoid delta-delay
// simulation issues
assign dqs_rst_n_delay = dqs_rst_n;
assign dqs_oe_n_delay = dqs_oe_n;
 
//***************************************************************************
// DQS input-side resources:
// - IODELAY (pad -> IDELAY)
// - BUFIO (IDELAY -> BUFIO)
//***************************************************************************
 
// Route DQS from PAD to IDELAY
(* IODELAY_GROUP = IODELAY_GRP *) IODELAY #
(
.DELAY_SRC("I"),
.IDELAY_TYPE("VARIABLE"),
.HIGH_PERFORMANCE_MODE(HIGH_PERFORMANCE_MODE),
.IDELAY_VALUE(0),
.ODELAY_VALUE(0)
)
u_idelay_dqs
(
.DATAOUT (dqs_idelay),
.C (clkdiv0),
.CE (dlyce_dqs),
.DATAIN (),
.IDATAIN (dqs_ibuf),
.INC (dlyinc_dqs),
.ODATAIN (),
.RST (dlyrst_dqs),
.T ()
);
 
// From IDELAY to BUFIO
BUFIO u_bufio_dqs
(
.I (dqs_idelay),
.O (dqs_bufio)
);
 
// To model additional delay of DQS BUFIO + gating network
// for behavioral simulation. Make sure to select a delay number smaller
// than half clock cycle (otherwise output will not track input changes
// because of inertial delay). Duplicate to avoid delta delay issues.
assign #(DQS_NET_DELAY) i_delayed_dqs = dqs_bufio;
assign #(DQS_NET_DELAY) delayed_dqs = dqs_bufio;
 
//***************************************************************************
// DQS gate circuit (not supported for all controllers)
//***************************************************************************
 
// Gate routing:
// en_dqs -> IDELAY -> en_dqs_sync -> IDDR.S -> dq_ce ->
// capture IDDR.CE
 
// Delay CE control so that it's in phase with delayed DQS
(* IODELAY_GROUP = IODELAY_GRP *) IODELAY #
(
.DELAY_SRC ("DATAIN"),
.IDELAY_TYPE ("VARIABLE"),
.HIGH_PERFORMANCE_MODE (HIGH_PERFORMANCE_MODE),
.IDELAY_VALUE (0),
.ODELAY_VALUE (0)
)
u_iodelay_dq_ce
(
.DATAOUT (en_dqs_sync),
.C (clkdiv0),
.CE (dlyce_gate),
.DATAIN (en_dqs),
.IDATAIN (),
.INC (dlyinc_gate),
.ODATAIN (),
.RST (dlyrst_gate),
.T ()
);
 
// Generate sync'ed CE to DQ IDDR's using an IDDR clocked by DQS
// We could also instantiate a negative-edge SDR flop here
IDDR #
(
.DDR_CLK_EDGE ("OPPOSITE_EDGE"),
.INIT_Q1 (1'b0),
.INIT_Q2 (1'b0),
.SRTYPE ("ASYNC")
)
u_iddr_dq_ce
(
.Q1 (),
.Q2 (dq_ce), // output on falling edge
.C (i_delayed_dqs),
.CE (1'b1),
.D (en_dqs_sync),
.R (1'b0),
.S (en_dqs_sync)
);
 
//***************************************************************************
// DQS output-side resources
//***************************************************************************
 
// synthesis attribute keep of dqs_rst_n_r is "true"
always @(posedge clk180)
dqs_rst_n_r <= dqs_rst_n_delay;
 
ODDR #
(
.SRTYPE("SYNC"),
.DDR_CLK_EDGE("OPPOSITE_EDGE")
)
u_oddr_dqs
(
.Q (dqs_out),
.C (clk180),
.CE (1'b1),
.D1 (dqs_rst_n_r), // keep output deasserted for write preamble
.D2 (1'b0),
.R (1'b0),
.S (1'b0)
);
 
(* IOB = "FORCE" *) FDP u_tri_state_dqs
(
.D (dqs_oe_n_delay),
.Q (dqs_oe_n_r),
.C (clk180),
.PRE (rst0)
) /* synthesis syn_useioff = 1 */;
 
//***************************************************************************
 
// use either single-ended (for DDR1) or differential (for DDR2) DQS input
 
generate
if (DDR_TYPE > 0) begin: gen_dqs_iob_ddr2
IOBUFDS u_iobuf_dqs
(
.O (dqs_ibuf),
.IO (ddr_dqs),
.IOB (ddr_dqs_n),
.I (dqs_out),
.T (dqs_oe_n_r)
);
end else begin: gen_dqs_iob_ddr1
IOBUF u_iobuf_dqs
(
.O (dqs_ibuf),
.IO (ddr_dqs),
.I (dqs_out),
.T (dqs_oe_n_r)
);
end
endgenerate
 
endmodule
/verilog/xilinx_ddr2/ddr2_top.v
0,0 → 1,278
//*****************************************************************************
// DISCLAIMER OF LIABILITY
//
// This file contains proprietary and confidential information of
// Xilinx, Inc. ("Xilinx"), that is distributed under a license
// from Xilinx, and may be used, copied and/or disclosed only
// pursuant to the terms of a valid license agreement with Xilinx.
//
// XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION
// ("MATERIALS") "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
// EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING WITHOUT
// LIMITATION, ANY WARRANTY WITH RESPECT TO NONINFRINGEMENT,
// MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE. Xilinx
// does not warrant that functions included in the Materials will
// meet the requirements of Licensee, or that the operation of the
// Materials will be uninterrupted or error-free, or that defects
// in the Materials will be corrected. Furthermore, Xilinx does
// not warrant or make any representations regarding use, or the
// results of the use, of the Materials in terms of correctness,
// accuracy, reliability or otherwise.
//
// Xilinx products are not designed or intended to be fail-safe,
// or for use in any application requiring fail-safe performance,
// such as life-support or safety devices or systems, Class III
// medical devices, nuclear facilities, applications related to
// the deployment of airbags, or any other applications that could
// lead to death, personal injury or severe property or
// environmental damage (individually and collectively, "critical
// applications"). Customer assumes the sole risk and liability
// of any use of Xilinx products in critical applications,
// subject only to applicable laws and regulations governing
// limitations on product liability.
//
// Copyright 2006, 2007, 2008 Xilinx, Inc.
// All rights reserved.
//
// This disclaimer and copyright notice must be retained as part
// of this file at all times.
//*****************************************************************************
// ____ ____
// / /\/ /
// /___/ \ / Vendor: Xilinx
// \ \ \/ Version: 3.0
// \ \ Application: MIG
// / / Filename: ddr2_top.v
// /___/ /\ Date Last Modified: $Date: 2009/01/15 14:22:14 $
// \ \ / \ Date Created: Wed Aug 16 2006
// \___\/\___\
//
//Device: Virtex-5
//Design Name: DDR2
//Purpose:
// System level module. This level contains just the memory controller.
// This level will be intiantated when the user wants to remove the
// synthesizable test bench, IDELAY control block and the clock
// generation modules.
//Reference:
//Revision History:
// Rev 1.1 - Parameter USE_DM_PORT added. PK. 6/25/08
// Rev 1.2 - Parameter HIGH_PERFORMANCE_MODE added. PK. 7/10/08
// Rev 1.3 - Parameter IODELAY_GRP added. PK. 11/27/08
//*****************************************************************************
 
`timescale 1ns/1ps
 
module ddr2_top #
(
// Following parameters are for 72-bit RDIMM design (for ML561 Reference
// board design). Actual values may be different. Actual parameters values
// are passed from design top module ddr2_mig module. Please refer to
// the ddr2_mig module for actual values.
parameter BANK_WIDTH = 2, // # of memory bank addr bits
parameter CKE_WIDTH = 1, // # of memory clock enable outputs
parameter CLK_WIDTH = 1, // # of clock outputs
parameter COL_WIDTH = 10, // # of memory column bits
parameter CS_NUM = 1, // # of separate memory chip selects
parameter CS_BITS = 0, // set to log2(CS_NUM) (rounded up)
parameter CS_WIDTH = 1, // # of total memory chip selects
parameter USE_DM_PORT = 1, // enable Data Mask (=1 enable)
parameter DM_WIDTH = 9, // # of data mask bits
parameter DQ_WIDTH = 72, // # of data width
parameter DQ_BITS = 7, // set to log2(DQS_WIDTH*DQ_PER_DQS)
parameter DQ_PER_DQS = 8, // # of DQ data bits per strobe
parameter DQS_WIDTH = 9, // # of DQS strobes
parameter DQS_BITS = 4, // set to log2(DQS_WIDTH)
parameter HIGH_PERFORMANCE_MODE = "TRUE", // IODELAY Performance Mode
parameter IODELAY_GRP = "IODELAY_MIG", // IODELAY Group Name
parameter ODT_WIDTH = 1, // # of memory on-die term enables
parameter ROW_WIDTH = 14, // # of memory row & # of addr bits
parameter APPDATA_WIDTH = 144, // # of usr read/write data bus bits
parameter ADDITIVE_LAT = 0, // additive write latency
parameter BURST_LEN = 4, // burst length (in double words)
parameter BURST_TYPE = 0, // burst type (=0 seq; =1 interlved)
parameter CAS_LAT = 5, // CAS latency
parameter ECC_ENABLE = 0, // enable ECC (=1 enable)
parameter ODT_TYPE = 1, // ODT (=0(none),=1(75),=2(150),=3(50))
parameter MULTI_BANK_EN = 1, // enable bank management
parameter TWO_T_TIME_EN = 0, // 2t timing for unbuffered dimms
parameter REDUCE_DRV = 0, // reduced strength mem I/O (=1 yes)
parameter REG_ENABLE = 1, // registered addr/ctrl (=1 yes)
parameter TREFI_NS = 7800, // auto refresh interval (ns)
parameter TRAS = 40000, // active->precharge delay
parameter TRCD = 15000, // active->read/write delay
parameter TRFC = 105000, // ref->ref, ref->active delay
parameter TRP = 15000, // precharge->command delay
parameter TRTP = 7500, // read->precharge delay
parameter TWR = 15000, // used to determine wr->prech
parameter TWTR = 10000, // write->read delay
parameter CLK_PERIOD = 3000, // Core/Mem clk period (in ps)
parameter SIM_ONLY = 0, // = 1 to skip power up delay
parameter DEBUG_EN = 0, // Enable debug signals/controls
parameter FPGA_SPEED_GRADE = 2 // FPGA Speed Grade
)
(
input clk0,
input usr_clk, // jb
input clk90,
input clkdiv0,
input rst0,
input rst90,
input rstdiv0,
input [2:0] app_af_cmd,
input [30:0] app_af_addr,
input app_af_wren,
input app_wdf_wren,
input [APPDATA_WIDTH-1:0] app_wdf_data,
input [(APPDATA_WIDTH/8)-1:0] app_wdf_mask_data,
output app_af_afull,
output app_wdf_afull,
output rd_data_valid,
output [APPDATA_WIDTH-1:0] rd_data_fifo_out,
output [1:0] rd_ecc_error,
output phy_init_done,
output [CLK_WIDTH-1:0] ddr2_ck,
output [CLK_WIDTH-1:0] ddr2_ck_n,
output [ROW_WIDTH-1:0] ddr2_a,
output [BANK_WIDTH-1:0] ddr2_ba,
output ddr2_ras_n,
output ddr2_cas_n,
output ddr2_we_n,
output [CS_WIDTH-1:0] ddr2_cs_n,
output [CKE_WIDTH-1:0] ddr2_cke,
output [ODT_WIDTH-1:0] ddr2_odt,
output [DM_WIDTH-1:0] ddr2_dm,
inout [DQS_WIDTH-1:0] ddr2_dqs,
inout [DQS_WIDTH-1:0] ddr2_dqs_n,
inout [DQ_WIDTH-1:0] ddr2_dq,
// Debug signals (optional use)
input dbg_idel_up_all,
input dbg_idel_down_all,
input dbg_idel_up_dq,
input dbg_idel_down_dq,
input dbg_idel_up_dqs,
input dbg_idel_down_dqs,
input dbg_idel_up_gate,
input dbg_idel_down_gate,
input [DQ_BITS-1:0] dbg_sel_idel_dq,
input dbg_sel_all_idel_dq,
input [DQS_BITS:0] dbg_sel_idel_dqs,
input dbg_sel_all_idel_dqs,
input [DQS_BITS:0] dbg_sel_idel_gate,
input dbg_sel_all_idel_gate,
output [3:0] dbg_calib_done,
output [3:0] dbg_calib_err,
output [(6*DQ_WIDTH)-1:0] dbg_calib_dq_tap_cnt,
output [(6*DQS_WIDTH)-1:0] dbg_calib_dqs_tap_cnt,
output [(6*DQS_WIDTH)-1:0] dbg_calib_gate_tap_cnt,
output [DQS_WIDTH-1:0] dbg_calib_rd_data_sel,
output [(5*DQS_WIDTH)-1:0] dbg_calib_rden_dly,
output [(5*DQS_WIDTH)-1:0] dbg_calib_gate_dly
);
 
// memory initialization/control logic
ddr2_mem_if_top #
(
.BANK_WIDTH (BANK_WIDTH),
.CKE_WIDTH (CKE_WIDTH),
.CLK_WIDTH (CLK_WIDTH),
.COL_WIDTH (COL_WIDTH),
.CS_BITS (CS_BITS),
.CS_NUM (CS_NUM),
.CS_WIDTH (CS_WIDTH),
.USE_DM_PORT (USE_DM_PORT),
.DM_WIDTH (DM_WIDTH),
.DQ_WIDTH (DQ_WIDTH),
.DQ_BITS (DQ_BITS),
.DQ_PER_DQS (DQ_PER_DQS),
.DQS_BITS (DQS_BITS),
.DQS_WIDTH (DQS_WIDTH),
.HIGH_PERFORMANCE_MODE (HIGH_PERFORMANCE_MODE),
.IODELAY_GRP (IODELAY_GRP),
.ODT_WIDTH (ODT_WIDTH),
.ROW_WIDTH (ROW_WIDTH),
.APPDATA_WIDTH (APPDATA_WIDTH),
.ADDITIVE_LAT (ADDITIVE_LAT),
.BURST_LEN (BURST_LEN),
.BURST_TYPE (BURST_TYPE),
.CAS_LAT (CAS_LAT),
.ECC_ENABLE (ECC_ENABLE),
.MULTI_BANK_EN (MULTI_BANK_EN),
.TWO_T_TIME_EN (TWO_T_TIME_EN),
.ODT_TYPE (ODT_TYPE),
.DDR_TYPE (1),
.REDUCE_DRV (REDUCE_DRV),
.REG_ENABLE (REG_ENABLE),
.TREFI_NS (TREFI_NS),
.TRAS (TRAS),
.TRCD (TRCD),
.TRFC (TRFC),
.TRP (TRP),
.TRTP (TRTP),
.TWR (TWR),
.TWTR (TWTR),
.CLK_PERIOD (CLK_PERIOD),
.SIM_ONLY (SIM_ONLY),
.DEBUG_EN (DEBUG_EN),
.FPGA_SPEED_GRADE (FPGA_SPEED_GRADE)
)
u_mem_if_top
(
.clk0 (clk0),
.usr_clk (usr_clk), // jb
.clk90 (clk90),
.clkdiv0 (clkdiv0),
.rst0 (rst0),
.rst90 (rst90),
.rstdiv0 (rstdiv0),
.app_af_cmd (app_af_cmd),
.app_af_addr (app_af_addr),
.app_af_wren (app_af_wren),
.app_wdf_wren (app_wdf_wren),
.app_wdf_data (app_wdf_data),
.app_wdf_mask_data (app_wdf_mask_data),
.app_af_afull (app_af_afull),
.app_wdf_afull (app_wdf_afull),
.rd_data_valid (rd_data_valid),
.rd_data_fifo_out (rd_data_fifo_out),
.rd_ecc_error (rd_ecc_error),
.phy_init_done (phy_init_done),
.ddr_ck (ddr2_ck),
.ddr_ck_n (ddr2_ck_n),
.ddr_addr (ddr2_a),
.ddr_ba (ddr2_ba),
.ddr_ras_n (ddr2_ras_n),
.ddr_cas_n (ddr2_cas_n),
.ddr_we_n (ddr2_we_n),
.ddr_cs_n (ddr2_cs_n),
.ddr_cke (ddr2_cke),
.ddr_odt (ddr2_odt),
.ddr_dm (ddr2_dm),
.ddr_dqs (ddr2_dqs),
.ddr_dqs_n (ddr2_dqs_n),
.ddr_dq (ddr2_dq),
.dbg_idel_up_all (dbg_idel_up_all),
.dbg_idel_down_all (dbg_idel_down_all),
.dbg_idel_up_dq (dbg_idel_up_dq),
.dbg_idel_down_dq (dbg_idel_down_dq),
.dbg_idel_up_dqs (dbg_idel_up_dqs),
.dbg_idel_down_dqs (dbg_idel_down_dqs),
.dbg_idel_up_gate (dbg_idel_up_gate),
.dbg_idel_down_gate (dbg_idel_down_gate),
.dbg_sel_idel_dq (dbg_sel_idel_dq),
.dbg_sel_all_idel_dq (dbg_sel_all_idel_dq),
.dbg_sel_idel_dqs (dbg_sel_idel_dqs),
.dbg_sel_all_idel_dqs (dbg_sel_all_idel_dqs),
.dbg_sel_idel_gate (dbg_sel_idel_gate),
.dbg_sel_all_idel_gate (dbg_sel_all_idel_gate),
.dbg_calib_done (dbg_calib_done),
.dbg_calib_err (dbg_calib_err),
.dbg_calib_dq_tap_cnt (dbg_calib_dq_tap_cnt),
.dbg_calib_dqs_tap_cnt (dbg_calib_dqs_tap_cnt),
.dbg_calib_gate_tap_cnt (dbg_calib_gate_tap_cnt),
.dbg_calib_rd_data_sel (dbg_calib_rd_data_sel),
.dbg_calib_rden_dly (dbg_calib_rden_dly),
.dbg_calib_gate_dly (dbg_calib_gate_dly)
);
 
endmodule
/verilog/xilinx_ddr2/ddr2_ctrl.v
0,0 → 1,1239
//*****************************************************************************
// DISCLAIMER OF LIABILITY
//
// This file contains proprietary and confidential information of
// Xilinx, Inc. ("Xilinx"), that is distributed under a license
// from Xilinx, and may be used, copied and/or disclosed only
// pursuant to the terms of a valid license agreement with Xilinx.
//
// XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION
// ("MATERIALS") "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
// EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING WITHOUT
// LIMITATION, ANY WARRANTY WITH RESPECT TO NONINFRINGEMENT,
// MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE. Xilinx
// does not warrant that functions included in the Materials will
// meet the requirements of Licensee, or that the operation of the
// Materials will be uninterrupted or error-free, or that defects
// in the Materials will be corrected. Furthermore, Xilinx does
// not warrant or make any representations regarding use, or the
// results of the use, of the Materials in terms of correctness,
// accuracy, reliability or otherwise.
//
// Xilinx products are not designed or intended to be fail-safe,
// or for use in any application requiring fail-safe performance,
// such as life-support or safety devices or systems, Class III
// medical devices, nuclear facilities, applications related to
// the deployment of airbags, or any other applications that could
// lead to death, personal injury or severe property or
// environmental damage (individually and collectively, "critical
// applications"). Customer assumes the sole risk and liability
// of any use of Xilinx products in critical applications,
// subject only to applicable laws and regulations governing
// limitations on product liability.
//
// Copyright 2006, 2007, 2008 Xilinx, Inc.
// All rights reserved.
//
// This disclaimer and copyright notice must be retained as part
// of this file at all times.
//*****************************************************************************
// ____ ____
// / /\/ /
// /___/ \ / Vendor: Xilinx
// \ \ \/ Version: 3.0
// \ \ Application: MIG
// / / Filename: ddr2_ctrl.v
// /___/ /\ Date Last Modified: $Date: 2008/12/23 14:26:00 $
// \ \ / \ Date Created: Wed Aug 30 2006
// \___\/\___\
//
//
//Device: Virtex-5
//Design Name: DDR/DDR2
//Purpose:
// This module is the main control logic of the memory interface. All
// commands are issued from here according to the burst, CAS Latency and the
// user commands.
//Reference:
//Revision History:
// Rev 1.2 - Fixed auto refresh to activate bug. KP 11-19-2007
// Rev 1.3 - For Dual Rank parts support CS logic modified. KP. 05/08/08
// Rev 1.4 - AUTO_REFRESH_WAIT state modified for Auto Refresh flag asserted
// immediately after calibration is completed. KP. 07/28/08
// Rev 1.5 - Assignment of bank_valid_r is modified to fix a bug in
// Bank Management logic. PK. 10/29/08
//*****************************************************************************
 
`timescale 1ns/1ps
 
module ddr2_ctrl #
(
// Following parameters are for 72-bit RDIMM design (for ML561 Reference
// board design). Actual values may be different. Actual parameters values
// are passed from design top module ddr2_mig module. Please refer to
// the ddr2_mig module for actual values.
parameter BANK_WIDTH = 2,
parameter COL_WIDTH = 10,
parameter CS_BITS = 0,
parameter CS_NUM = 1,
parameter ROW_WIDTH = 14,
parameter ADDITIVE_LAT = 0,
parameter BURST_LEN = 4,
parameter CAS_LAT = 5,
parameter ECC_ENABLE = 0,
parameter REG_ENABLE = 1,
parameter TREFI_NS = 7800,
parameter TRAS = 40000,
parameter TRCD = 15000,
parameter TRRD = 10000,
parameter TRFC = 105000,
parameter TRP = 15000,
parameter TRTP = 7500,
parameter TWR = 15000,
parameter TWTR = 10000,
parameter CLK_PERIOD = 3000,
parameter MULTI_BANK_EN = 1,
parameter TWO_T_TIME_EN = 0,
parameter DDR_TYPE = 1
)
(
input clk,
input rst,
input [2:0] af_cmd,
input [30:0] af_addr,
input af_empty,
input phy_init_done,
output ctrl_ref_flag,
output ctrl_af_rden,
output reg ctrl_wren,
output reg ctrl_rden,
output [ROW_WIDTH-1:0] ctrl_addr,
output [BANK_WIDTH-1:0] ctrl_ba,
output ctrl_ras_n,
output ctrl_cas_n,
output ctrl_we_n,
output [CS_NUM-1:0] ctrl_cs_n
);
 
// input address split into various ranges
localparam ROW_RANGE_START = COL_WIDTH;
localparam ROW_RANGE_END = ROW_WIDTH + ROW_RANGE_START - 1;
localparam BANK_RANGE_START = ROW_RANGE_END + 1;
localparam BANK_RANGE_END = BANK_WIDTH + BANK_RANGE_START - 1;
localparam CS_RANGE_START = BANK_RANGE_START + BANK_WIDTH;
localparam CS_RANGE_END = CS_BITS + CS_RANGE_START - 1;
// compare address (for determining bank/row hits) split into various ranges
// (compare address doesn't include column bits)
localparam CMP_WIDTH = CS_BITS + BANK_WIDTH + ROW_WIDTH;
localparam CMP_ROW_RANGE_START = 0;
localparam CMP_ROW_RANGE_END = ROW_WIDTH + CMP_ROW_RANGE_START - 1;
localparam CMP_BANK_RANGE_START = CMP_ROW_RANGE_END + 1;
localparam CMP_BANK_RANGE_END = BANK_WIDTH + CMP_BANK_RANGE_START - 1;
localparam CMP_CS_RANGE_START = CMP_BANK_RANGE_END + 1;
localparam CMP_CS_RANGE_END = CS_BITS + CMP_CS_RANGE_START-1;
 
localparam BURST_LEN_DIV2 = BURST_LEN / 2;
localparam OPEN_BANK_NUM = 4;
localparam CS_BITS_FIX = (CS_BITS == 0) ? 1 : CS_BITS;
 
// calculation counters based on clock cycle and memory parameters
// TRAS: ACTIVE->PRECHARGE interval - 2
localparam integer TRAS_CYC = (TRAS + CLK_PERIOD)/CLK_PERIOD;
// TRCD: ACTIVE->READ/WRITE interval - 3 (for DDR2 factor in ADD_LAT)
localparam integer TRRD_CYC = (TRRD + CLK_PERIOD)/CLK_PERIOD;
localparam integer TRCD_CYC = (((TRCD + CLK_PERIOD)/CLK_PERIOD) >
ADDITIVE_LAT )?
((TRCD+CLK_PERIOD)/ CLK_PERIOD) - ADDITIVE_LAT : 0;
// TRFC: REFRESH->REFRESH, REFRESH->ACTIVE interval - 2
localparam integer TRFC_CYC = (TRFC + CLK_PERIOD)/CLK_PERIOD;
// TRP: PRECHARGE->COMMAND interval - 2
// for precharge all add 1 extra clock cycle
localparam integer TRP_CYC = ((TRP + CLK_PERIOD)/CLK_PERIOD) +1;
// TRTP: READ->PRECHARGE interval - 2 (Al + BL/2 + (max (TRTP, 2tck))-2
localparam integer TRTP_TMP_MIN = (((TRTP + CLK_PERIOD)/CLK_PERIOD) >= 2)?
((TRTP + CLK_PERIOD)/CLK_PERIOD) : 2;
localparam integer TRTP_CYC = TRTP_TMP_MIN + ADDITIVE_LAT
+ BURST_LEN_DIV2 - 2;
// TWR: WRITE->PRECHARGE interval - 2
localparam integer WR_LAT = (DDR_TYPE > 0) ? CAS_LAT + ADDITIVE_LAT - 1 : 1;
localparam integer TWR_CYC = ((TWR + CLK_PERIOD)/CLK_PERIOD) +
WR_LAT + BURST_LEN_DIV2 ;
// TWTR: WRITE->READ interval - 3 (for DDR1, TWTR = 2 clks)
// DDR2 = CL-1 + BL/2 +TWTR
localparam integer TWTR_TMP_MIN = (TWTR + CLK_PERIOD)/CLK_PERIOD;
localparam integer TWTR_CYC = (DDR_TYPE > 0) ? (TWTR_TMP_MIN + (CAS_LAT -1)
+ BURST_LEN_DIV2 ): 2;
 
// TRTW: READ->WRITE interval - 3
// DDR1: CL + (BL/2)
// DDR2: (BL/2) + 2. Two more clocks are added to
// the DDR2 counter to account for the delay in
// arrival of the DQS during reads (pcb trace + buffer
// delays + memory parameters).
localparam TRTW_CYC = (DDR_TYPE > 0) ? BURST_LEN_DIV2 + 4 :
(CAS_LAT == 25) ? 2 + BURST_LEN_DIV2 : CAS_LAT + BURST_LEN_DIV2;
 
localparam integer CAS_LAT_RD = (CAS_LAT == 25) ? 2 : CAS_LAT;
 
// Make sure all values >= 0 (some may be = 0)
localparam TRAS_COUNT = (TRAS_CYC > 0) ? TRAS_CYC : 0;
localparam TRCD_COUNT = (TRCD_CYC > 0) ? TRCD_CYC : 0;
localparam TRRD_COUNT = (TRRD_CYC > 0) ? TRRD_CYC : 0;
localparam TRFC_COUNT = (TRFC_CYC > 0) ? TRFC_CYC : 0;
localparam TRP_COUNT = (TRP_CYC > 0) ? TRP_CYC : 0;
localparam TRTP_COUNT = (TRTP_CYC > 0) ? TRTP_CYC : 0;
localparam TWR_COUNT = (TWR_CYC > 0) ? TWR_CYC : 0;
localparam TWTR_COUNT = (TWTR_CYC > 0) ? TWTR_CYC : 0;
localparam TRTW_COUNT = (TRTW_CYC > 0) ? TRTW_CYC : 0;
 
// Auto refresh interval
localparam TREFI_COUNT = ((TREFI_NS * 1000)/CLK_PERIOD) - 1;
 
// memory controller states
localparam CTRL_IDLE = 5'h00;
localparam CTRL_PRECHARGE = 5'h01;
localparam CTRL_PRECHARGE_WAIT = 5'h02;
localparam CTRL_AUTO_REFRESH = 5'h03;
localparam CTRL_AUTO_REFRESH_WAIT = 5'h04;
localparam CTRL_ACTIVE = 5'h05;
localparam CTRL_ACTIVE_WAIT = 5'h06;
localparam CTRL_BURST_READ = 5'h07;
localparam CTRL_READ_WAIT = 5'h08;
localparam CTRL_BURST_WRITE = 5'h09;
localparam CTRL_WRITE_WAIT = 5'h0A;
localparam CTRL_PRECHARGE_WAIT1 = 5'h0B;
 
 
reg [CMP_WIDTH-1:0] act_addr_r;
wire [30:0] af_addr_r;
reg [30:0] af_addr_r1;
reg [30:0] af_addr_r2;
reg [30:0] af_addr_r3;
wire [2:0] af_cmd_r;
reg [2:0] af_cmd_r1;
reg [2:0] af_cmd_r2;
reg af_valid_r;
reg af_valid_r1;
reg af_valid_r2;
reg [CS_BITS_FIX :0] auto_cnt_r;
reg auto_ref_r;
reg [(OPEN_BANK_NUM*CMP_WIDTH)-1:0] bank_cmp_addr_r;
reg [OPEN_BANK_NUM-1:0] bank_hit;
reg [OPEN_BANK_NUM-1:0] bank_hit_r;
reg [OPEN_BANK_NUM-1:0] bank_hit_r1;
reg [OPEN_BANK_NUM-1:0] bank_valid_r;
reg bank_conflict_r;
reg conflict_resolved_r;
reg ctrl_af_rden_r;
reg conflict_detect_r;
wire conflict_detect;
reg cs_change_r;
reg cs_change_sticky_r;
reg [ROW_WIDTH-1:0] ddr_addr_r;
wire [ROW_WIDTH-1:0] ddr_addr_col;
wire [ROW_WIDTH-1:0] ddr_addr_row;
reg [BANK_WIDTH-1:0] ddr_ba_r;
reg ddr_cas_n_r;
reg [CS_NUM-1:0] ddr_cs_n_r;
reg ddr_ras_n_r;
reg ddr_we_n_r;
reg [4:0] next_state;
reg no_precharge_wait_r;
reg no_precharge_r;
reg no_precharge_r1;
reg phy_init_done_r;
reg [4:0] precharge_ok_cnt_r;
reg precharge_ok_r;
reg [4:0] ras_cnt_r;
reg [3:0] rcd_cnt_r;
reg rcd_cnt_ok_r;
reg [2:0] rdburst_cnt_r;
reg rdburst_ok_r;
reg rdburst_rden_ok_r;
reg rd_af_flag_r;
wire rd_flag;
reg rd_flag_r;
reg [4:0] rd_to_wr_cnt_r;
reg rd_to_wr_ok_r;
reg ref_flag_r;
reg [11:0] refi_cnt_r;
reg refi_cnt_ok_r;
reg rst_r
/* synthesis syn_preserve = 1 */;
reg rst_r1
/* synthesis syn_maxfan = 10 */;
reg [7:0] rfc_cnt_r;
reg rfc_ok_r;
reg [3:0] row_miss;
reg [3:0] row_conflict_r;
reg [3:0] rp_cnt_r;
reg rp_cnt_ok_r;
reg [CMP_WIDTH-1:0] sb_open_add_r;
reg [4:0] state_r;
reg [4:0] state_r1;
wire sm_rden;
reg sm_rden_r;
reg [2:0] trrd_cnt_r;
reg trrd_cnt_ok_r;
reg [2:0] two_t_enable_r;
reg [CS_NUM-1:0] two_t_enable_r1;
reg [2:0] wrburst_cnt_r;
reg wrburst_ok_r;
reg wrburst_wren_ok_r;
wire wr_flag;
reg wr_flag_r;
reg [4:0] wr_to_rd_cnt_r;
reg wr_to_rd_ok_r;
 
// XST attributes for local reset "tree"
// synthesis attribute shreg_extract of rst_r is "no";
// synthesis attribute shreg_extract of rst_r1 is "no";
// synthesis attribute equivalent_register_removal of rst_r is "no"
 
//***************************************************************************
 
// sm_rden is used to assert read enable to the address FIFO
assign sm_rden = ((state_r == CTRL_BURST_WRITE) ||
(state_r == CTRL_BURST_READ)) ;
 
// Assert this when approaching refresh and not in an access
reg ref_approaching;
always @(posedge clk)
ref_approaching <= (refi_cnt_r >= (TREFI_COUNT -80)) & ~af_valid_r2;
reg ref_just_happened;
always @(posedge clk)
ref_just_happened <= (refi_cnt_r < 12'h30) & ~af_valid_r2;
 
// assert read flag to the adress FIFO
assign ctrl_af_rden = (sm_rden || rd_af_flag_r) & !(ref_approaching | ref_just_happened);
 
// local reset "tree" for controller logic only. Create this to ease timing
// on reset path. Prohibit equivalent register removal on RST_R to prevent
// "sharing" with other local reset trees (caution: make sure global fanout
// limit is set to large enough value, otherwise SLICES may be used for
// fanout control on RST_R.
always @(posedge clk) begin
rst_r <= rst;
rst_r1 <= rst_r;
end
 
//*****************************************************************
// interpret commands from Command/Address FIFO
//*****************************************************************
 
assign wr_flag = (af_valid_r2) ? ((af_cmd_r2 == 3'b000) ? 1'b1 : 1'b0): 1'b0;
assign rd_flag = (af_valid_r2) ? ((af_cmd_r2 == 3'b001) ? 1'b1 : 1'b0): 1'b0;
 
always @(posedge clk) begin
rd_flag_r <= rd_flag;
wr_flag_r <= wr_flag;
end
 
//////////////////////////////////////////////////
// The data from the address FIFO is fetched and
// stored in two register stages. The data will be
// pulled out of the second register stage whenever
// the state machine can handle new data from the
// address FIFO.
 
// This flag is asserted when there is no
// cmd & address in the pipe. When there is
// valid cmd & addr from the address FIFO the
// af_valid signals will be asserted. This flag will
// be set the cycle af_valid_r is de-asserted.
always @(posedge clk) begin
// for simulation purposes - to force CTRL_AF_RDEN low during reset
if (rst_r1)
rd_af_flag_r <= 1'd0;
else if (rd_af_flag_r) // jb - probably should find a way to stop this toggling all the time
rd_af_flag_r <= 0; // jb
else if((ctrl_af_rden_r) ||
(/*rd_af_flag_r &&*/ (af_valid_r || af_valid_r1))) // Fixed bug where third addresses would get lost (pulled off fifo and then clobbered by other value later, thus ignored/skipped) - just make sure we don't get too excited and pull too many off at once - jb
rd_af_flag_r <= 1'd0;
else if (~af_valid_r1 || ~af_valid_r)
rd_af_flag_r <= 1'd1;
 
end // always @ (posedge clk)
 
 
// First register stage for the cmd & add from the FIFO.
// The af_valid_r signal gives the status of the data
// in this stage. The af_valid_r will be asserted when there
// is valid data. This register stage will be updated
// 1. read to the FIFO and the FIFO not empty
// 2. After write and read states
// 3. The valid signal is not asserted in the last stage.
always @(posedge clk) begin
if (rst_r1)begin
af_valid_r <= 1'd0;
end else begin
if (ctrl_af_rden_r || sm_rden_r || ~af_valid_r1
|| ~af_valid_r2)begin
af_valid_r <= ctrl_af_rden_r;
end
end
end
 
// The output register in the FIFO is used. The addr
// and command are already registered in the FIFO.
assign af_addr_r = af_addr;
assign af_cmd_r = af_cmd;
 
// Second register stage for the cmd & add from the FIFO.
// The af_valid_r1 signal gives the status of the data
// in this stage. The af_valid_r will be asserted when there
// is valid data. This register stage will be updated
// 1. read to the FIFO and the FIFO not empty and there
// is no valid data on this stage
// 2. After write and read states
// 3. The valid signal is not asserted in the last stage.
always@(posedge clk) begin
if (rst_r1)begin
af_valid_r1 <= 1'd0;
af_addr_r1 <= {31{1'bx}};
af_cmd_r1 <= {3{1'bx}};
end else if (~af_valid_r1 || sm_rden_r ||
~af_valid_r2) begin
af_valid_r1 <= af_valid_r;
af_addr_r1 <= af_addr_r;
af_cmd_r1 <= af_cmd_r;
end
end
 
// The state machine uses the address and command in this
// register stage. The data is fetched from the second
// register stage whenever the state machine can accept new
// addr. The conflict flags are also generated based on the
// second register stage and updated when the new address
// is loaded for the state machine.
always@(posedge clk) begin
if (rst_r1)begin
af_valid_r2 <= 1'd0;
af_addr_r2 <= {31{1'bx}};
af_cmd_r2 <= {3{1'bx}};
bank_hit_r <= {OPEN_BANK_NUM{1'bx}};
bank_conflict_r <= 1'bx;
row_conflict_r <= 4'bx;
end else if(sm_rden || ~af_valid_r2)begin
af_valid_r2 <= af_valid_r1;
af_addr_r2 <= af_addr_r1;
af_cmd_r2 <= af_cmd_r1;
if(MULTI_BANK_EN)begin
bank_hit_r <= bank_hit;
row_conflict_r <= row_miss;
bank_conflict_r <= (~(|bank_hit));
end else begin
bank_hit_r <= {OPEN_BANK_NUM{1'b0}};
bank_conflict_r <= 1'd0;
row_conflict_r[0] <= (af_addr_r1[CS_RANGE_END:ROW_RANGE_START]
!= sb_open_add_r[CMP_WIDTH-1:0]);
end
end
end // always@ (posedge clk)
 
//detecting cs change for multi chip select case
generate
if(CS_NUM > 1) begin: gen_cs_change
always @(posedge clk) begin
if(sm_rden || ~af_valid_r2)begin
cs_change_r <= af_addr_r1[CS_RANGE_END:CS_RANGE_START] !=
af_addr_r2[CS_RANGE_END:CS_RANGE_START] ;
cs_change_sticky_r <=
af_addr_r1[CS_RANGE_END:CS_RANGE_START] !=
af_addr_r2[CS_RANGE_END:CS_RANGE_START] ;
end else
cs_change_r <= 1'd0;
end
end // block: gen_cs_change
else begin: gen_cs_0
always @(posedge clk) begin
cs_change_r <= 1'd0;
cs_change_sticky_r <= 1'd0;
end
end
endgenerate
 
assign conflict_detect = (MULTI_BANK_EN) ?
((|(row_conflict_r[3:0] & bank_hit_r[3:0]))
| bank_conflict_r) & af_valid_r2 :
row_conflict_r[0] & af_valid_r2;
 
always @(posedge clk) begin
conflict_detect_r <= conflict_detect;
sm_rden_r <= sm_rden;
af_addr_r3 <= af_addr_r2;
ctrl_af_rden_r <= ctrl_af_rden & ~af_empty;
end
 
// conflict resolved signal. When this signal is asserted
// the conflict is resolved. The address to be compared
// for the conflict_resolved_r will be stored in act_add_r
// when the bank is opened.
always @(posedge clk) begin
conflict_resolved_r <= (act_addr_r ==
af_addr_r2[CS_RANGE_END:ROW_RANGE_START]);
if((state_r == CTRL_ACTIVE))
act_addr_r <= af_addr_r2[CS_RANGE_END:ROW_RANGE_START];
end
 
//***************************************************************************
// Bank management logic
// Semi-hardcoded for now for 4 banks
// will keep multiple banks open if MULTI_BANK_EN is true.
//***************************************************************************
 
genvar bank_i;
generate // if multiple bank option chosen
if(MULTI_BANK_EN) begin: gen_multi_bank_open
 
for (bank_i = 0; bank_i < OPEN_BANK_NUM;
bank_i = bank_i + 1) begin: gen_bank_hit1
// asserted if bank address match + open bank entry is valid
always @(*) begin
bank_hit[bank_i]
= ((bank_cmp_addr_r[(CMP_WIDTH*(bank_i+1))-1:
(CMP_WIDTH*bank_i)+ROW_WIDTH] ==
af_addr_r1[CS_RANGE_END:BANK_RANGE_START]) &&
bank_valid_r[bank_i]);
// asserted if row address match (no check for bank entry valid, rely
// on this term to be used in conjunction with BANK_HIT[])
row_miss[bank_i]
= (bank_cmp_addr_r[(CMP_WIDTH*bank_i)+ROW_WIDTH-1:
(CMP_WIDTH*bank_i)] !=
af_addr_r1[ROW_RANGE_END:ROW_RANGE_START]);
end
end
 
always @(posedge clk) begin
no_precharge_wait_r <= bank_valid_r[3] & bank_conflict_r;
bank_hit_r1 <= bank_hit_r;
end
 
always@(*)
no_precharge_r = ~bank_valid_r[3] & bank_conflict_r;
 
always@(posedge clk)
no_precharge_r1 <= no_precharge_r;
 
 
always @(posedge clk) begin
// Clear all bank valid bits during AR (i.e. since all banks get
// precharged during auto-refresh)
if ((state_r1 == CTRL_AUTO_REFRESH)) begin
bank_valid_r <= {OPEN_BANK_NUM{1'b0}};
bank_cmp_addr_r <= {(OPEN_BANK_NUM*CMP_WIDTH-1){1'b0}};
end else begin
if (state_r1 == CTRL_ACTIVE) begin
// 00 is always going to have the latest bank and row.
bank_cmp_addr_r[CMP_WIDTH-1:0]
<= af_addr_r3[CS_RANGE_END:ROW_RANGE_START];
// This indicates the bank was activated
bank_valid_r[0] <= 1'b1;
 
case ({bank_hit_r1[2:0]})
3'b001: begin
bank_cmp_addr_r[CMP_WIDTH-1:0]
<= af_addr_r3[CS_RANGE_END:ROW_RANGE_START];
// This indicates the bank was activated
bank_valid_r[0] <= 1'b1;
end
3'b010: begin //(b0->b1)
bank_cmp_addr_r[(2*CMP_WIDTH)-1:CMP_WIDTH]
<= bank_cmp_addr_r[CMP_WIDTH-1:0];
bank_valid_r[1] <= bank_valid_r[0];
end
3'b100:begin //(b0->b1, b1->b2)
bank_cmp_addr_r[(2*CMP_WIDTH)-1:CMP_WIDTH]
<= bank_cmp_addr_r[CMP_WIDTH-1:0];
bank_cmp_addr_r[(3*CMP_WIDTH)-1:2*CMP_WIDTH]
<= bank_cmp_addr_r[(2*CMP_WIDTH)-1:CMP_WIDTH];
bank_valid_r[1] <= bank_valid_r[0];
bank_valid_r[2] <= bank_valid_r[1];
end
default: begin //(b0->b1, b1->b2, b2->b3)
bank_cmp_addr_r[(2*CMP_WIDTH)-1:CMP_WIDTH]
<= bank_cmp_addr_r[CMP_WIDTH-1:0];
bank_cmp_addr_r[(3*CMP_WIDTH)-1:2*CMP_WIDTH]
<= bank_cmp_addr_r[(2*CMP_WIDTH)-1:CMP_WIDTH];
bank_cmp_addr_r[(4*CMP_WIDTH)-1:3*CMP_WIDTH]
<= bank_cmp_addr_r[(3*CMP_WIDTH)-1:2*CMP_WIDTH];
bank_valid_r[1] <= bank_valid_r[0];
bank_valid_r[2] <= bank_valid_r[1];
bank_valid_r[3] <= bank_valid_r[2];
end
endcase
end
end
end
end else begin: gen_single_bank_open // single bank option
always @(posedge clk) begin
no_precharge_r <= 1'd0;
no_precharge_r1 <= 1'd0;
no_precharge_wait_r <= 1'd0;
if (rst_r1)
sb_open_add_r <= {CMP_WIDTH{1'b0}};
else if (state_r == CTRL_ACTIVE)
sb_open_add_r <= af_addr_r2[CS_RANGE_END:ROW_RANGE_START];
end
end
endgenerate
 
//***************************************************************************
// Timing counters
//***************************************************************************
 
//*****************************************************************
// Write and read enable generation for PHY
//*****************************************************************
 
// write burst count. Counts from (BL/2 to 1).
// Also logic for controller write enable.
always @(posedge clk) begin
if (state_r == CTRL_BURST_WRITE) begin
wrburst_cnt_r <= BURST_LEN_DIV2;
end else if (wrburst_cnt_r >= 3'd1)
wrburst_cnt_r <= wrburst_cnt_r - 1;
end // always @ (posedge clk)
 
 
always @(posedge clk) begin
if (rst_r1) begin
ctrl_wren <= 1'b0;
end else if (state_r == CTRL_BURST_WRITE) begin
ctrl_wren <= 1'b1;
end else if (wrburst_wren_ok_r)
ctrl_wren <= 1'b0;
end
 
 
always @(posedge clk) begin
if ((state_r == CTRL_BURST_WRITE)
&& (BURST_LEN_DIV2 > 2))
wrburst_ok_r <= 1'd0;
else if ((wrburst_cnt_r <= 3'd3) ||
(BURST_LEN_DIV2 <= 2))
wrburst_ok_r <= 1'b1;
end
 
// flag to check when wrburst count has reached
// a value of 1. This flag is used in the ctrl_wren
// logic
always @(posedge clk) begin
if(wrburst_cnt_r == 3'd2)
wrburst_wren_ok_r <=1'b1;
else
wrburst_wren_ok_r <= 1'b0;
end
 
 
// read burst count. Counts from (BL/2 to 1)
always @(posedge clk) begin
if (state_r == CTRL_BURST_READ) begin
rdburst_cnt_r <= BURST_LEN_DIV2;
end else if (rdburst_cnt_r >= 3'd1)
rdburst_cnt_r <= rdburst_cnt_r - 1;
end // always @ (posedge clk)
 
 
always @(posedge clk) begin
if (rst_r1) begin
ctrl_rden <= 1'b0;
end else if (state_r == CTRL_BURST_READ) begin
ctrl_rden <= 1'b1;
end else if (rdburst_rden_ok_r)
ctrl_rden <= 1'b0;
end
 
// the rd_burst_ok_r signal will be asserted one cycle later
// in multi chip select cases if the back to back read is to
// different chip selects. The cs_changed_sticky_r signal will
// be asserted only for multi chip select cases.
always @(posedge clk) begin
if ((state_r == CTRL_BURST_READ)
&& (BURST_LEN_DIV2 > 2))
rdburst_ok_r <= 1'd0;
else if ((rdburst_cnt_r <=( 3'd3 - cs_change_sticky_r)) ||
(BURST_LEN_DIV2 <= 2))
rdburst_ok_r <= 1'b1;
end
 
// flag to check when rdburst count has reached
// a value of 1. This flag is used in the ctrl_rden
// logic
always @(posedge clk) begin
if (rdburst_cnt_r == 3'd2)
rdburst_rden_ok_r <= 1'b1;
else
rdburst_rden_ok_r <= 1'b0;
end
 
 
//*****************************************************************
// Various delay counters
// The counters are checked for value of <= 3 to determine the
// if the count values are reached during different commands.
// It is checked for 3 because
// 1. The counters are loaded during the state when the command
// state is reached (+1)
// 2. After the <= 3 condition is reached the sm takes two cycles
// to transition to the new command state (+2)
//*****************************************************************
 
// tRP count - precharge command period
always @(posedge clk) begin
if (state_r == CTRL_PRECHARGE)
rp_cnt_r <= TRP_COUNT;
else if (rp_cnt_r != 4'd0)
rp_cnt_r <= rp_cnt_r - 1;
end
 
always @(posedge clk) begin
if (state_r == CTRL_PRECHARGE)
rp_cnt_ok_r <= 1'd0;
else if (rp_cnt_r <= 4'd3)
rp_cnt_ok_r <= 1'd1;
end
 
// tRFC count - refresh-refresh, refresh-active
always @(posedge clk) begin
if (state_r == CTRL_AUTO_REFRESH)
rfc_cnt_r <= TRFC_COUNT;
else if (rfc_cnt_r != 8'd0)
rfc_cnt_r <= rfc_cnt_r - 1;
end
 
always @(posedge clk) begin
if (state_r == CTRL_AUTO_REFRESH)
rfc_ok_r <= 1'b0;
else if(rfc_cnt_r <= 8'd3)
rfc_ok_r <= 1'b1;
end
 
// tRCD count - active to read/write
always @(posedge clk) begin
if (state_r == CTRL_ACTIVE)
rcd_cnt_r <= TRCD_COUNT;
else if (rcd_cnt_r != 4'd0)
rcd_cnt_r <= rcd_cnt_r - 1;
end
 
always @(posedge clk) begin
if ((state_r == CTRL_ACTIVE)
&& (TRCD_COUNT > 2))
rcd_cnt_ok_r <= 1'd0;
else if (rcd_cnt_r <= 4'd3)
rcd_cnt_ok_r <= 1;
end
 
// tRRD count - active to active
always @(posedge clk) begin
if (state_r == CTRL_ACTIVE)
trrd_cnt_r <= TRRD_COUNT;
else if (trrd_cnt_r != 3'd0)
trrd_cnt_r <= trrd_cnt_r - 1;
end
 
always @(posedge clk) begin
if (state_r == CTRL_ACTIVE)
trrd_cnt_ok_r <= 1'd0;
else if (trrd_cnt_r <= 3'd3)
trrd_cnt_ok_r <= 1;
end
 
// tRAS count - active to precharge
always @(posedge clk) begin
if (state_r == CTRL_ACTIVE)
ras_cnt_r <= TRAS_COUNT;
else if (ras_cnt_r != 5'd0)
ras_cnt_r <= ras_cnt_r - 1;
end
 
// counter for write to prcharge
// read to precharge and
// activate to precharge
// precharge_ok_cnt_r is added with trtp count,
// there can be cases where the sm can go from
// activate to read and the act->pre count time
// would not have been satisfied. The rd->pre
// time is very less. wr->pre time is almost the
// same as act-> pre
always @(posedge clk) begin
if (state_r == CTRL_BURST_READ) begin
// assign only if the cnt is < TRTP_COUNT
if (precharge_ok_cnt_r < TRTP_COUNT)
precharge_ok_cnt_r <= TRTP_COUNT;
end else if (state_r == CTRL_BURST_WRITE)
precharge_ok_cnt_r <= TWR_COUNT;
else if (state_r == CTRL_ACTIVE)
precharge_ok_cnt_r <= TRAS_COUNT;
else if (precharge_ok_cnt_r != 5'd0)
precharge_ok_cnt_r <= precharge_ok_cnt_r - 1;
end
 
always @(posedge clk) begin
if ((state_r == CTRL_BURST_READ) ||
(state_r == CTRL_BURST_WRITE)||
(state_r == CTRL_ACTIVE))
precharge_ok_r <= 1'd0;
else if(precharge_ok_cnt_r <= 5'd3)
precharge_ok_r <=1'd1;
end
 
// write to read counter
// write to read includes : write latency + burst time + tWTR
always @(posedge clk) begin
if (rst_r1)
wr_to_rd_cnt_r <= 5'd0;
else if (state_r == CTRL_BURST_WRITE)
wr_to_rd_cnt_r <= (TWTR_COUNT);
else if (wr_to_rd_cnt_r != 5'd0)
wr_to_rd_cnt_r <= wr_to_rd_cnt_r - 1;
end
 
always @(posedge clk) begin
if (state_r == CTRL_BURST_WRITE)
wr_to_rd_ok_r <= 1'd0;
else if (wr_to_rd_cnt_r <= 5'd3)
wr_to_rd_ok_r <= 1'd1;
end
 
// read to write counter
always @(posedge clk) begin
if (rst_r1)
rd_to_wr_cnt_r <= 5'd0;
else if (state_r == CTRL_BURST_READ)
rd_to_wr_cnt_r <= (TRTW_COUNT);
else if (rd_to_wr_cnt_r != 5'd0)
rd_to_wr_cnt_r <= rd_to_wr_cnt_r - 1;
end
 
always @(posedge clk) begin
if (state_r == CTRL_BURST_READ)
rd_to_wr_ok_r <= 1'b0;
else if (rd_to_wr_cnt_r <= 5'd3)
rd_to_wr_ok_r <= 1'b1;
end
 
always @(posedge clk) begin
if(refi_cnt_r == (TREFI_COUNT -1))
refi_cnt_ok_r <= 1'b1;
else
refi_cnt_ok_r <= 1'b0;
end
 
// auto refresh interval counter in refresh_clk domain
always @(posedge clk) begin
if ((rst_r1) || (refi_cnt_ok_r)) begin
refi_cnt_r <= 12'd0;
end else begin
refi_cnt_r <= refi_cnt_r + 1;
end
end // always @ (posedge clk)
 
// auto refresh flag
always @(posedge clk) begin
if (refi_cnt_ok_r) begin
ref_flag_r <= 1'b1;
end else begin
ref_flag_r <= 1'b0;
end
end // always @ (posedge clk)
 
assign ctrl_ref_flag = ref_flag_r;
 
//refresh flag detect
//auto_ref high indicates auto_refresh requirement
//auto_ref is held high until auto refresh command is issued.
always @(posedge clk)begin
if (rst_r1)
auto_ref_r <= 1'b0;
else if (ref_flag_r)
auto_ref_r <= 1'b1;
else if (state_r == CTRL_AUTO_REFRESH)
auto_ref_r <= 1'b0;
end
 
 
// keep track of which chip selects got auto-refreshed (avoid auto-refreshing
// all CS's at once to avoid current spike)
always @(posedge clk)begin
if (rst_r1 || (state_r1 == CTRL_PRECHARGE))
auto_cnt_r <= 'd0;
else if (state_r1 == CTRL_AUTO_REFRESH)
auto_cnt_r <= auto_cnt_r + 1;
end
 
// register for timing purposes. Extra delay doesn't really matter
always @(posedge clk)
phy_init_done_r <= phy_init_done;
 
always @(posedge clk)begin
if (rst_r1) begin
state_r <= CTRL_IDLE;
state_r1 <= CTRL_IDLE;
end else begin
state_r <= next_state;
state_r1 <= state_r;
end
end
 
//***************************************************************************
// main control state machine
//***************************************************************************
 
always @(*) begin
next_state = state_r;
(* full_case, parallel_case *) case (state_r)
CTRL_IDLE: begin
// perform auto refresh as soon as we are done with calibration.
// The calibration logic does not do any refreshes.
if (phy_init_done_r)
next_state = CTRL_AUTO_REFRESH;
end
 
CTRL_PRECHARGE: begin
if (auto_ref_r)
next_state = CTRL_PRECHARGE_WAIT1;
// when precharging an LRU bank, do not have to go to wait state
// since we can't possibly be activating row in same bank next
// disabled for 2t timing. There needs to be a gap between cmds
// in 2t timing
else if (no_precharge_wait_r && !TWO_T_TIME_EN)
next_state = CTRL_ACTIVE;
else
next_state = CTRL_PRECHARGE_WAIT;
end
 
CTRL_PRECHARGE_WAIT:begin
if (rp_cnt_ok_r)begin
if (auto_ref_r)
// precharge again to make sure we close all the banks
next_state = CTRL_PRECHARGE;
else
next_state = CTRL_ACTIVE;
end
end
 
CTRL_PRECHARGE_WAIT1:
if (rp_cnt_ok_r)
next_state = CTRL_AUTO_REFRESH;
 
CTRL_AUTO_REFRESH:
next_state = CTRL_AUTO_REFRESH_WAIT;
 
CTRL_AUTO_REFRESH_WAIT:
//staggering Auto refresh for multi
// chip select designs. The SM waits
// for the rfc time before issuing the
// next auto refresh.
if (auto_cnt_r < (CS_NUM))begin
if (rfc_ok_r )
next_state = CTRL_AUTO_REFRESH;
end else if (rfc_ok_r)begin
if(auto_ref_r)
// MIG 2.3: For deep designs if Auto Refresh
// flag asserted immediately after calibration is completed
next_state = CTRL_PRECHARGE;
else if ( wr_flag || rd_flag)
next_state = CTRL_ACTIVE;
end
 
CTRL_ACTIVE:
next_state = CTRL_ACTIVE_WAIT;
 
CTRL_ACTIVE_WAIT: begin
if (rcd_cnt_ok_r) begin
if ((conflict_detect_r && ~conflict_resolved_r) ||
auto_ref_r) begin
if (no_precharge_r1 && ~auto_ref_r && trrd_cnt_ok_r)
next_state = CTRL_ACTIVE;
else if(precharge_ok_r)
next_state = CTRL_PRECHARGE;
end else if ((wr_flag_r) && (rd_to_wr_ok_r))
next_state = CTRL_BURST_WRITE;
else if ((rd_flag_r)&& (wr_to_rd_ok_r))
next_state = CTRL_BURST_READ;
end
end
 
// beginning of write burst
CTRL_BURST_WRITE: begin
if (BURST_LEN_DIV2 == 1) begin
// special case if BL = 2 (i.e. burst lasts only one clk cycle)
if (wr_flag)
// if we have another non-conflict write command right after the
// current write, then stay in this state
next_state = CTRL_BURST_WRITE;
else
// otherwise, if we're done with this burst, and have no write
// immediately scheduled after this one, wait until write-read
// delay has passed
next_state = CTRL_WRITE_WAIT;
end else
// otherwise BL > 2, and we have at least one more write cycle for
// current burst
next_state = CTRL_WRITE_WAIT;
// continuation of write burst (also covers waiting after write burst
// has completed for write-read delay to pass)
end
 
CTRL_WRITE_WAIT: begin
if ((conflict_detect) || auto_ref_r) begin
if (no_precharge_r && ~auto_ref_r && wrburst_ok_r)
next_state = CTRL_ACTIVE;
else if (precharge_ok_r)
next_state = CTRL_PRECHARGE;
end else if (wrburst_ok_r && wr_flag)
next_state = CTRL_BURST_WRITE;
else if ((rd_flag) && (wr_to_rd_ok_r))
next_state = CTRL_BURST_READ;
end
 
CTRL_BURST_READ: begin
if (BURST_LEN_DIV2 == 1) begin
// special case if BL = 2 (i.e. burst lasts only one clk cycle)
if (rd_flag)
next_state = CTRL_BURST_READ;
else
next_state = CTRL_READ_WAIT;
end else
next_state = CTRL_READ_WAIT;
end
 
CTRL_READ_WAIT: begin
if ((conflict_detect) || auto_ref_r)begin
if (no_precharge_r && ~auto_ref_r && rdburst_ok_r)
next_state = CTRL_ACTIVE;
else if (precharge_ok_r)
next_state = CTRL_PRECHARGE;
// for burst of 4 in multi chip select
// if there is a change in cs wait one cycle before the
// next read command. cs_change_r will be asserted.
end else if (rdburst_ok_r && rd_flag && ~cs_change_r)
next_state = CTRL_BURST_READ;
else if (wr_flag && (rd_to_wr_ok_r))
next_state = CTRL_BURST_WRITE;
end
endcase
end
 
//***************************************************************************
// control signals to memory
//***************************************************************************
 
always @(posedge clk) begin
if ((state_r == CTRL_AUTO_REFRESH) ||
(state_r == CTRL_ACTIVE) ||
(state_r == CTRL_PRECHARGE)) begin
ddr_ras_n_r <= 1'b0;
two_t_enable_r[0] <= 1'b0;
end else begin
if (TWO_T_TIME_EN)
ddr_ras_n_r <= two_t_enable_r[0] ;
else
ddr_ras_n_r <= 1'd1;
two_t_enable_r[0] <= 1'b1;
end
end
 
always @(posedge clk)begin
if ((state_r == CTRL_BURST_WRITE) ||
(state_r == CTRL_BURST_READ) ||
(state_r == CTRL_AUTO_REFRESH)) begin
ddr_cas_n_r <= 1'b0;
two_t_enable_r[1] <= 1'b0;
end else begin
if (TWO_T_TIME_EN)
ddr_cas_n_r <= two_t_enable_r[1];
else
ddr_cas_n_r <= 1'b1;
two_t_enable_r[1] <= 1'b1;
end
end
 
always @(posedge clk) begin
if ((state_r == CTRL_BURST_WRITE) ||
(state_r == CTRL_PRECHARGE)) begin
ddr_we_n_r <= 1'b0;
two_t_enable_r[2] <= 1'b0;
end else begin
if(TWO_T_TIME_EN)
ddr_we_n_r <= two_t_enable_r[2];
else
ddr_we_n_r <= 1'b1;
two_t_enable_r[2] <= 1'b1;
end
end
 
// turn off auto-precharge when issuing commands (A10 = 0)
// mapping the col add for linear addressing.
generate
if (TWO_T_TIME_EN) begin: gen_addr_col_two_t
if (COL_WIDTH == ROW_WIDTH-1) begin: gen_ddr_addr_col_0
assign ddr_addr_col = {af_addr_r3[COL_WIDTH-1:10], 1'b0,
af_addr_r3[9:0]};
end else begin
if (COL_WIDTH > 10) begin: gen_ddr_addr_col_1
assign ddr_addr_col = {{(ROW_WIDTH-COL_WIDTH-1){1'b0}},
af_addr_r3[COL_WIDTH-1:10], 1'b0,
af_addr_r3[9:0]};
end else begin: gen_ddr_addr_col_2
assign ddr_addr_col = {{(ROW_WIDTH-COL_WIDTH-1){1'b0}}, 1'b0,
af_addr_r3[COL_WIDTH-1:0]};
end
end
end else begin: gen_addr_col_one_t
if (COL_WIDTH == ROW_WIDTH-1) begin: gen_ddr_addr_col_0_1
assign ddr_addr_col = {af_addr_r2[COL_WIDTH-1:10], 1'b0,
af_addr_r2[9:0]};
end else begin
if (COL_WIDTH > 10) begin: gen_ddr_addr_col_1_1
assign ddr_addr_col = {{(ROW_WIDTH-COL_WIDTH-1){1'b0}},
af_addr_r2[COL_WIDTH-1:10], 1'b0,
af_addr_r2[9:0]};
end else begin: gen_ddr_addr_col_2_1
assign ddr_addr_col = {{(ROW_WIDTH-COL_WIDTH-1){1'b0}}, 1'b0,
af_addr_r2[COL_WIDTH-1:0]};
end
end
end
endgenerate
 
// Assign address during row activate
generate
if (TWO_T_TIME_EN)
assign ddr_addr_row = af_addr_r3[ROW_RANGE_END:ROW_RANGE_START];
else
assign ddr_addr_row = af_addr_r2[ROW_RANGE_END:ROW_RANGE_START];
endgenerate
 
 
always @(posedge clk)begin
if ((state_r == CTRL_ACTIVE) ||
((state_r1 == CTRL_ACTIVE) && TWO_T_TIME_EN))
ddr_addr_r <= ddr_addr_row;
else if ((state_r == CTRL_BURST_WRITE) ||
(state_r == CTRL_BURST_READ) ||
(((state_r1 == CTRL_BURST_WRITE) ||
(state_r1 == CTRL_BURST_READ)) &&
TWO_T_TIME_EN))
ddr_addr_r <= ddr_addr_col;
else if (((state_r == CTRL_PRECHARGE) ||
((state_r1 == CTRL_PRECHARGE) && TWO_T_TIME_EN))
&& auto_ref_r) begin
// if we're precharging as a result of AUTO-REFRESH, precharge all banks
ddr_addr_r <= {ROW_WIDTH{1'b0}};
ddr_addr_r[10] <= 1'b1;
end else if ((state_r == CTRL_PRECHARGE) ||
((state_r1 == CTRL_PRECHARGE) && TWO_T_TIME_EN))
// if we're precharging to close a specific bank/row, set A10=0
ddr_addr_r <= {ROW_WIDTH{1'b0}};
else
ddr_addr_r <= {ROW_WIDTH{1'bx}};
end
 
always @(posedge clk)begin
// whenever we're precharging, we're either: (1) precharging all banks (in
// which case banks bits are don't care, (2) precharging the LRU bank,
// b/c we've exceeded the limit of # of banks open (need to close the LRU
// bank to make room for a new one), (3) we haven't exceed the maximum #
// of banks open, but we trying to open a different row in a bank that's
// already open
if (((state_r == CTRL_PRECHARGE) ||
((state_r1 == CTRL_PRECHARGE) && TWO_T_TIME_EN)) &&
bank_conflict_r && MULTI_BANK_EN)
// When LRU bank needs to be closed
ddr_ba_r <= bank_cmp_addr_r[(3*CMP_WIDTH)+CMP_BANK_RANGE_END:
(3*CMP_WIDTH)+CMP_BANK_RANGE_START];
else begin
// Either precharge due to refresh or bank hit case
if (TWO_T_TIME_EN)
ddr_ba_r <= af_addr_r3[BANK_RANGE_END:BANK_RANGE_START];
else
ddr_ba_r <= af_addr_r2[BANK_RANGE_END:BANK_RANGE_START];
end
end
 
// chip enable generation logic
generate
// if only one chip select, always assert it after reset
if (CS_BITS == 0) begin: gen_ddr_cs_0
always @(posedge clk)
if (rst_r1)
ddr_cs_n_r[0] <= 1'b1;
else
ddr_cs_n_r[0] <= 1'b0;
// otherwise if we have multiple chip selects
end else begin: gen_ddr_cs_1
if(TWO_T_TIME_EN) begin: gen_2t_cs
always @(posedge clk)
if (rst_r1)
ddr_cs_n_r <= {CS_NUM{1'b1}};
else if ((state_r1 == CTRL_AUTO_REFRESH)) begin
// if auto-refreshing, only auto-refresh one CS at any time (avoid
// beating on the ground plane by refreshing all CS's at same time)
ddr_cs_n_r <= {CS_NUM{1'b1}};
ddr_cs_n_r[auto_cnt_r] <= 1'b0;
end else if (auto_ref_r && (state_r1 == CTRL_PRECHARGE)) begin
ddr_cs_n_r <= {CS_NUM{1'b0}};
end else if ((state_r1 == CTRL_PRECHARGE) && ( bank_conflict_r
&& MULTI_BANK_EN))begin
// precharging the LRU bank
ddr_cs_n_r <= {CS_NUM{1'b1}};
ddr_cs_n_r[bank_cmp_addr_r[(3*CMP_WIDTH)+CMP_CS_RANGE_END:
(3*CMP_WIDTH)+CMP_CS_RANGE_START]] <= 1'b0;
end else begin
// otherwise, check the upper address bits to see which CS to assert
ddr_cs_n_r <= {CS_NUM{1'b1}};
ddr_cs_n_r[af_addr_r3[CS_RANGE_END:CS_RANGE_START]] <= 1'b0;
end // else: !if(((state_r == CTRL_PRECHARGE) ||...
end else begin: gen_1t_cs // block: gen_2t_cs
always @(posedge clk)
if (rst_r1)
ddr_cs_n_r <= {CS_NUM{1'b1}};
else if ((state_r == CTRL_AUTO_REFRESH) ) begin
// if auto-refreshing, only auto-refresh one CS at any time (avoid
// beating on the ground plane by refreshing all CS's at same time)
ddr_cs_n_r <= {CS_NUM{1'b1}};
ddr_cs_n_r[auto_cnt_r] <= 1'b0;
end else if (auto_ref_r && (state_r == CTRL_PRECHARGE) ) begin
ddr_cs_n_r <= {CS_NUM{1'b0}};
end else if ((state_r == CTRL_PRECHARGE) &&
(bank_conflict_r && MULTI_BANK_EN))begin
// precharging the LRU bank
ddr_cs_n_r <= {CS_NUM{1'b1}};
ddr_cs_n_r[bank_cmp_addr_r[(3*CMP_WIDTH)+CMP_CS_RANGE_END:
(3*CMP_WIDTH)+CMP_CS_RANGE_START]] <= 1'b0;
end else begin
// otherwise, check the upper address bits to see which CS to assert
ddr_cs_n_r <= {CS_NUM{1'b1}};
ddr_cs_n_r[af_addr_r2[CS_RANGE_END:CS_RANGE_START]] <= 1'b0;
end // else: !if(((state_r == CTRL_PRECHARGE) ||...
end // block: gen_1t_cs
end
endgenerate
 
// registring the two_t timing enable signal.
// This signal will be asserted (low) when the
// chip select has to be asserted.
always @(posedge clk)begin
if(&two_t_enable_r)
two_t_enable_r1 <= {CS_NUM{1'b1}};
else
two_t_enable_r1 <= {CS_NUM{1'b0}};
end
 
assign ctrl_addr = ddr_addr_r;
assign ctrl_ba = ddr_ba_r;
assign ctrl_ras_n = ddr_ras_n_r;
assign ctrl_cas_n = ddr_cas_n_r;
assign ctrl_we_n = ddr_we_n_r;
assign ctrl_cs_n = (TWO_T_TIME_EN) ?
(ddr_cs_n_r | two_t_enable_r1) :
ddr_cs_n_r;
 
endmodule
 
/verilog/xilinx_ddr2/ddr2_usr_addr_fifo.v
0,0 → 1,133
//*****************************************************************************
// DISCLAIMER OF LIABILITY
//
// This file contains proprietary and confidential information of
// Xilinx, Inc. ("Xilinx"), that is distributed under a license
// from Xilinx, and may be used, copied and/or disclosed only
// pursuant to the terms of a valid license agreement with Xilinx.
//
// XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION
// ("MATERIALS") "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
// EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING WITHOUT
// LIMITATION, ANY WARRANTY WITH RESPECT TO NONINFRINGEMENT,
// MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE. Xilinx
// does not warrant that functions included in the Materials will
// meet the requirements of Licensee, or that the operation of the
// Materials will be uninterrupted or error-free, or that defects
// in the Materials will be corrected. Furthermore, Xilinx does
// not warrant or make any representations regarding use, or the
// results of the use, of the Materials in terms of correctness,
// accuracy, reliability or otherwise.
//
// Xilinx products are not designed or intended to be fail-safe,
// or for use in any application requiring fail-safe performance,
// such as life-support or safety devices or systems, Class III
// medical devices, nuclear facilities, applications related to
// the deployment of airbags, or any other applications that could
// lead to death, personal injury or severe property or
// environmental damage (individually and collectively, "critical
// applications"). Customer assumes the sole risk and liability
// of any use of Xilinx products in critical applications,
// subject only to applicable laws and regulations governing
// limitations on product liability.
//
// Copyright 2006, 2007 Xilinx, Inc.
// All rights reserved.
//
// This disclaimer and copyright notice must be retained as part
// of this file at all times.
//*****************************************************************************
// ____ ____
// / /\/ /
// /___/ \ / Vendor: Xilinx
// \ \ \/ Version: 3.0
// \ \ Application: MIG
// / / Filename: ddr2_usr_addr_fifo.v
// /___/ /\ Date Last Modified: $Date: 2008/12/23 14:26:01 $
// \ \ / \ Date Created: Mon Aug 28 2006
// \___\/\___\
//
//Device: Virtex-5
//Design Name: DDR2
//Purpose:
// This module instantiates the block RAM based FIFO to store the user
// address and the command information. Also calculates potential bank/row
// conflicts by comparing the new address with last address issued.
//Reference:
//Revision History:
//*****************************************************************************
 
`timescale 1ns/1ps
 
module ddr2_usr_addr_fifo #
(
// Following parameters are for 72-bit RDIMM design (for ML561 Reference
// board design). Actual values may be different. Actual parameters values
// are passed from design top module ddr2_mig module. Please refer to
// the ddr2_mig module for actual values.
parameter BANK_WIDTH = 2,
parameter COL_WIDTH = 10,
parameter CS_BITS = 0,
parameter ROW_WIDTH = 14
)
(
input clk0,
input rst0,
input usr_clk,
input [2:0] app_af_cmd,
input [30:0] app_af_addr,
input app_af_wren,
input ctrl_af_rden,
output [2:0] af_cmd,
output [30:0] af_addr,
output af_empty,
output app_af_afull
);
 
wire [35:0] fifo_data_out;
reg rst_r;
 
 
always @(posedge clk0)
rst_r <= rst0;
 
 
//***************************************************************************
 
assign af_cmd = fifo_data_out[33:31];
assign af_addr = fifo_data_out[30:0];
 
//***************************************************************************
 
FIFO36 #
(
.ALMOST_EMPTY_OFFSET (13'h0007),
.ALMOST_FULL_OFFSET (13'h000F),
.DATA_WIDTH (36),
.DO_REG (1),
.EN_SYN ("FALSE"), // changed to FALSE - jb
.FIRST_WORD_FALL_THROUGH ("FALSE")
)
u_af
(
.ALMOSTEMPTY (),
.ALMOSTFULL (app_af_afull),
.DO (fifo_data_out[31:0]),
.DOP (fifo_data_out[35:32]),
.EMPTY (af_empty),
.FULL (),
.RDCOUNT (),
.RDERR (),
.WRCOUNT (),
.WRERR (),
.DI ({app_af_cmd[0],app_af_addr}),
.DIP ({2'b00,app_af_cmd[2:1]}),
.RDCLK (clk0),
.RDEN (ctrl_af_rden),
.RST (rst_r),
//.WRCLK (clk0),
.WRCLK (usr_clk),
.WREN (app_af_wren)
);
 
endmodule
/verilog/xilinx_ddr2/ddr2_phy_dm_iob.v
0,0 → 1,106
//*****************************************************************************
// DISCLAIMER OF LIABILITY
//
// This file contains proprietary and confidential information of
// Xilinx, Inc. ("Xilinx"), that is distributed under a license
// from Xilinx, and may be used, copied and/or disclosed only
// pursuant to the terms of a valid license agreement with Xilinx.
//
// XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION
// ("MATERIALS") "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
// EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING WITHOUT
// LIMITATION, ANY WARRANTY WITH RESPECT TO NONINFRINGEMENT,
// MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE. Xilinx
// does not warrant that functions included in the Materials will
// meet the requirements of Licensee, or that the operation of the
// Materials will be uninterrupted or error-free, or that defects
// in the Materials will be corrected. Furthermore, Xilinx does
// not warrant or make any representations regarding use, or the
// results of the use, of the Materials in terms of correctness,
// accuracy, reliability or otherwise.
//
// Xilinx products are not designed or intended to be fail-safe,
// or for use in any application requiring fail-safe performance,
// such as life-support or safety devices or systems, Class III
// medical devices, nuclear facilities, applications related to
// the deployment of airbags, or any other applications that could
// lead to death, personal injury or severe property or
// environmental damage (individually and collectively, "critical
// applications"). Customer assumes the sole risk and liability
// of any use of Xilinx products in critical applications,
// subject only to applicable laws and regulations governing
// limitations on product liability.
//
// Copyright 2006, 2007, 2008 Xilinx, Inc.
// All rights reserved.
//
// This disclaimer and copyright notice must be retained as part
// of this file at all times.
//*****************************************************************************
// ____ ____
// / /\/ /
// /___/ \ / Vendor: Xilinx
// \ \ \/ Version: 3.0
// \ \ Application: MIG
// / / Filename: ddr2_phy_dm_iob.v
// /___/ /\ Date Last Modified: $Date: 2008/12/23 14:26:00 $
// \ \ / \ Date Created: Wed Aug 16 2006
// \___\/\___\
//
//Device: Virtex-5
//Design Name: DDR2
//Purpose:
// This module places the data mask signals into the IOBs.
//Reference:
//Revision History:
// Rev 1.1 - To fix timing issues with Synplicity 9.6.1, syn_preserve
// attribute added for the instance u_dm_ce. PK. 11/11/08
//*****************************************************************************
 
`timescale 1ns/1ps
 
module ddr2_phy_dm_iob
(
input clk90,
input dm_ce,
input mask_data_rise,
input mask_data_fall,
output ddr_dm
);
 
wire dm_out;
wire dm_ce_r;
 
FDRSE_1 u_dm_ce
(
.Q (dm_ce_r),
.C (clk90),
.CE (1'b1),
.D (dm_ce),
.R (1'b0),
.S (1'b0)
) /* synthesis syn_preserve=1 */;
 
ODDR #
(
.SRTYPE("SYNC"),
.DDR_CLK_EDGE("SAME_EDGE")
)
u_oddr_dm
(
.Q (dm_out),
.C (clk90),
.CE (dm_ce_r),
.D1 (mask_data_rise),
.D2 (mask_data_fall),
.R (1'b0),
.S (1'b0)
);
 
OBUF u_obuf_dm
(
.I (dm_out),
.O (ddr_dm)
);
 
endmodule
/verilog/xilinx_ddr2/ddr2_phy_write.v
0,0 → 1,442
//*****************************************************************************
// DISCLAIMER OF LIABILITY
//
// This file contains proprietary and confidential information of
// Xilinx, Inc. ("Xilinx"), that is distributed under a license
// from Xilinx, and may be used, copied and/or disclosed only
// pursuant to the terms of a valid license agreement with Xilinx.
//
// XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION
// ("MATERIALS") "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
// EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING WITHOUT
// LIMITATION, ANY WARRANTY WITH RESPECT TO NONINFRINGEMENT,
// MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE. Xilinx
// does not warrant that functions included in the Materials will
// meet the requirements of Licensee, or that the operation of the
// Materials will be uninterrupted or error-free, or that defects
// in the Materials will be corrected. Furthermore, Xilinx does
// not warrant or make any representations regarding use, or the
// results of the use, of the Materials in terms of correctness,
// accuracy, reliability or otherwise.
//
// Xilinx products are not designed or intended to be fail-safe,
// or for use in any application requiring fail-safe performance,
// such as life-support or safety devices or systems, Class III
// medical devices, nuclear facilities, applications related to
// the deployment of airbags, or any other applications that could
// lead to death, personal injury or severe property or
// environmental damage (individually and collectively, "critical
// applications"). Customer assumes the sole risk and liability
// of any use of Xilinx products in critical applications,
// subject only to applicable laws and regulations governing
// limitations on product liability.
//
// Copyright 2006, 2007, 2008 Xilinx, Inc.
// All rights reserved.
//
// This disclaimer and copyright notice must be retained as part
// of this file at all times.
//*****************************************************************************
// ____ ____
// / /\/ /
// /___/ \ / Vendor: Xilinx
// \ \ \/ Version: 3.0
// \ \ Application: MIG
// / / Filename: ddr2_phy_write.v
// /___/ /\ Date Last Modified: $Date: 2008/12/23 14:26:00 $
// \ \ / \ Date Created: Thu Aug 24 2006
// \___\/\___\
//
//Device: Virtex-5
//Design Name: DDR2
//Purpose:
//Reference:
// Handles delaying various write control signals appropriately depending
// on CAS latency, additive latency, etc. Also splits the data and mask in
// rise and fall buses.
//Revision History:
// Rev 1.1 - For Dual Rank parts support ODT logic corrected. PK. 08/05/08
//*****************************************************************************
 
`timescale 1ns/1ps
 
module ddr2_phy_write #
(
// Following parameters are for 72-bit RDIMM design (for ML561 Reference
// board design). Actual values may be different. Actual parameters values
// are passed from design top module ddr2_mig module. Please refer to
// the ddr2_mig module for actual values.
parameter DQ_WIDTH = 72,
parameter CS_NUM = 1,
parameter ADDITIVE_LAT = 0,
parameter CAS_LAT = 5,
parameter ECC_ENABLE = 0,
parameter ODT_TYPE = 1,
parameter REG_ENABLE = 1,
parameter DDR_TYPE = 1
)
(
input clk0,
input clk90,
input rst90,
input [(2*DQ_WIDTH)-1:0] wdf_data,
input [(2*DQ_WIDTH/8)-1:0] wdf_mask_data,
input ctrl_wren,
input phy_init_wren,
input phy_init_data_sel,
output reg dm_ce,
output reg [1:0] dq_oe_n,
output reg dqs_oe_n ,
output reg dqs_rst_n ,
output wdf_rden,
output reg [CS_NUM-1:0] odt ,
output [DQ_WIDTH-1:0] wr_data_rise,
output [DQ_WIDTH-1:0] wr_data_fall,
output [(DQ_WIDTH/8)-1:0] mask_data_rise,
output [(DQ_WIDTH/8)-1:0] mask_data_fall
);
 
localparam MASK_WIDTH = DQ_WIDTH/8;
localparam DDR1 = 0;
localparam DDR2 = 1;
localparam DDR3 = 2;
 
// (MIN,MAX) value of WR_LATENCY for DDR1:
// REG_ENABLE = (0,1)
// ECC_ENABLE = (0,1)
// Write latency = 1
// Total: (1,3)
// (MIN,MAX) value of WR_LATENCY for DDR2:
// REG_ENABLE = (0,1)
// ECC_ENABLE = (0,1)
// Write latency = ADDITIVE_CAS + CAS_LAT - 1 = (0,4) + (3,5) - 1 = (2,8)
// ADDITIVE_LAT = (0,4) (JEDEC79-2B)
// CAS_LAT = (3,5) (JEDEC79-2B)
// Total: (2,10)
localparam WR_LATENCY = (DDR_TYPE == DDR3) ?
(ADDITIVE_LAT + (CAS_LAT) + REG_ENABLE ) :
(DDR_TYPE == DDR2) ?
(ADDITIVE_LAT + (CAS_LAT-1) + REG_ENABLE ) :
(1 + REG_ENABLE );
 
// NOTE that ODT timing does not need to be delayed for registered
// DIMM case, since like other control/address signals, it gets
// delayed by one clock cycle at the DIMM
localparam ODT_WR_LATENCY = WR_LATENCY - REG_ENABLE;
 
wire dm_ce_0;
reg dm_ce_r;
wire [1:0] dq_oe_0;
reg [1:0] dq_oe_n_90_r1;
reg [1:0] dq_oe_270;
wire dqs_oe_0;
reg dqs_oe_270;
reg dqs_oe_n_180_r1;
wire dqs_rst_0;
reg dqs_rst_n_180_r1;
reg dqs_rst_270;
reg ecc_dm_error_r;
reg ecc_dm_error_r1;
reg [(DQ_WIDTH-1):0] init_data_f;
reg [(DQ_WIDTH-1):0] init_data_r;
reg [3:0] init_wdf_cnt_r;
wire odt_0;
reg rst90_r /* synthesis syn_maxfan = 10 */;
reg [10:0] wr_stages ;
reg [(2*DQ_WIDTH)-1:0] wdf_data_r;
reg [(2*DQ_WIDTH/8)-1:0] wdf_mask_r;
wire [(2*DQ_WIDTH/8)-1:0] wdf_ecc_mask;
 
reg [(2*DQ_WIDTH/8)-1:0] wdf_mask_r1;
wire wdf_rden_0;
reg calib_rden_90_r;
reg wdf_rden_90_r;
reg wdf_rden_90_r1;
reg wdf_rden_270;
 
always @(posedge clk90)
rst90_r <= rst90;
 
//***************************************************************************
// Analysis of additional pipeline delays:
// 1. dq_oe (DQ 3-state): 1 CLK90 cyc in IOB 3-state FF
// 2. dqs_oe (DQS 3-state): 1 CLK180 cyc in IOB 3-state FF
// 3. dqs_rst (DQS output value reset): 1 CLK180 cyc in FF + 1 CLK180 cyc
// in IOB DDR
// 4. odt (ODT control): 1 CLK0 cyc in IOB FF
// 5. write data (output two cyc after wdf_rden - output of RAMB_FIFO w/
// output register enabled): 2 CLK90 cyc in OSERDES
//***************************************************************************
 
// DQS 3-state must be asserted one extra clock cycle due b/c of write
// pre- and post-amble (extra half clock cycle for each)
assign dqs_oe_0 = wr_stages[WR_LATENCY-1] | wr_stages[WR_LATENCY-2];
 
// same goes for ODT, need to handle both pre- and post-amble (generate
// ODT only for DDR2)
// ODT generation for DDR2 based on write latency. The MIN write
// latency is 2. Based on the write latency ODT is asserted.
generate
if ((DDR_TYPE != DDR1) && (ODT_TYPE > 0))begin: gen_odt_ddr2
if(ODT_WR_LATENCY > 2)
assign odt_0 =
wr_stages[ODT_WR_LATENCY-1] |
wr_stages[ODT_WR_LATENCY-2] |
wr_stages[ODT_WR_LATENCY-3] ;
else
assign odt_0 =
wr_stages[ODT_WR_LATENCY] |
wr_stages[ODT_WR_LATENCY-1] |
wr_stages[ODT_WR_LATENCY-2] ;
end else
assign odt_0 = 1'b0;
endgenerate
 
assign dq_oe_0[0] = wr_stages[WR_LATENCY-1] | wr_stages[WR_LATENCY];
assign dq_oe_0[1] = wr_stages[WR_LATENCY-1] | wr_stages[WR_LATENCY-2];
assign dqs_rst_0 = ~wr_stages[WR_LATENCY-2];
assign dm_ce_0 = wr_stages[WR_LATENCY] | wr_stages[WR_LATENCY-1]
| wr_stages[WR_LATENCY-2];
 
// write data fifo, read flag assertion
generate
if (DDR_TYPE != DDR1) begin: gen_wdf_ddr2
if (WR_LATENCY > 2)
assign wdf_rden_0 = wr_stages[WR_LATENCY-3];
else
assign wdf_rden_0 = wr_stages[WR_LATENCY-2];
end else begin: gen_wdf_ddr1
assign wdf_rden_0 = wr_stages[WR_LATENCY-2];
end
endgenerate
 
// first stage isn't registered
always @(*)
wr_stages[0] = (phy_init_data_sel) ? ctrl_wren : phy_init_wren;
 
always @(posedge clk0) begin
wr_stages[1] <= wr_stages[0];
wr_stages[2] <= wr_stages[1];
wr_stages[3] <= wr_stages[2];
wr_stages[4] <= wr_stages[3];
wr_stages[5] <= wr_stages[4];
wr_stages[6] <= wr_stages[5];
wr_stages[7] <= wr_stages[6];
wr_stages[8] <= wr_stages[7];
wr_stages[9] <= wr_stages[8];
wr_stages[10] <= wr_stages[9];
end
 
// intermediate synchronization to CLK270
always @(negedge clk90) begin
dq_oe_270 <= dq_oe_0;
dqs_oe_270 <= dqs_oe_0;
dqs_rst_270 <= dqs_rst_0;
wdf_rden_270 <= wdf_rden_0;
end
 
// synchronize DQS signals to CLK180
always @(negedge clk0) begin
dqs_oe_n_180_r1 <= ~dqs_oe_270;
dqs_rst_n_180_r1 <= ~dqs_rst_270;
end
 
// All write data-related signals synced to CLK90
always @(posedge clk90) begin
dq_oe_n_90_r1 <= ~dq_oe_270;
wdf_rden_90_r <= wdf_rden_270;
end
 
// generate for wdf_rden and calib rden. These signals
// are asserted based on write latency. For write
// latency of 2, the extra register stage is taken out.
generate
if (WR_LATENCY > 2) begin
always @(posedge clk90) begin
// assert wdf rden only for non calibration opertations
wdf_rden_90_r1 <= wdf_rden_90_r &
phy_init_data_sel;
// rden for calibration
calib_rden_90_r <= wdf_rden_90_r;
end
end else begin
always @(*) begin
wdf_rden_90_r1 = wdf_rden_90_r
& phy_init_data_sel;
calib_rden_90_r = wdf_rden_90_r;
end
end // else: !if(WR_LATENCY > 2)
endgenerate
 
// dm CE signal to stop dm oscilation
always @(negedge clk90)begin
dm_ce_r <= dm_ce_0;
dm_ce <= dm_ce_r;
end
 
// When in ECC mode the upper byte [71:64] will have the
// ECC parity. Mapping the bytes which have valid data
// to the upper byte in ecc mode. Also in ecc mode there
// is an extra register stage to account for timing.
 
genvar mask_i;
generate
if(ECC_ENABLE) begin
for (mask_i = 0; mask_i < (2*DQ_WIDTH)/72;
mask_i = mask_i+1) begin: gen_mask
assign wdf_ecc_mask[((mask_i*9)+9)-1:(mask_i*9)] =
{&wdf_mask_data[(mask_i*8)+(7+mask_i):mask_i*9],
wdf_mask_data[(mask_i*8)+(7+mask_i):mask_i*9]};
end
end
endgenerate
 
generate
if (ECC_ENABLE) begin:gen_ecc_reg
always @(posedge clk90)begin
if(phy_init_data_sel)
wdf_mask_r <= wdf_ecc_mask;
else
wdf_mask_r <= {(2*DQ_WIDTH/8){1'b0}};
end
end else begin
always@(posedge clk90) begin
if (phy_init_data_sel)
wdf_mask_r <= wdf_mask_data;
else
wdf_mask_r <= {(2*DQ_WIDTH/8){1'b0}};
end
end
endgenerate
 
always @(posedge clk90) begin
if(phy_init_data_sel)
wdf_data_r <= wdf_data;
else
wdf_data_r <={init_data_f,init_data_r};
end
 
// Error generation block during simulation.
// Error will be displayed when all the DM
// bits are not zero. The error will be
// displayed only during the start of the sequence
// for errors that are continous over many cycles.
generate
if (ECC_ENABLE) begin: gen_ecc_error
always @(posedge clk90) begin
//synthesis translate_off
wdf_mask_r1 <= wdf_mask_r;
if(DQ_WIDTH > 72)
ecc_dm_error_r
<= (
(~wdf_mask_r1[35] && (|wdf_mask_r1[34:27])) ||
(~wdf_mask_r1[26] && (|wdf_mask_r1[25:18])) ||
(~wdf_mask_r1[17] && (|wdf_mask_r1[16:9])) ||
(~wdf_mask_r1[8] && (|wdf_mask_r1[7:0]))) && phy_init_data_sel;
else
ecc_dm_error_r
<= ((~wdf_mask_r1[17] && (|wdf_mask_r1[16:9])) ||
(~wdf_mask_r1[8] && (|wdf_mask_r1[7:0]))) && phy_init_data_sel;
ecc_dm_error_r1 <= ecc_dm_error_r ;
if (ecc_dm_error_r && ~ecc_dm_error_r1) // assert the error only once.
$display ("ECC DM ERROR. ");
//synthesis translate_on
end
end
endgenerate
 
//***************************************************************************
// State logic to write calibration training patterns
//***************************************************************************
 
always @(posedge clk90) begin
if (rst90_r) begin
init_wdf_cnt_r <= 4'd0;
init_data_r <= {64{1'bx}};
init_data_f <= {64{1'bx}};
end else begin
init_wdf_cnt_r <= init_wdf_cnt_r + calib_rden_90_r;
casex (init_wdf_cnt_r)
// First stage calibration. Pattern (rise/fall) = 1(r)->0(f)
// The rise data and fall data are already interleaved in the manner
// required for data into the WDF write FIFO
4'b00xx: begin
init_data_r <= {DQ_WIDTH{1'b1}};
init_data_f <= {DQ_WIDTH{1'b0}};
end
// Second stage calibration. Pattern = 1(r)->1(f)->0(r)->0(f)
4'b01x0: begin
init_data_r <= {DQ_WIDTH{1'b1}};
init_data_f <= {DQ_WIDTH{1'b1}};
end
4'b01x1: begin
init_data_r <= {DQ_WIDTH{1'b0}};
init_data_f <= {DQ_WIDTH{1'b0}};
end
// MIG 2.1: Changed Stage 3/4 training pattern
// Third and fourth stage calibration patern =
// 11(r)->ee(f)->ee(r)->11(f)-11(r)->ee(f)->ee(r)->11(f)
4'b1000: begin
init_data_r <= {DQ_WIDTH/4{4'h1}};
init_data_f <= {DQ_WIDTH/4{4'hE}};
end
4'b1001: begin
init_data_r <= {DQ_WIDTH/4{4'hE}};
init_data_f <= {DQ_WIDTH/4{4'h1}};
end
4'b1010: begin
init_data_r <= {(DQ_WIDTH/4){4'h1}};
init_data_f <= {(DQ_WIDTH/4){4'hE}};
end
4'b1011: begin
init_data_r <= {(DQ_WIDTH/4){4'hE}};
init_data_f <= {(DQ_WIDTH/4){4'h1}};
end
default: begin
init_data_f <= {(2*DQ_WIDTH){1'bx}};
init_data_r <= {(2*DQ_WIDTH){1'bx}};
end
endcase
end
end
 
//***************************************************************************
 
always @(posedge clk90)
dq_oe_n <= dq_oe_n_90_r1;
 
always @(negedge clk0)
dqs_oe_n <= dqs_oe_n_180_r1;
 
always @(negedge clk0)
dqs_rst_n <= dqs_rst_n_180_r1;
 
// generate for odt. odt is asserted based on
// write latency. For write latency of 2
// the extra register stage is taken out.
generate
if (ODT_WR_LATENCY > 2) begin
always @(posedge clk0) begin
odt <= 'b0;
odt[0] <= odt_0;
end
end else begin
always @ (*) begin
odt = 'b0;
odt[0] = odt_0;
end
end
endgenerate
 
assign wdf_rden = wdf_rden_90_r1;
 
//***************************************************************************
// Format write data/mask: Data is in format: {fall, rise}
//***************************************************************************
 
assign wr_data_rise = wdf_data_r[DQ_WIDTH-1:0];
assign wr_data_fall = wdf_data_r[(2*DQ_WIDTH)-1:DQ_WIDTH];
assign mask_data_rise = wdf_mask_r[MASK_WIDTH-1:0];
assign mask_data_fall = wdf_mask_r[(2*MASK_WIDTH)-1:MASK_WIDTH];
 
endmodule
/verilog/xilinx_ddr2/xilinx_ddr2.v
0,0 → 1,214
/*
* Wrapper for Xilinx MIG'd DDR2 controller, allowing 3 masters
* to contol the single interface.
*/
 
module xilinx_ddr2
(
// Inputs
input [31:0] wbm0_adr_i,
input [1:0] wbm0_bte_i,
input [2:0] wbm0_cti_i,
input wbm0_cyc_i,
input [31:0] wbm0_dat_i,
input [3:0] wbm0_sel_i,
input wbm0_stb_i,
input wbm0_we_i,
// Outputs
output wbm0_ack_o,
output wbm0_err_o,
output wbm0_rty_o,
output [31:0] wbm0_dat_o,
// Inputs
input [31:0] wbm1_adr_i,
input [1:0] wbm1_bte_i,
input [2:0] wbm1_cti_i,
input wbm1_cyc_i,
input [31:0] wbm1_dat_i,
input [3:0] wbm1_sel_i,
input wbm1_stb_i,
input wbm1_we_i,
// Outputs
output wbm1_ack_o,
output wbm1_err_o,
output wbm1_rty_o,
output [31:0] wbm1_dat_o,
 
 
// Inputs
input [31:0] wbm2_adr_i,
input [1:0] wbm2_bte_i,
input [2:0] wbm2_cti_i,
input wbm2_cyc_i,
input [31:0] wbm2_dat_i,
input [3:0] wbm2_sel_i,
input wbm2_stb_i,
input wbm2_we_i,
// Outputs
output wbm2_ack_o,
output wbm2_err_o,
output wbm2_rty_o,
output [31:0] wbm2_dat_o,
 
input wb_clk,
input wb_rst,
 
output [12:0] ddr2_a,
output [1:0] ddr2_ba,
output ddr2_ras_n,
output ddr2_cas_n,
output ddr2_we_n,
output [1:0] ddr2_cs_n,
output [1:0] ddr2_odt,
output [1:0] ddr2_cke,
output [7:0] ddr2_dm,
inout [63:0] ddr2_dq,
inout [7:0] ddr2_dqs,
inout [7:0] ddr2_dqs_n,
output [1:0] ddr2_ck,
output [1:0] ddr2_ck_n,
 
input ddr2_if_clk,
input clk200,
input ddr2_if_rst
);
 
// Internal wires to actual RAM
wire [31:0] wbs_ram_adr_i;
wire [1:0] wbs_ram_bte_i;
wire [2:0] wbs_ram_cti_i;
wire wbs_ram_cyc_i;
wire [31:0] wbs_ram_dat_i;
wire [3:0] wbs_ram_sel_i;
wire wbs_ram_stb_i;
wire wbs_ram_we_i;
wire wbs_ram_ack_o;
wire [31:0] wbs_ram_dat_o;
 
reg [2:0] input_select, last_selected;
wire arb_for_wbm0, arb_for_wbm1, arb_for_wbm2;
// Wires allowing selection of new input
assign arb_for_wbm0 = (last_selected[1] | last_selected[2] |
!wbm1_cyc_i | !wbm2_cyc_i) & !(|input_select);
assign arb_for_wbm1 = (last_selected[0] | last_selected[2] |
!wbm0_cyc_i | !wbm2_cyc_i) & !(|input_select);
assign arb_for_wbm2 = (last_selected[0] | last_selected[1] |
!wbm0_cyc_i | !wbm1_cyc_i) & !(|input_select);
// Master select logic
always @(posedge wb_clk)
if (wb_rst)
input_select <= 0;
else if ((input_select[0] & !wbm0_cyc_i) | (input_select[1] & !wbm1_cyc_i)
| (input_select[2] & !wbm2_cyc_i))
input_select <= 0;
else if (!(&input_select) & wbm0_cyc_i & arb_for_wbm0)
input_select <= 3'b001;
else if (!(&input_select) & wbm1_cyc_i & arb_for_wbm1)
input_select <= 3'b010;
else if (!(&input_select) & wbm2_cyc_i & arb_for_wbm2)
input_select <= 3'b100;
always @(posedge wb_clk)
if (wb_rst)
last_selected <= 0;
else if (!(&input_select) & wbm0_cyc_i & arb_for_wbm0)
last_selected <= 3'b001;
else if (!(&input_select) & wbm1_cyc_i & arb_for_wbm1)
last_selected <= 3'b010;
else if (!(&input_select) & wbm2_cyc_i & arb_for_wbm2)
last_selected <= 3'b100;
 
// Mux input signals to RAM (default to wbm0)
assign wbs_ram_adr_i = (input_select[2]) ? wbm2_adr_i :
(input_select[1]) ? wbm1_adr_i :
(input_select[0]) ? wbm0_adr_i : 0;
assign wbs_ram_bte_i = (input_select[2]) ? wbm2_bte_i :
(input_select[1]) ? wbm1_bte_i :
(input_select[0]) ? wbm0_bte_i : 0;
assign wbs_ram_cti_i = (input_select[2]) ? wbm2_cti_i :
(input_select[1]) ? wbm1_cti_i :
(input_select[0]) ? wbm0_cti_i : 0;
assign wbs_ram_cyc_i = (input_select[2]) ? wbm2_cyc_i :
(input_select[1]) ? wbm1_cyc_i :
(input_select[0]) ? wbm0_cyc_i : 0;
assign wbs_ram_dat_i = (input_select[2]) ? wbm2_dat_i :
(input_select[1]) ? wbm1_dat_i :
(input_select[0]) ? wbm0_dat_i : 0;
assign wbs_ram_sel_i = (input_select[2]) ? wbm2_sel_i :
(input_select[1]) ? wbm1_sel_i :
(input_select[0]) ? wbm0_sel_i : 0;
assign wbs_ram_stb_i = (input_select[2]) ? wbm2_stb_i :
(input_select[1]) ? wbm1_stb_i :
(input_select[0]) ? wbm0_stb_i : 0;
assign wbs_ram_we_i = (input_select[2]) ? wbm2_we_i :
(input_select[1]) ? wbm1_we_i :
(input_select[0]) ? wbm0_we_i : 0;
 
// Output from RAM, gate the ACK, ERR, RTY signals appropriately
assign wbm0_dat_o = wbs_ram_dat_o;
assign wbm0_ack_o = wbs_ram_ack_o & input_select[0];
assign wbm0_err_o = 0;
assign wbm0_rty_o = 0;
 
assign wbm1_dat_o = wbs_ram_dat_o;
assign wbm1_ack_o = wbs_ram_ack_o & input_select[1];
assign wbm1_err_o = 0;
assign wbm1_rty_o = 0;
 
assign wbm2_dat_o = wbs_ram_dat_o;
assign wbm2_ack_o = wbs_ram_ack_o & input_select[2];
assign wbm2_err_o = 0;
assign wbm2_rty_o = 0;
 
 
xilinx_ddr2_if xilinx_ddr2_if0
(
 
.wb_dat_o (wbs_ram_dat_o),
.wb_ack_o (wbs_ram_ack_o),
.wb_adr_i (wbs_ram_adr_i[31:0]),
.wb_stb_i (wbs_ram_stb_i),
.wb_cyc_i (wbs_ram_cyc_i),
.wb_we_i (wbs_ram_we_i),
.wb_sel_i (wbs_ram_sel_i[3:0]),
.wb_dat_i (wbs_ram_dat_i[31:0]),
 
.ddr2_a (ddr2_a[12:0]),
.ddr2_ba (ddr2_ba[1:0]),
.ddr2_ras_n (ddr2_ras_n),
.ddr2_cas_n (ddr2_cas_n),
.ddr2_we_n (ddr2_we_n),
.ddr2_cs_n (ddr2_cs_n),
.ddr2_odt (ddr2_odt),
.ddr2_cke (ddr2_cke),
.ddr2_dm (ddr2_dm[7:0]),
.ddr2_ck (ddr2_ck[1:0]),
.ddr2_ck_n (ddr2_ck_n[1:0]),
.ddr2_dq (ddr2_dq[63:0]),
.ddr2_dqs (ddr2_dqs[7:0]),
.ddr2_dqs_n (ddr2_dqs_n[7:0]),
 
.ddr2_if_clk (ddr2_if_clk),
.idly_clk_200 (clk200),
.ddr2_if_rst (ddr2_if_rst),
.wb_clk (wb_clk),
.wb_rst (wb_rst));
 
 
endmodule
 
/verilog/xilinx_ddr2/xilinx_ddr2_if_cache.v
0,0 → 1,152
/*******************************************************************************
* This file is owned and controlled by Xilinx and must be used *
* solely for design, simulation, implementation and creation of *
* design files limited to Xilinx devices or technologies. Use *
* with non-Xilinx devices or technologies is expressly prohibited *
* and immediately terminates your license. *
* *
* XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" *
* SOLELY FOR USE IN DEVELOPING PROGRAMS AND SOLUTIONS FOR *
* XILINX DEVICES. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION *
* AS ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION *
* OR STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS *
* IMPLEMENTATION IS FREE FROM ANY CLAIMS OF INFRINGEMENT, *
* AND YOU ARE RESPONSIBLE FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE *
* FOR YOUR IMPLEMENTATION. XILINX EXPRESSLY DISCLAIMS ANY *
* WARRANTY WHATSOEVER WITH RESPECT TO THE ADEQUACY OF THE *
* IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OR *
* REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM CLAIMS OF *
* INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS *
* FOR A PARTICULAR PURPOSE. *
* *
* Xilinx products are not intended for use in life support *
* appliances, devices, or systems. Use in such applications are *
* expressly prohibited. *
* *
* (c) Copyright 1995-2009 Xilinx, Inc. *
* All rights reserved. *
*******************************************************************************/
// The synthesis directives "translate_off/translate_on" specified below are
// supported by Xilinx, Mentor Graphics and Synplicity synthesis
// tools. Ensure they are correct for your synthesis tool(s).
 
// You must compile the wrapper file xilinx_ddr2_if_cache.v when simulating
// the core, xilinx_ddr2_if_cache. When compiling the wrapper file, be sure to
// reference the XilinxCoreLib Verilog simulation library. For detailed
// instructions, please refer to the "CORE Generator Help".
 
`timescale 1ns/1ps
 
module xilinx_ddr2_if_cache(
clka,
ena,
wea,
addra,
dina,
douta,
clkb,
enb,
web,
addrb,
dinb,
doutb);
 
 
input clka;
input ena;
input [3 : 0] wea;
input [11 : 0] addra;
input [31 : 0] dina;
output [31 : 0] douta;
input clkb;
input enb;
input [15 : 0] web;
input [9 : 0] addrb;
input [127 : 0] dinb;
output [127 : 0] doutb;
 
// synthesis translate_off
 
BLK_MEM_GEN_V3_1 #(
.C_ADDRA_WIDTH(12),
.C_ADDRB_WIDTH(10),
.C_ALGORITHM(1),
.C_BYTE_SIZE(8),
.C_COMMON_CLK(0),
.C_DEFAULT_DATA("0"),
.C_DISABLE_WARN_BHV_COLL(0),
.C_DISABLE_WARN_BHV_RANGE(0),
.C_FAMILY("virtex5"),
.C_HAS_ENA(1),
.C_HAS_ENB(1),
.C_HAS_INJECTERR(0),
.C_HAS_MEM_OUTPUT_REGS_A(0),
.C_HAS_MEM_OUTPUT_REGS_B(0),
.C_HAS_MUX_OUTPUT_REGS_A(0),
.C_HAS_MUX_OUTPUT_REGS_B(0),
.C_HAS_REGCEA(0),
.C_HAS_REGCEB(0),
.C_HAS_RSTA(0),
.C_HAS_RSTB(0),
.C_INITA_VAL("0"),
.C_INITB_VAL("0"),
.C_INIT_FILE_NAME("no_coe_file_loaded"),
.C_LOAD_INIT_FILE(0),
.C_MEM_TYPE(2),
.C_MUX_PIPELINE_STAGES(0),
.C_PRIM_TYPE(1),
.C_READ_DEPTH_A(4096),
.C_READ_DEPTH_B(1024),
.C_READ_WIDTH_A(32),
.C_READ_WIDTH_B(128),
.C_RSTRAM_A(0),
.C_RSTRAM_B(0),
.C_RST_PRIORITY_A("CE"),
.C_RST_PRIORITY_B("CE"),
.C_RST_TYPE("SYNC"),
.C_SIM_COLLISION_CHECK("ALL"),
.C_USE_BYTE_WEA(1),
.C_USE_BYTE_WEB(1),
.C_USE_DEFAULT_DATA(0),
.C_USE_ECC(0),
.C_WEA_WIDTH(4),
.C_WEB_WIDTH(16),
.C_WRITE_DEPTH_A(4096),
.C_WRITE_DEPTH_B(1024),
.C_WRITE_MODE_A("WRITE_FIRST"),
.C_WRITE_MODE_B("WRITE_FIRST"),
.C_WRITE_WIDTH_A(32),
.C_WRITE_WIDTH_B(128),
.C_XDEVICEFAMILY("virtex5"))
inst (
.CLKA(clka),
.ENA(ena),
.WEA(wea),
.ADDRA(addra),
.DINA(dina),
.DOUTA(douta),
.CLKB(clkb),
.ENB(enb),
.WEB(web),
.ADDRB(addrb),
.DINB(dinb),
.DOUTB(doutb),
.RSTA(),
.REGCEA(),
.RSTB(),
.REGCEB(),
.INJECTSBITERR(),
.INJECTDBITERR(),
.SBITERR(),
.DBITERR(),
.RDADDRECC());
 
 
// synthesis translate_on
 
// XST black box declaration
// box_type "black_box"
// synthesis attribute box_type of ml501_ddr2_if_cache is "black_box"
 
endmodule
 
/verilog/xilinx_ddr2/ddr2_mig.v
0,0 → 1,618
//*****************************************************************************
// DISCLAIMER OF LIABILITY
//
// This file contains proprietary and confidential information of
// Xilinx, Inc. ("Xilinx"), that is distributed under a license
// from Xilinx, and may be used, copied and/or disclosed only
// pursuant to the terms of a valid license agreement with Xilinx.
//
// XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION
// ("MATERIALS") "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
// EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING WITHOUT
// LIMITATION, ANY WARRANTY WITH RESPECT TO NONINFRINGEMENT,
// MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE. Xilinx
// does not warrant that functions included in the Materials will
// meet the requirements of Licensee, or that the operation of the
// Materials will be uninterrupted or error-free, or that defects
// in the Materials will be corrected. Furthermore, Xilinx does
// not warrant or make any representations regarding use, or the
// results of the use, of the Materials in terms of correctness,
// accuracy, reliability or otherwise.
//
// Xilinx products are not designed or intended to be fail-safe,
// or for use in any application requiring fail-safe performance,
// such as life-support or safety devices or systems, Class III
// medical devices, nuclear facilities, applications related to
// the deployment of airbags, or any other applications that could
// lead to death, personal injury or severe property or
// environmental damage (individually and collectively, "critical
// applications"). Customer assumes the sole risk and liability
// of any use of Xilinx products in critical applications,
// subject only to applicable laws and regulations governing
// limitations on product liability.
//
// Copyright 2006, 2007, 2008 Xilinx, Inc.
// All rights reserved.
//
// This disclaimer and copyright notice must be retained as part
// of this file at all times.
//*****************************************************************************
// ____ ____
// / /\/ /
// /___/ \ / Vendor: Xilinx
// \ \ \/ Version: 3.0
// \ \ Application: MIG
// / / Filename: ddr2_mig.v
// /___/ /\ Date Last Modified: $Date: 2009/02/03 18:46:29 $
// \ \ / \ Date Created: Wed Aug 16 2006
// \___\/\___\
//
//Device: Virtex-5
//Design Name: DDR2
//Purpose:
// Top-level module. Simple model for what the user might use
// Typically, the user will only instantiate MEM_INTERFACE_TOP in their
// code, and generate all backend logic (test bench) separately.
// In addition to the memory controller, the module instantiates:
// 1. Clock generation/distribution, reset logic
// 2. IDELAY control block
//Reference:
//Revision History:
// Rev 1.1 - Parameter USE_DM_PORT added. PK. 6/25/08
// Rev 1.2 - Parameter HIGH_PERFORMANCE_MODE added. PK. 7/10/08
// Rev 1.3 - Parameter IODELAY_GRP added. PK. 11/27/08
//*****************************************************************************
 
`timescale 1ns/1ps
 
(* X_CORE_INFO = "mig_v3_0_ddr2_v5, Coregen 11.1" , CORE_GENERATION_INFO = "ddr2_v5,mig_v3_0,{component_name=ddr2_mig, BANK_WIDTH=2, CKE_WIDTH=1, CLK_WIDTH=2, COL_WIDTH=10, CS_NUM=1, CS_WIDTH=1, DM_WIDTH=8, DQ_WIDTH=64, DQ_PER_DQS=8, DQS_WIDTH=8, ODT_WIDTH=1, ROW_WIDTH=13, ADDITIVE_LAT=0, BURST_LEN=4, BURST_TYPE=0, CAS_LAT=4, ECC_ENABLE=0, MULTI_BANK_EN=1, TWO_T_TIME_EN=1, ODT_TYPE=1, REDUCE_DRV=0, REG_ENABLE=0, TREFI_NS=7800, TRAS=40000, TRCD=15000, TRFC=105000, TRP=15000, TRTP=7500, TWR=15000, TWTR=7500, DDR2_CLK_PERIOD=3750, RST_ACT_LOW=1}" *)
module ddr2_mig #
(
parameter BANK_WIDTH = 2,
// # of memory bank addr bits.
parameter CKE_WIDTH = 1,
// # of memory clock enable outputs.
parameter CLK_WIDTH = 2,
// # of clock outputs.
parameter COL_WIDTH = 10,
// # of memory column bits.
parameter CS_NUM = 1,
// # of separate memory chip selects.
parameter CS_WIDTH = 1,
// # of total memory chip selects.
parameter CS_BITS = 0,
// set to log2(CS_NUM) (rounded up).
parameter DM_WIDTH = 8,
// # of data mask bits.
parameter DQ_WIDTH = 64,
// # of data width.
parameter DQ_PER_DQS = 8,
// # of DQ data bits per strobe.
parameter DQS_WIDTH = 8,
// # of DQS strobes.
parameter DQ_BITS = 6,
// set to log2(DQS_WIDTH*DQ_PER_DQS).
parameter DQS_BITS = 3,
// set to log2(DQS_WIDTH).
parameter ODT_WIDTH = 1,
// # of memory on-die term enables.
parameter ROW_WIDTH = 13,
// # of memory row and # of addr bits.
parameter ADDITIVE_LAT = 0,
// additive write latency.
parameter BURST_LEN = 4,
// burst length (in double words).
parameter BURST_TYPE = 0,
// burst type (=0 seq; =1 interleaved).
parameter CAS_LAT = 4,
// CAS latency.
parameter ECC_ENABLE = 0,
// enable ECC (=1 enable).
parameter APPDATA_WIDTH = 128,
// # of usr read/write data bus bits.
parameter MULTI_BANK_EN = 1,
// Keeps multiple banks open. (= 1 enable).
parameter TWO_T_TIME_EN = 1,
// 2t timing for unbuffered dimms.
parameter ODT_TYPE = 1,
// ODT (=0(none),=1(75),=2(150),=3(50)).
parameter REDUCE_DRV = 0,
// reduced strength mem I/O (=1 yes).
parameter REG_ENABLE = 0,
// registered addr/ctrl (=1 yes).
parameter TREFI_NS = 7800,
// auto refresh interval (ns).
parameter TRAS = 40000,
// active->precharge delay.
parameter TRCD = 15000,
// active->read/write delay.
parameter TRFC = 105000,
// refresh->refresh, refresh->active delay.
parameter TRP = 15000,
// precharge->command delay.
parameter TRTP = 7500,
// read->precharge delay.
parameter TWR = 15000,
// used to determine write->precharge.
parameter TWTR = 7500,
// write->read delay.
parameter HIGH_PERFORMANCE_MODE = "TRUE",
// # = TRUE, the IODELAY performance mode is set
// to high.
// # = FALSE, the IODELAY performance mode is set
// to low.
parameter SIM_ONLY = 0,
// = 1 to skip SDRAM power up delay.
parameter DEBUG_EN = 0,
// Enable debug signals/controls.
// When this parameter is changed from 0 to 1,
// make sure to uncomment the coregen commands
// in ise_flow.bat or create_ise.bat files in
// par folder.
parameter CLK_PERIOD = 3750,
// Core/Memory clock period (in ps).
parameter CLK_TYPE = "SINGLE_ENDED",
// # = "DIFFERENTIAL " ->; Differential input clocks ,
// # = "SINGLE_ENDED" -> Single ended input clocks.
parameter DLL_FREQ_MODE = "HIGH",
// DCM Frequency range.
parameter RST_ACT_LOW = 1
// =1 for active low reset, =0 for active high.
)
(
inout [DQ_WIDTH-1:0] ddr2_dq,
output [ROW_WIDTH-1:0] ddr2_a,
output [BANK_WIDTH-1:0] ddr2_ba,
output ddr2_ras_n,
output ddr2_cas_n,
output ddr2_we_n,
output [CS_WIDTH-1:0] ddr2_cs_n,
output [ODT_WIDTH-1:0] ddr2_odt,
output [CKE_WIDTH-1:0] ddr2_cke,
output [DM_WIDTH-1:0] ddr2_dm,
input sys_clk,
input idly_clk_200,
input sys_rst_n,
output phy_init_done,
output rst0_tb,
output clk0_tb,
input usr_clk, // jb
output app_wdf_afull,
output app_af_afull,
output rd_data_valid,
input app_wdf_wren,
input app_af_wren,
input [30:0] app_af_addr,
input [2:0] app_af_cmd,
output [(APPDATA_WIDTH)-1:0] rd_data_fifo_out,
input [(APPDATA_WIDTH)-1:0] app_wdf_data,
input [(APPDATA_WIDTH/8)-1:0] app_wdf_mask_data,
inout [DQS_WIDTH-1:0] ddr2_dqs,
inout [DQS_WIDTH-1:0] ddr2_dqs_n,
output [CLK_WIDTH-1:0] ddr2_ck,
output [CLK_WIDTH-1:0] ddr2_ck_n
);
 
//***************************************************************************
// IODELAY Group Name: Replication and placement of IDELAYCTRLs will be
// handled automatically by software tools if IDELAYCTRLs have same refclk,
// reset and rdy nets. Designs with a unique RESET will commonly create a
// unique RDY. Constraint IODELAY_GROUP is associated to a set of IODELAYs
// with an IDELAYCTRL. The parameter IODELAY_GRP value can be any string.
//***************************************************************************
 
localparam IODELAY_GRP = "IODELAY_MIG";
initial
$display("Xilinx DDR2 MIGed controller at %m\n");
 
 
 
wire sys_clk_p;
wire sys_clk_n;
wire clk200_p;
wire clk200_n;
wire rst0;
wire rst90;
wire rstdiv0;
wire rst200;
wire clk0;
wire clk90;
wire clkdiv0;
wire clk200;
wire idelay_ctrl_rdy;
 
 
//Debug signals
 
 
wire [3:0] dbg_calib_done;
wire [3:0] dbg_calib_err;
wire [(6*DQ_WIDTH)-1:0] dbg_calib_dq_tap_cnt;
wire [(6*DQS_WIDTH)-1:0] dbg_calib_dqs_tap_cnt;
wire [(6*DQS_WIDTH)-1:0] dbg_calib_gate_tap_cnt;
wire [DQS_WIDTH-1:0] dbg_calib_rd_data_sel;
wire [(5*DQS_WIDTH)-1:0] dbg_calib_rden_dly;
wire [(5*DQS_WIDTH)-1:0] dbg_calib_gate_dly;
wire dbg_idel_up_all;
wire dbg_idel_down_all;
wire dbg_idel_up_dq;
wire dbg_idel_down_dq;
wire dbg_idel_up_dqs;
wire dbg_idel_down_dqs;
wire dbg_idel_up_gate;
wire dbg_idel_down_gate;
wire [DQ_BITS-1:0] dbg_sel_idel_dq;
wire dbg_sel_all_idel_dq;
wire [DQS_BITS:0] dbg_sel_idel_dqs;
wire dbg_sel_all_idel_dqs;
wire [DQS_BITS:0] dbg_sel_idel_gate;
wire dbg_sel_all_idel_gate;
 
 
// Debug signals (optional use)
 
//***********************************
// PHY Debug Port demo
//***********************************
wire [35:0] cs_control0;
wire [35:0] cs_control1;
wire [35:0] cs_control2;
wire [35:0] cs_control3;
wire [191:0] vio0_in;
wire [95:0] vio1_in;
wire [99:0] vio2_in;
wire [31:0] vio3_out;
 
 
 
 
//***************************************************************************
 
assign rst0_tb = rst0;
assign clk0_tb = clk0;
assign sys_clk_p = 1'b1;
assign sys_clk_n = 1'b0;
assign clk200_p = 1'b1;
assign clk200_n = 1'b0;
 
ddr2_idelay_ctrl #
(
.IODELAY_GRP (IODELAY_GRP)
)
u_ddr2_idelay_ctrl
(
.rst200 (rst200),
.clk200 (clk200),
.idelay_ctrl_rdy (idelay_ctrl_rdy)
);
 
ddr2_infrastructure #
(
.CLK_PERIOD (CLK_PERIOD),
.CLK_TYPE (CLK_TYPE),
.DLL_FREQ_MODE (DLL_FREQ_MODE),
.RST_ACT_LOW (RST_ACT_LOW)
)
u_ddr2_infrastructure
(
.sys_clk_p (sys_clk_p),
.sys_clk_n (sys_clk_n),
.sys_clk (sys_clk),
.clk200_p (clk200_p),
.clk200_n (clk200_n),
.idly_clk_200 (idly_clk_200),
.sys_rst_n (sys_rst_n),
.rst0 (rst0),
.rst90 (rst90),
.rstdiv0 (rstdiv0),
.rst200 (rst200),
.clk0 (clk0),
.clk90 (clk90),
.clkdiv0 (clkdiv0),
.clk200 (clk200),
.idelay_ctrl_rdy (idelay_ctrl_rdy)
);
 
ddr2_top #
(
.BANK_WIDTH (BANK_WIDTH),
.CKE_WIDTH (CKE_WIDTH),
.CLK_WIDTH (CLK_WIDTH),
.COL_WIDTH (COL_WIDTH),
.CS_NUM (CS_NUM),
.CS_WIDTH (CS_WIDTH),
.CS_BITS (CS_BITS),
.DM_WIDTH (DM_WIDTH),
.DQ_WIDTH (DQ_WIDTH),
.DQ_PER_DQS (DQ_PER_DQS),
.DQS_WIDTH (DQS_WIDTH),
.DQ_BITS (DQ_BITS),
.DQS_BITS (DQS_BITS),
.ODT_WIDTH (ODT_WIDTH),
.ROW_WIDTH (ROW_WIDTH),
.ADDITIVE_LAT (ADDITIVE_LAT),
.BURST_LEN (BURST_LEN),
.BURST_TYPE (BURST_TYPE),
.CAS_LAT (CAS_LAT),
.ECC_ENABLE (ECC_ENABLE),
.APPDATA_WIDTH (APPDATA_WIDTH),
.MULTI_BANK_EN (MULTI_BANK_EN),
.TWO_T_TIME_EN (TWO_T_TIME_EN),
.ODT_TYPE (ODT_TYPE),
.REDUCE_DRV (REDUCE_DRV),
.REG_ENABLE (REG_ENABLE),
.TREFI_NS (TREFI_NS),
.TRAS (TRAS),
.TRCD (TRCD),
.TRFC (TRFC),
.TRP (TRP),
.TRTP (TRTP),
.TWR (TWR),
.TWTR (TWTR),
.HIGH_PERFORMANCE_MODE (HIGH_PERFORMANCE_MODE),
.IODELAY_GRP (IODELAY_GRP),
.SIM_ONLY (SIM_ONLY),
.DEBUG_EN (DEBUG_EN),
.CLK_PERIOD (CLK_PERIOD),
.FPGA_SPEED_GRADE (1),
.USE_DM_PORT (1)
)
u_ddr2_top_0
(
.ddr2_dq (ddr2_dq),
.ddr2_a (ddr2_a),
.ddr2_ba (ddr2_ba),
.ddr2_ras_n (ddr2_ras_n),
.ddr2_cas_n (ddr2_cas_n),
.ddr2_we_n (ddr2_we_n),
.ddr2_cs_n (ddr2_cs_n),
.ddr2_odt (ddr2_odt),
.ddr2_cke (ddr2_cke),
.ddr2_dm (ddr2_dm),
.phy_init_done (phy_init_done),
.rst0 (rst0),
.rst90 (rst90),
.rstdiv0 (rstdiv0),
.clk0 (clk0),
.usr_clk (usr_clk), // jb
.clk90 (clk90),
.clkdiv0 (clkdiv0),
.app_wdf_afull (app_wdf_afull),
.app_af_afull (app_af_afull),
.rd_data_valid (rd_data_valid),
.app_wdf_wren (app_wdf_wren),
.app_af_wren (app_af_wren),
.app_af_addr (app_af_addr),
.app_af_cmd (app_af_cmd),
.rd_data_fifo_out (rd_data_fifo_out),
.app_wdf_data (app_wdf_data),
.app_wdf_mask_data (app_wdf_mask_data),
.ddr2_dqs (ddr2_dqs),
.ddr2_dqs_n (ddr2_dqs_n),
.ddr2_ck (ddr2_ck),
.rd_ecc_error (),
.ddr2_ck_n (ddr2_ck_n),
 
.dbg_calib_done (dbg_calib_done),
.dbg_calib_err (dbg_calib_err),
.dbg_calib_dq_tap_cnt (dbg_calib_dq_tap_cnt),
.dbg_calib_dqs_tap_cnt (dbg_calib_dqs_tap_cnt),
.dbg_calib_gate_tap_cnt (dbg_calib_gate_tap_cnt),
.dbg_calib_rd_data_sel (dbg_calib_rd_data_sel),
.dbg_calib_rden_dly (dbg_calib_rden_dly),
.dbg_calib_gate_dly (dbg_calib_gate_dly),
.dbg_idel_up_all (dbg_idel_up_all),
.dbg_idel_down_all (dbg_idel_down_all),
.dbg_idel_up_dq (dbg_idel_up_dq),
.dbg_idel_down_dq (dbg_idel_down_dq),
.dbg_idel_up_dqs (dbg_idel_up_dqs),
.dbg_idel_down_dqs (dbg_idel_down_dqs),
.dbg_idel_up_gate (dbg_idel_up_gate),
.dbg_idel_down_gate (dbg_idel_down_gate),
.dbg_sel_idel_dq (dbg_sel_idel_dq),
.dbg_sel_all_idel_dq (dbg_sel_all_idel_dq),
.dbg_sel_idel_dqs (dbg_sel_idel_dqs),
.dbg_sel_all_idel_dqs (dbg_sel_all_idel_dqs),
.dbg_sel_idel_gate (dbg_sel_idel_gate),
.dbg_sel_all_idel_gate (dbg_sel_all_idel_gate)
);
 
//*****************************************************************
// Hooks to prevent sim/syn compilation errors (mainly for VHDL - but
// keep it also in Verilog version of code) w/ floating inputs if
// DEBUG_EN = 0.
//*****************************************************************
 
generate
if (DEBUG_EN == 0) begin: gen_dbg_tie_off
assign dbg_idel_up_all = 'b0;
assign dbg_idel_down_all = 'b0;
assign dbg_idel_up_dq = 'b0;
assign dbg_idel_down_dq = 'b0;
assign dbg_idel_up_dqs = 'b0;
assign dbg_idel_down_dqs = 'b0;
assign dbg_idel_up_gate = 'b0;
assign dbg_idel_down_gate = 'b0;
assign dbg_sel_idel_dq = 'b0;
assign dbg_sel_all_idel_dq = 'b0;
assign dbg_sel_idel_dqs = 'b0;
assign dbg_sel_all_idel_dqs = 'b0;
assign dbg_sel_idel_gate = 'b0;
assign dbg_sel_all_idel_gate = 'b0;
end else begin: gen_dbg_enable
`ifdef XILINX_DDR2_CHIPSCOPE
//*****************************************************************
// PHY Debug Port example - see MIG User's Guide, XAPP858 or
// Answer Record 29443
// This logic supports up to 32 DQ and 8 DQS I/O
// NOTES:
// 1. PHY Debug Port demo connects to 4 VIO modules:
// - 3 VIO modules with only asynchronous inputs
// * Monitor IDELAY taps for DQ, DQS, DQS Gate
// * Calibration status
// - 1 VIO module with synchronous outputs
// * Allow dynamic adjustment o f IDELAY taps
// 2. User may need to modify this code to incorporate other
// chipscope-related modules in their larger design (e.g.
// if they have other ILA/VIO modules, they will need to
// for example instantiate a larger ICON module). In addition
// user may want to instantiate more VIO modules to control
// IDELAY for more DQ, DQS than is shown here
//*****************************************************************
 
icon4 u_icon
(
.control0 (cs_control0),
.control1 (cs_control1),
.control2 (cs_control2),
.control3 (cs_control3)
);
 
//*****************************************************************
// VIO ASYNC input: Display current IDELAY setting for up to 32
// DQ taps (32x6) = 192
//*****************************************************************
 
vio_async_in192 u_vio0
(
.control (cs_control0),
.async_in (vio0_in)
);
 
//*****************************************************************
// VIO ASYNC input: Display current IDELAY setting for up to 8 DQS
// and DQS Gate taps (8x6x2) = 96
//*****************************************************************
 
vio_async_in96 u_vio1
(
.control (cs_control1),
.async_in (vio1_in)
);
 
//*****************************************************************
// VIO ASYNC input: Display other calibration results
//*****************************************************************
 
vio_async_in100 u_vio2
(
.control (cs_control2),
.async_in (vio2_in)
);
//*****************************************************************
// VIO SYNC output: Dynamically change IDELAY taps
//*****************************************************************
vio_sync_out32 u_vio3
(
.control (cs_control3),
.clk (clkdiv0),
.sync_out (vio3_out)
);
 
//*****************************************************************
// Bit assignments:
// NOTE: Not all VIO, ILA inputs/outputs may be used - these will
// be dependent on the user's particular bit width
//*****************************************************************
 
if (DQ_WIDTH <= 32) begin: gen_dq_le_32
assign vio0_in[(6*DQ_WIDTH)-1:0]
= dbg_calib_dq_tap_cnt[(6*DQ_WIDTH)-1:0];
end else begin: gen_dq_gt_32
assign vio0_in = dbg_calib_dq_tap_cnt[191:0];
end
 
if (DQS_WIDTH <= 8) begin: gen_dqs_le_8
assign vio1_in[(6*DQS_WIDTH)-1:0]
= dbg_calib_dqs_tap_cnt[(6*DQS_WIDTH)-1:0];
assign vio1_in[(12*DQS_WIDTH)-1:(6*DQS_WIDTH)]
= dbg_calib_gate_tap_cnt[(6*DQS_WIDTH)-1:0];
end else begin: gen_dqs_gt_32
assign vio1_in[47:0] = dbg_calib_dqs_tap_cnt[47:0];
assign vio1_in[95:48] = dbg_calib_gate_tap_cnt[47:0];
end
//dbg_calib_rd_data_sel
 
if (DQS_WIDTH <= 8) begin: gen_rdsel_le_8
assign vio2_in[(DQS_WIDTH)+7:8]
= dbg_calib_rd_data_sel[(DQS_WIDTH)-1:0];
end else begin: gen_rdsel_gt_32
assign vio2_in[15:8]
= dbg_calib_rd_data_sel[7:0];
end
//dbg_calib_rden_dly
 
if (DQS_WIDTH <= 8) begin: gen_calrd_le_8
assign vio2_in[(5*DQS_WIDTH)+19:20]
= dbg_calib_rden_dly[(5*DQS_WIDTH)-1:0];
end else begin: gen_calrd_gt_32
assign vio2_in[59:20]
= dbg_calib_rden_dly[39:0];
end
 
//dbg_calib_gate_dly
 
if (DQS_WIDTH <= 8) begin: gen_calgt_le_8
assign vio2_in[(5*DQS_WIDTH)+59:60]
= dbg_calib_gate_dly[(5*DQS_WIDTH)-1:0];
end else begin: gen_calgt_gt_32
assign vio2_in[99:60]
= dbg_calib_gate_dly[39:0];
end
 
//dbg_sel_idel_dq
 
if (DQ_BITS <= 5) begin: gen_selid_le_5
assign dbg_sel_idel_dq[DQ_BITS-1:0]
= vio3_out[DQ_BITS+7:8];
end else begin: gen_selid_gt_32
assign dbg_sel_idel_dq[4:0]
= vio3_out[12:8];
end
 
//dbg_sel_idel_dqs
 
if (DQS_BITS <= 3) begin: gen_seldqs_le_3
assign dbg_sel_idel_dqs[DQS_BITS:0]
= vio3_out[(DQS_BITS+16):16];
end else begin: gen_seldqs_gt_32
assign dbg_sel_idel_dqs[3:0]
= vio3_out[19:16];
end
 
//dbg_sel_idel_gate
 
if (DQS_BITS <= 3) begin: gen_gtdqs_le_3
assign dbg_sel_idel_gate[DQS_BITS:0]
= vio3_out[(DQS_BITS+21):21];
end else begin: gen_gtdqs_gt_32
assign dbg_sel_idel_gate[3:0]
= vio3_out[24:21];
end
 
`endif // `ifdef XILINX_DDR2_CHIPSCOPE
assign vio2_in[3:0] = dbg_calib_done;
assign vio2_in[7:4] = dbg_calib_err;
assign dbg_idel_up_all = vio3_out[0];
assign dbg_idel_down_all = vio3_out[1];
assign dbg_idel_up_dq = vio3_out[2];
assign dbg_idel_down_dq = vio3_out[3];
assign dbg_idel_up_dqs = vio3_out[4];
assign dbg_idel_down_dqs = vio3_out[5];
assign dbg_idel_up_gate = vio3_out[6];
assign dbg_idel_down_gate = vio3_out[7];
assign dbg_sel_all_idel_dq = vio3_out[15];
assign dbg_sel_all_idel_dqs = vio3_out[20];
assign dbg_sel_all_idel_gate = vio3_out[25];
end
endgenerate
 
endmodule
/verilog/xilinx_ddr2/ddr2_chipscope.v
0,0 → 1,114
//*****************************************************************************
// DISCLAIMER OF LIABILITY
//
// This file contains proprietary and confidential information of
// Xilinx, Inc. ("Xilinx"), that is distributed under a license
// from Xilinx, and may be used, copied and/or disclosed only
// pursuant to the terms of a valid license agreement with Xilinx.
//
// XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION
// ("MATERIALS") "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
// EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING WITHOUT
// LIMITATION, ANY WARRANTY WITH RESPECT TO NONINFRINGEMENT,
// MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE. Xilinx
// does not warrant that functions included in the Materials will
// meet the requirements of Licensee, or that the operation of the
// Materials will be uninterrupted or error-free, or that defects
// in the Materials will be corrected. Furthermore, Xilinx does
// not warrant or make any representations regarding use, or the
// results of the use, of the Materials in terms of correctness,
// accuracy, reliability or otherwise.
//
// Xilinx products are not designed or intended to be fail-safe,
// or for use in any application requiring fail-safe performance,
// such as life-support or safety devices or systems, Class III
// medical devices, nuclear facilities, applications related to
// the deployment of airbags, or any other applications that could
// lead to death, personal injury or severe property or
// environmental damage (individually and collectively, "critical
// applications"). Customer assumes the sole risk and liability
// of any use of Xilinx products in critical applications,
// subject only to applicable laws and regulations governing
// limitations on product liability.
//
// Copyright 2006, 2007 Xilinx, Inc.
// All rights reserved.
//
// This disclaimer and copyright notice must be retained as part
// of this file at all times.
//*****************************************************************************
// ____ ____
// / /\/ /
// /___/ \ / Vendor: Xilinx
// \ \ \/ Version: 3.0
// \ \ Application: MIG
// / / Filename: ddr2_chipscope.v
// /___/ /\ Date Last Modified: $Data$
// \ \ / \ Date Created: 9/14/06
// \___\/\___\
//
//Device: Virtex-5
//Purpose:
// Skeleton Chipscope module declarations - for simulation only
//Reference:
//Revision History:
//
//*****************************************************************************
 
`timescale 1ns/1ps
 
module icon4
(
control0,
control1,
control2,
control3
)
/* synthesis syn_black_box syn_noprune = 1 */;
output [35:0] control0;
output [35:0] control1;
output [35:0] control2;
output [35:0] control3;
endmodule
 
module vio_async_in192
(
control,
async_in
)
/* synthesis syn_black_box syn_noprune = 1 */;
input [35:0] control;
input [191:0] async_in;
endmodule
 
module vio_async_in96
(
control,
async_in
)
/* synthesis syn_black_box syn_noprune = 1 */;
input [35:0] control;
input [95:0] async_in;
endmodule
 
module vio_async_in100
(
control,
async_in
)
/* synthesis syn_black_box syn_noprune = 1 */;
input [35:0] control;
input [99:0] async_in;
endmodule
 
module vio_sync_out32
(
control,
clk,
sync_out
)
/* synthesis syn_black_box syn_noprune = 1 */;
input [35:0] control;
input clk;
output [31:0] sync_out;
endmodule
/verilog/xilinx_ddr2/ddr2_phy_dq_iob.v
0,0 → 1,592
//*****************************************************************************
// DISCLAIMER OF LIABILITY
//
// This file contains proprietary and confidential information of
// Xilinx, Inc. ("Xilinx"), that is distributed under a license
// from Xilinx, and may be used, copied and/or disclosed only
// pursuant to the terms of a valid license agreement with Xilinx.
//
// XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION
// ("MATERIALS") "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
// EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING WITHOUT
// LIMITATION, ANY WARRANTY WITH RESPECT TO NONINFRINGEMENT,
// MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE. Xilinx
// does not warrant that functions included in the Materials will
// meet the requirements of Licensee, or that the operation of the
// Materials will be uninterrupted or error-free, or that defects
// in the Materials will be corrected. Furthermore, Xilinx does
// not warrant or make any representations regarding use, or the
// results of the use, of the Materials in terms of correctness,
// accuracy, reliability or otherwise.
//
// Xilinx products are not designed or intended to be fail-safe,
// or for use in any application requiring fail-safe performance,
// such as life-support or safety devices or systems, Class III
// medical devices, nuclear facilities, applications related to
// the deployment of airbags, or any other applications that could
// lead to death, personal injury or severe property or
// environmental damage (individually and collectively, "critical
// applications"). Customer assumes the sole risk and liability
// of any use of Xilinx products in critical applications,
// subject only to applicable laws and regulations governing
// limitations on product liability.
//
// Copyright 2006, 2007, 2008 Xilinx, Inc.
// All rights reserved.
//
// This disclaimer and copyright notice must be retained as part
// of this file at all times.
//*****************************************************************************
// ____ ____
// / /\/ /
// /___/ \ / Vendor: Xilinx
// \ \ \/ Version: 3.0
// \ \ Application: MIG
// / / Filename: ddr2_phy_dq_iob.v
// /___/ /\ Date Last Modified: $Date: 2009/01/15 14:22:14 $
// \ \ / \ Date Created: Wed Aug 16 2006
// \___\/\___\
//
//Device: Virtex-5
//Design Name: DDR2
//Purpose:
// This module places the data in the IOBs.
//Reference:
//Revision History:
// Rev 1.1 - Parameter HIGH_PERFORMANCE_MODE added. PK. 7/10/08
// Rev 1.2 - DIRT strings removed and modified the code. PK. 11/13/08
// Rev 1.3 - Parameter IODELAY_GRP added and constraint IODELAY_GROUP added
// on IODELAY primitive. PK. 11/27/08
//*****************************************************************************
 
`timescale 1ns/1ps
 
module ddr2_phy_dq_iob #
(
// Following parameters are for 72-bit RDIMM design (for ML561 Reference
// board design). Actual values may be different. Actual parameters values
// are passed from design top module ddr2_mig module. Please refer to
// the ddr2_mig module for actual values.
parameter HIGH_PERFORMANCE_MODE = "TRUE",
parameter IODELAY_GRP = "IODELAY_MIG",
parameter FPGA_SPEED_GRADE = 2
)
(
input clk0,
input clk90,
input clkdiv0,
input rst90,
input dlyinc,
input dlyce,
input dlyrst,
input [1:0] dq_oe_n,
input dqs,
input ce,
input rd_data_sel,
input wr_data_rise,
input wr_data_fall,
output rd_data_rise,
output rd_data_fall,
inout ddr_dq
);
 
wire dq_iddr_clk;
wire dq_idelay;
wire dq_in;
wire dq_oe_n_r;
wire dq_out;
wire stg2a_out_fall;
wire stg2a_out_rise;
(* XIL_PAR_DELAY = "0 ps", XIL_PAR_IP_NAME = "MIG", syn_keep = "1", keep = "TRUE" *)
wire stg2b_out_fall;
(* XIL_PAR_DELAY = "0 ps", XIL_PAR_IP_NAME = "MIG", syn_keep = "1", keep = "TRUE" *)
wire stg2b_out_rise;
wire stg3a_out_fall;
wire stg3a_out_rise;
wire stg3b_out_fall;
wire stg3b_out_rise;
 
//***************************************************************************
// Directed routing constraints for route between IDDR and stage 2 capture
// in fabric.
// Only 2 out of the 12 wire declarations will be used for any given
// instantiation of this module.
// Varies according:
// (1) I/O column (left, center, right) used
// (2) Which I/O in I/O pair (master, slave) used
// Nomenclature: _Xy, X = column (0 = left, 1 = center, 2 = right),
// y = master or slave
//***************************************************************************
 
// MODIFIED, RC, 06/13/08: Remove all references to DIRT, master/slave
 
(* XIL_PAR_DELAY = "500 ps", XIL_PAR_SKEW = "55 ps", XIL_PAR_IP_NAME = "MIG", syn_keep = "1", keep = "TRUE" *)
wire stg1_out_rise_sg3;
(* XIL_PAR_DELAY = "500 ps", XIL_PAR_SKEW = "55 ps", XIL_PAR_IP_NAME = "MIG", syn_keep = "1", keep = "TRUE" *)
wire stg1_out_fall_sg3;
(* XIL_PAR_DELAY = "575 ps", XIL_PAR_SKEW = "65 ps", XIL_PAR_IP_NAME = "MIG", syn_keep = "1", keep = "TRUE" *)
wire stg1_out_rise_sg2;
(* XIL_PAR_DELAY = "575 ps", XIL_PAR_SKEW = "65 ps", XIL_PAR_IP_NAME = "MIG", syn_keep = "1", keep = "TRUE" *)
wire stg1_out_fall_sg2;
(* XIL_PAR_DELAY = "650 ps", XIL_PAR_SKEW = "70 ps", XIL_PAR_IP_NAME = "MIG", syn_keep = "1", keep = "TRUE" *)
wire stg1_out_rise_sg1;
(* XIL_PAR_DELAY = "650 ps", XIL_PAR_SKEW = "70 ps", XIL_PAR_IP_NAME = "MIG", syn_keep = "1", keep = "TRUE" *)
wire stg1_out_fall_sg1;
 
//***************************************************************************
// Bidirectional I/O
//***************************************************************************
 
IOBUF u_iobuf_dq
(
.I (dq_out),
.T (dq_oe_n_r),
.IO (ddr_dq),
.O (dq_in)
);
 
//***************************************************************************
// Write (output) path
//***************************************************************************
 
// on a write, rising edge of DQS corresponds to rising edge of CLK180
// (aka falling edge of CLK0 -> rising edge DQS). We also know:
// 1. data must be driven 1/4 clk cycle before corresponding DQS edge
// 2. first rising DQS edge driven on falling edge of CLK0
// 3. rising data must be driven 1/4 cycle before falling edge of CLK0
// 4. therefore, rising data driven on rising edge of CLK
ODDR #
(
.SRTYPE("SYNC"),
.DDR_CLK_EDGE("SAME_EDGE")
)
u_oddr_dq
(
.Q (dq_out),
.C (clk90),
.CE (1'b1),
.D1 (wr_data_rise),
.D2 (wr_data_fall),
.R (1'b0),
.S (1'b0)
);
 
// make sure output is tri-state during reset (DQ_OE_N_R = 1)
ODDR #
(
.SRTYPE("ASYNC"),
.DDR_CLK_EDGE("SAME_EDGE")
)
u_tri_state_dq
(
.Q (dq_oe_n_r),
.C (clk90),
.CE (1'b1),
.D1 (dq_oe_n[0]),
.D2 (dq_oe_n[1]),
.R (1'b0),
.S (rst90)
);
 
//***************************************************************************
// Read data capture scheme description:
// Data capture consists of 3 ranks of flops, and a MUX
// 1. Rank 1 ("Stage 1"): IDDR captures delayed DDR DQ from memory using
// delayed DQS.
// - Data is split into 2 SDR streams, one each for rise and fall data.
// - BUFIO (DQS) input inverted to IDDR. IDDR configured in SAME_EDGE
// mode. This means that: (1) Q1 = fall data, Q2 = rise data,
// (2) Both rise and fall data are output on falling edge of DQS -
// rather than rise output being output on one edge of DQS, and fall
// data on the other edge if the IDDR were configured in OPPOSITE_EDGE
// mode. This simplifies Stage 2 capture (only one core clock edge
// used, removing effects of duty-cycle-distortion), and saves one
// fabric flop in Rank 3.
// 2. Rank 2 ("Stage 2"): Fabric flops are used to capture output of first
// rank into FPGA clock (CLK) domain. Each rising/falling SDR stream
// from IDDR is feed into two flops, one clocked off rising and one off
// falling edge of CLK. One of these flops is chosen, with the choice
// being the one that reduces # of DQ/DQS taps necessary to align Stage
// 1 and Stage 2. Same edge is used to capture both rise and fall SDR
// streams.
// 3. Rank 3 ("Stage 3"): Removes half-cycle paths in CLK domain from
// output of Rank 2. This stage, like Stage 2, is clocked by CLK. Note
// that Stage 3 can be expanded to also support SERDES functionality
// 4. Output MUX: Selects whether Stage 1 output is aligned to rising or
// falling edge of CLK (i.e. specifically this selects whether IDDR
// rise/fall output is transfered to rising or falling edge of CLK).
// Implementation:
// 1. Rank 1 is implemented using an IDDR primitive
// 2. Rank 2 is implemented using:
// - An RPM to fix the location of the capture flops near the DQ I/O.
// The exact RPM used depends on which I/O column (left, center,
// right) the DQ I/O is placed at - this affects the optimal location
// of the slice flops (or does it - can we always choose the two
// columns to slices to the immediate right of the I/O to use, no
// matter what the column?). The origin of the RPM must be set in the
// UCF file using the RLOC_ORIGIN constraint (where the original is
// based on the DQ I/O location).
// - Directed Routing Constraints ("DIRT strings") to fix the routing
// to the rank 2 fabric flops. This is done to minimize: (1) total
// route delay (and therefore minimize voltage/temperature-related
// variations), and (2) minimize skew both within each rising and
// falling data net, as well as between the rising and falling nets.
// The exact DIRT string used depends on: (1) which I/O column the
// DQ I/O is placed, and (2) whether the DQ I/O is placed on the
// "Master" or "Slave" I/O of a diff pair (DQ is not differential, but
// the routing will be affected by which of each I/O pair is used)
// 3. Rank 3 is implemented using fabric flops. No LOC or DIRT contraints
// are used, tools are expected to place these and meet PERIOD timing
// without constraints (constraints may be necessary for "full" designs,
// in this case, user may need to add LOC constraints - if this is the
// case, there are no constraints - other than meeting PERIOD timing -
// for rank 3 flops.
//***************************************************************************
 
//***************************************************************************
// MIG 2.2: Define AREA_GROUP = "DDR_CAPTURE_FFS" contain all RPM flops in
// design. In UCF file, add constraint:
// AREA_GROUP "DDR_CAPTURE_FFS" GROUP = CLOSED;
// This is done to prevent MAP from packing unrelated logic into
// the slices used by the RPMs. Doing so may cause the DIRT strings
// that define the IDDR -> fabric flop routing to later become
// unroutable during PAR because the unrelated logic placed by MAP
// may use routing resources required by the DIRT strings. MAP
// does not currently take into account DIRT strings when placing
// logic
//***************************************************************************
 
// IDELAY to delay incoming data for synchronization purposes
(* IODELAY_GROUP = IODELAY_GRP *) IODELAY #
(
.DELAY_SRC ("I"),
.IDELAY_TYPE ("VARIABLE"),
.HIGH_PERFORMANCE_MODE (HIGH_PERFORMANCE_MODE),
.IDELAY_VALUE (0),
.ODELAY_VALUE (0)
)
u_idelay_dq
(
.DATAOUT (dq_idelay),
.C (clkdiv0),
.CE (dlyce),
.DATAIN (),
.IDATAIN (dq_in),
.INC (dlyinc),
.ODATAIN (),
.RST (dlyrst),
.T ()
);
 
//***************************************************************************
// Rank 1 capture: Use IDDR to generate two SDR outputs
//***************************************************************************
 
// invert clock to IDDR in order to use SAME_EDGE mode (otherwise, we "run
// out of clocks" because DQS is not continuous
assign dq_iddr_clk = ~dqs;
 
//***************************************************************************
// Rank 2 capture: Use fabric flops to capture Rank 1 output. Use RPM and
// DIRT strings here.
// BEL ("Basic Element of Logic") and relative location constraints for
// second stage capture. C
// Varies according:
// (1) I/O column (left, center, right) used
// (2) Which I/O in I/O pair (master, slave) used
//***************************************************************************
 
// MODIFIED, RC, 06/13/08: Remove all references to DIRT, master/slave
// Take out generate statements - collapses to a single case
 
generate
if (FPGA_SPEED_GRADE == 3) begin: gen_stg2_sg3
IDDR #
(
.DDR_CLK_EDGE ("SAME_EDGE")
)
u_iddr_dq
(
.Q1 (stg1_out_fall_sg3),
.Q2 (stg1_out_rise_sg3),
.C (dq_iddr_clk),
.CE (ce),
.D (dq_idelay),
.R (1'b0),
.S (1'b0)
);
 
//*********************************************************
// Slice #1 (posedge CLK): Used for:
// 1. IDDR transfer to CLK0 rising edge domain ("stg2a")
// 2. stg2 falling edge -> stg3 rising edge transfer
//*********************************************************
 
// Stage 2 capture
FDRSE u_ff_stg2a_fall
(
.Q (stg2a_out_fall),
.C (clk0),
.CE (1'b1),
.D (stg1_out_fall_sg3),
.R (1'b0),
.S (1'b0)
)/* synthesis syn_preserve = 1 */
/* synthesis syn_replicate = 0 */;
FDRSE u_ff_stg2a_rise
(
.Q (stg2a_out_rise),
.C (clk0),
.CE (1'b1),
.D (stg1_out_rise_sg3),
.R (1'b0),
.S (1'b0)
)/* synthesis syn_preserve = 1 */
/* synthesis syn_replicate = 0 */;
// Stage 3 falling -> rising edge translation
FDRSE u_ff_stg3b_fall
(
.Q (stg3b_out_fall),
.C (clk0),
.CE (1'b1),
.D (stg2b_out_fall),
.R (1'b0),
.S (1'b0)
)/* synthesis syn_preserve = 1 */
/* synthesis syn_replicate = 0 */;
FDRSE u_ff_stg3b_rise
(
.Q (stg3b_out_rise),
.C (clk0),
.CE (1'b1),
.D (stg2b_out_rise),
.R (1'b0),
.S (1'b0)
)/* synthesis syn_preserve = 1 */
/* synthesis syn_replicate = 0 */;
 
//*********************************************************
// Slice #2 (posedge CLK): Used for:
// 1. IDDR transfer to CLK0 falling edge domain ("stg2b")
//*********************************************************
 
FDRSE_1 u_ff_stg2b_fall
(
.Q (stg2b_out_fall),
.C (clk0),
.CE (1'b1),
.D (stg1_out_fall_sg3),
.R (1'b0),
.S (1'b0)
)/* synthesis syn_preserve = 1 */
/* synthesis syn_replicate = 0 */;
 
FDRSE_1 u_ff_stg2b_rise
(
.Q (stg2b_out_rise),
.C (clk0),
.CE (1'b1),
.D (stg1_out_rise_sg3),
.R (1'b0),
.S (1'b0)
)/* synthesis syn_preserve = 1 */
/* synthesis syn_replicate = 0 */;
end else if (FPGA_SPEED_GRADE == 2) begin: gen_stg2_sg2
IDDR #
(
.DDR_CLK_EDGE ("SAME_EDGE")
)
u_iddr_dq
(
.Q1 (stg1_out_fall_sg2),
.Q2 (stg1_out_rise_sg2),
.C (dq_iddr_clk),
.CE (ce),
.D (dq_idelay),
.R (1'b0),
.S (1'b0)
);
 
//*********************************************************
// Slice #1 (posedge CLK): Used for:
// 1. IDDR transfer to CLK0 rising edge domain ("stg2a")
// 2. stg2 falling edge -> stg3 rising edge transfer
//*********************************************************
 
// Stage 2 capture
FDRSE u_ff_stg2a_fall
(
.Q (stg2a_out_fall),
.C (clk0),
.CE (1'b1),
.D (stg1_out_fall_sg2),
.R (1'b0),
.S (1'b0)
)/* synthesis syn_preserve = 1 */
/* synthesis syn_replicate = 0 */;
FDRSE u_ff_stg2a_rise
(
.Q (stg2a_out_rise),
.C (clk0),
.CE (1'b1),
.D (stg1_out_rise_sg2),
.R (1'b0),
.S (1'b0)
)/* synthesis syn_preserve = 1 */
/* synthesis syn_replicate = 0 */;
// Stage 3 falling -> rising edge translation
FDRSE u_ff_stg3b_fall
(
.Q (stg3b_out_fall),
.C (clk0),
.CE (1'b1),
.D (stg2b_out_fall),
.R (1'b0),
.S (1'b0)
)/* synthesis syn_preserve = 1 */
/* synthesis syn_replicate = 0 */;
FDRSE u_ff_stg3b_rise
(
.Q (stg3b_out_rise),
.C (clk0),
.CE (1'b1),
.D (stg2b_out_rise),
.R (1'b0),
.S (1'b0)
)/* synthesis syn_preserve = 1 */
/* synthesis syn_replicate = 0 */;
 
//*********************************************************
// Slice #2 (posedge CLK): Used for:
// 1. IDDR transfer to CLK0 falling edge domain ("stg2b")
//*********************************************************
 
FDRSE_1 u_ff_stg2b_fall
(
.Q (stg2b_out_fall),
.C (clk0),
.CE (1'b1),
.D (stg1_out_fall_sg2),
.R (1'b0),
.S (1'b0)
)/* synthesis syn_preserve = 1 */
/* synthesis syn_replicate = 0 */;
 
FDRSE_1 u_ff_stg2b_rise
(
.Q (stg2b_out_rise),
.C (clk0),
.CE (1'b1),
.D (stg1_out_rise_sg2),
.R (1'b0),
.S (1'b0)
)/* synthesis syn_preserve = 1 */
/* synthesis syn_replicate = 0 */;
end else if (FPGA_SPEED_GRADE == 1) begin: gen_stg2_sg1
IDDR #
(
.DDR_CLK_EDGE ("SAME_EDGE")
)
u_iddr_dq
(
.Q1 (stg1_out_fall_sg1),
.Q2 (stg1_out_rise_sg1),
.C (dq_iddr_clk),
.CE (ce),
.D (dq_idelay),
.R (1'b0),
.S (1'b0)
);
 
//*********************************************************
// Slice #1 (posedge CLK): Used for:
// 1. IDDR transfer to CLK0 rising edge domain ("stg2a")
// 2. stg2 falling edge -> stg3 rising edge transfer
//*********************************************************
 
// Stage 2 capture
FDRSE u_ff_stg2a_fall
(
.Q (stg2a_out_fall),
.C (clk0),
.CE (1'b1),
.D (stg1_out_fall_sg1),
.R (1'b0),
.S (1'b0)
)/* synthesis syn_preserve = 1 */
/* synthesis syn_replicate = 0 */;
FDRSE u_ff_stg2a_rise
(
.Q (stg2a_out_rise),
.C (clk0),
.CE (1'b1),
.D (stg1_out_rise_sg1),
.R (1'b0),
.S (1'b0)
)/* synthesis syn_preserve = 1 */
/* synthesis syn_replicate = 0 */;
// Stage 3 falling -> rising edge translation
FDRSE u_ff_stg3b_fall
(
.Q (stg3b_out_fall),
.C (clk0),
.CE (1'b1),
.D (stg2b_out_fall),
.R (1'b0),
.S (1'b0)
)/* synthesis syn_preserve = 1 */
/* synthesis syn_replicate = 0 */;
FDRSE u_ff_stg3b_rise
(
.Q (stg3b_out_rise),
.C (clk0),
.CE (1'b1),
.D (stg2b_out_rise),
.R (1'b0),
.S (1'b0)
)/* synthesis syn_preserve = 1 */
/* synthesis syn_replicate = 0 */;
 
//*********************************************************
// Slice #2 (posedge CLK): Used for:
// 1. IDDR transfer to CLK0 falling edge domain ("stg2b")
//*********************************************************
 
FDRSE_1 u_ff_stg2b_fall
(
.Q (stg2b_out_fall),
.C (clk0),
.CE (1'b1),
.D (stg1_out_fall_sg1),
.R (1'b0),
.S (1'b0)
)/* synthesis syn_preserve = 1 */
/* synthesis syn_replicate = 0 */;
 
FDRSE_1 u_ff_stg2b_rise
(
.Q (stg2b_out_rise),
.C (clk0),
.CE (1'b1),
.D (stg1_out_rise_sg1),
.R (1'b0),
.S (1'b0)
)/* synthesis syn_preserve = 1 */
/* synthesis syn_replicate = 0 */;
end
endgenerate
 
//***************************************************************************
// Second stage flops clocked by posedge CLK0 don't need another layer of
// registering
//***************************************************************************
 
assign stg3a_out_rise = stg2a_out_rise;
assign stg3a_out_fall = stg2a_out_fall;
 
//*******************************************************************
 
assign rd_data_rise = (rd_data_sel) ? stg3a_out_rise : stg3b_out_rise;
assign rd_data_fall = (rd_data_sel) ? stg3a_out_fall : stg3b_out_fall;
 
endmodule
/verilog/xilinx_ddr2/README
0,0 → 1,17
Xilinx DDR2 controller with Wishbone interface
 
This is a Xilinx technology-dependent DDR2 memory controller, based on a
controller from Xilinx's memory interface generator (MIG), with a small cache
memory and Wishbone wrapper.
 
The xilinx_ddr2_wb_if.v is a 3-master arbiter for the controller.
The xilinx_ddr2_if.v is the actual interface between the Wishbone bus and
Xilinx MIG control interface.
 
When synthesizing, take note of the xilinx_ddr2_if_cache module, that is a
dual-port memory, with different aspects on each size, and cannot be inferred.
The NGC should be in the appropriate place in the synthesis or backend
directories.
 
Wishbone B3-compliant bursting is yet to be implemented.
 
/verilog/xilinx_ddr2/ddr2_mem_if_top.v
0,0 → 1,382
//*****************************************************************************
// DISCLAIMER OF LIABILITY
//
// This file contains proprietary and confidential information of
// Xilinx, Inc. ("Xilinx"), that is distributed under a license
// from Xilinx, and may be used, copied and/or disclosed only
// pursuant to the terms of a valid license agreement with Xilinx.
//
// XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION
// ("MATERIALS") "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
// EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING WITHOUT
// LIMITATION, ANY WARRANTY WITH RESPECT TO NONINFRINGEMENT,
// MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE. Xilinx
// does not warrant that functions included in the Materials will
// meet the requirements of Licensee, or that the operation of the
// Materials will be uninterrupted or error-free, or that defects
// in the Materials will be corrected. Furthermore, Xilinx does
// not warrant or make any representations regarding use, or the
// results of the use, of the Materials in terms of correctness,
// accuracy, reliability or otherwise.
//
// Xilinx products are not designed or intended to be fail-safe,
// or for use in any application requiring fail-safe performance,
// such as life-support or safety devices or systems, Class III
// medical devices, nuclear facilities, applications related to
// the deployment of airbags, or any other applications that could
// lead to death, personal injury or severe property or
// environmental damage (individually and collectively, "critical
// applications"). Customer assumes the sole risk and liability
// of any use of Xilinx products in critical applications,
// subject only to applicable laws and regulations governing
// limitations on product liability.
//
// Copyright 2006, 2007, 2008 Xilinx, Inc.
// All rights reserved.
//
// This disclaimer and copyright notice must be retained as part
// of this file at all times.
//*****************************************************************************
// ____ ____
// / /\/ /
// /___/ \ / Vendor: Xilinx
// \ \ \/ Version: 3.0
// \ \ Application: MIG
// / / Filename: ddr2_mem_if_top.v
// /___/ /\ Date Last Modified: $Date: 2009/01/15 14:22:14 $
// \ \ / \ Date Created: Wed Aug 16 2006
// \___\/\___\
//
//Device: Virtex-5
//Design Name: DDR/DDR2
//Purpose:
// Top-level for parameterizable (DDR or DDR2) memory interface
//Reference:
//Revision History:
// Rev 1.1 - Parameter USE_DM_PORT added. PK. 6/25/08
// Rev 1.2 - Parameter HIGH_PERFORMANCE_MODE added. PK. 7/10/08
// Rev 1.3 - Parameter CS_BITS added. PK. 10/8/08
// Rev 1.4 - Parameter IODELAY_GRP added. PK. 11/27/08
//*****************************************************************************
 
`timescale 1ns/1ps
 
module ddr2_mem_if_top #
(
// Following parameters are for 72-bit RDIMM design (for ML561 Reference
// board design). Actual values may be different. Actual parameters values
// are passed from design top module ddr2_mig module. Please refer to
// the ddr2_mig module for actual values.
parameter BANK_WIDTH = 2,
parameter CKE_WIDTH = 1,
parameter CLK_WIDTH = 1,
parameter COL_WIDTH = 10,
parameter CS_BITS = 0,
parameter CS_NUM = 1,
parameter CS_WIDTH = 1,
parameter USE_DM_PORT = 1,
parameter DM_WIDTH = 9,
parameter DQ_WIDTH = 72,
parameter DQ_BITS = 7,
parameter DQ_PER_DQS = 8,
parameter DQS_BITS = 4,
parameter DQS_WIDTH = 9,
parameter HIGH_PERFORMANCE_MODE = "TRUE",
parameter IODELAY_GRP = "IODELAY_MIG",
parameter ODT_WIDTH = 1,
parameter ROW_WIDTH = 14,
parameter APPDATA_WIDTH = 144,
parameter ADDITIVE_LAT = 0,
parameter BURST_LEN = 4,
parameter BURST_TYPE = 0,
parameter CAS_LAT = 5,
parameter ECC_ENABLE = 0,
parameter MULTI_BANK_EN = 1,
parameter TWO_T_TIME_EN = 0,
parameter ODT_TYPE = 1,
parameter DDR_TYPE = 1,
parameter REDUCE_DRV = 0,
parameter REG_ENABLE = 1,
parameter TREFI_NS = 7800,
parameter TRAS = 40000,
parameter TRCD = 15000,
parameter TRFC = 105000,
parameter TRP = 15000,
parameter TRTP = 7500,
parameter TWR = 15000,
parameter TWTR = 10000,
parameter CLK_PERIOD = 3000,
parameter SIM_ONLY = 0,
parameter DEBUG_EN = 0,
parameter FPGA_SPEED_GRADE = 2
)
(
input clk0,
input usr_clk, // jb
input clk90,
input clkdiv0,
input rst0,
input rst90,
input rstdiv0,
input [2:0] app_af_cmd,
input [30:0] app_af_addr,
input app_af_wren,
input app_wdf_wren,
input [APPDATA_WIDTH-1:0] app_wdf_data,
input [(APPDATA_WIDTH/8)-1:0] app_wdf_mask_data,
output [1:0] rd_ecc_error,
output app_af_afull,
output app_wdf_afull,
output rd_data_valid,
output [APPDATA_WIDTH-1:0] rd_data_fifo_out,
output phy_init_done,
output [CLK_WIDTH-1:0] ddr_ck,
output [CLK_WIDTH-1:0] ddr_ck_n,
output [ROW_WIDTH-1:0] ddr_addr,
output [BANK_WIDTH-1:0] ddr_ba,
output ddr_ras_n,
output ddr_cas_n,
output ddr_we_n,
output [CS_WIDTH-1:0] ddr_cs_n,
output [CKE_WIDTH-1:0] ddr_cke,
output [ODT_WIDTH-1:0] ddr_odt,
output [DM_WIDTH-1:0] ddr_dm,
inout [DQS_WIDTH-1:0] ddr_dqs,
inout [DQS_WIDTH-1:0] ddr_dqs_n,
inout [DQ_WIDTH-1:0] ddr_dq,
// Debug signals (optional use)
input dbg_idel_up_all,
input dbg_idel_down_all,
input dbg_idel_up_dq,
input dbg_idel_down_dq,
input dbg_idel_up_dqs,
input dbg_idel_down_dqs,
input dbg_idel_up_gate,
input dbg_idel_down_gate,
input [DQ_BITS-1:0] dbg_sel_idel_dq,
input dbg_sel_all_idel_dq,
input [DQS_BITS:0] dbg_sel_idel_dqs,
input dbg_sel_all_idel_dqs,
input [DQS_BITS:0] dbg_sel_idel_gate,
input dbg_sel_all_idel_gate,
output [3:0] dbg_calib_done,
output [3:0] dbg_calib_err,
output [(6*DQ_WIDTH)-1:0] dbg_calib_dq_tap_cnt,
output [(6*DQS_WIDTH)-1:0] dbg_calib_dqs_tap_cnt,
output [(6*DQS_WIDTH)-1:0] dbg_calib_gate_tap_cnt,
output [DQS_WIDTH-1:0] dbg_calib_rd_data_sel,
output [(5*DQS_WIDTH)-1:0] dbg_calib_rden_dly,
output [(5*DQS_WIDTH)-1:0] dbg_calib_gate_dly
);
 
wire [30:0] af_addr;
wire [2:0] af_cmd;
wire af_empty;
wire [ROW_WIDTH-1:0] ctrl_addr;
wire ctrl_af_rden;
wire [BANK_WIDTH-1:0] ctrl_ba;
wire ctrl_cas_n;
wire [CS_NUM-1:0] ctrl_cs_n;
wire ctrl_ras_n;
wire ctrl_rden;
wire ctrl_ref_flag;
wire ctrl_we_n;
wire ctrl_wren;
wire [DQS_WIDTH-1:0] phy_calib_rden;
wire [DQS_WIDTH-1:0] phy_calib_rden_sel;
wire [DQ_WIDTH-1:0] rd_data_fall;
wire [DQ_WIDTH-1:0] rd_data_rise;
wire [(2*DQ_WIDTH)-1:0] wdf_data;
wire [((2*DQ_WIDTH)/8)-1:0] wdf_mask_data;
wire wdf_rden;
 
//***************************************************************************
 
ddr2_phy_top #
(
.BANK_WIDTH (BANK_WIDTH),
.CKE_WIDTH (CKE_WIDTH),
.CLK_WIDTH (CLK_WIDTH),
.COL_WIDTH (COL_WIDTH),
.CS_BITS (CS_BITS),
.CS_NUM (CS_NUM),
.CS_WIDTH (CS_WIDTH),
.USE_DM_PORT (USE_DM_PORT),
.DM_WIDTH (DM_WIDTH),
.DQ_WIDTH (DQ_WIDTH),
.DQ_BITS (DQ_BITS),
.DQ_PER_DQS (DQ_PER_DQS),
.DQS_BITS (DQS_BITS),
.DQS_WIDTH (DQS_WIDTH),
.HIGH_PERFORMANCE_MODE (HIGH_PERFORMANCE_MODE),
.IODELAY_GRP (IODELAY_GRP),
.ODT_WIDTH (ODT_WIDTH),
.ROW_WIDTH (ROW_WIDTH),
.TWO_T_TIME_EN (TWO_T_TIME_EN),
.ADDITIVE_LAT (ADDITIVE_LAT),
.BURST_LEN (BURST_LEN),
.BURST_TYPE (BURST_TYPE),
.CAS_LAT (CAS_LAT),
.ECC_ENABLE (ECC_ENABLE),
.ODT_TYPE (ODT_TYPE),
.DDR_TYPE (DDR_TYPE),
.REDUCE_DRV (REDUCE_DRV),
.REG_ENABLE (REG_ENABLE),
.TWR (TWR),
.CLK_PERIOD (CLK_PERIOD),
.SIM_ONLY (SIM_ONLY),
.DEBUG_EN (DEBUG_EN),
.FPGA_SPEED_GRADE (FPGA_SPEED_GRADE)
)
u_phy_top
(
.clk0 (clk0),
.clk90 (clk90),
.clkdiv0 (clkdiv0),
.rst0 (rst0),
.rst90 (rst90),
.rstdiv0 (rstdiv0),
.ctrl_wren (ctrl_wren),
.ctrl_addr (ctrl_addr),
.ctrl_ba (ctrl_ba),
.ctrl_ras_n (ctrl_ras_n),
.ctrl_cas_n (ctrl_cas_n),
.ctrl_we_n (ctrl_we_n),
.ctrl_cs_n (ctrl_cs_n),
.ctrl_rden (ctrl_rden),
.ctrl_ref_flag (ctrl_ref_flag),
.wdf_data (wdf_data),
.wdf_mask_data (wdf_mask_data),
.wdf_rden (wdf_rden),
.phy_init_done (phy_init_done),
.phy_calib_rden (phy_calib_rden),
.phy_calib_rden_sel (phy_calib_rden_sel),
.rd_data_rise (rd_data_rise),
.rd_data_fall (rd_data_fall),
.ddr_ck (ddr_ck),
.ddr_ck_n (ddr_ck_n),
.ddr_addr (ddr_addr),
.ddr_ba (ddr_ba),
.ddr_ras_n (ddr_ras_n),
.ddr_cas_n (ddr_cas_n),
.ddr_we_n (ddr_we_n),
.ddr_cs_n (ddr_cs_n),
.ddr_cke (ddr_cke),
.ddr_odt (ddr_odt),
.ddr_dm (ddr_dm),
.ddr_dqs (ddr_dqs),
.ddr_dqs_n (ddr_dqs_n),
.ddr_dq (ddr_dq),
.dbg_idel_up_all (dbg_idel_up_all),
.dbg_idel_down_all (dbg_idel_down_all),
.dbg_idel_up_dq (dbg_idel_up_dq),
.dbg_idel_down_dq (dbg_idel_down_dq),
.dbg_idel_up_dqs (dbg_idel_up_dqs),
.dbg_idel_down_dqs (dbg_idel_down_dqs),
.dbg_idel_up_gate (dbg_idel_up_gate),
.dbg_idel_down_gate (dbg_idel_down_gate),
.dbg_sel_idel_dq (dbg_sel_idel_dq),
.dbg_sel_all_idel_dq (dbg_sel_all_idel_dq),
.dbg_sel_idel_dqs (dbg_sel_idel_dqs),
.dbg_sel_all_idel_dqs (dbg_sel_all_idel_dqs),
.dbg_sel_idel_gate (dbg_sel_idel_gate),
.dbg_sel_all_idel_gate (dbg_sel_all_idel_gate),
.dbg_calib_done (dbg_calib_done),
.dbg_calib_err (dbg_calib_err),
.dbg_calib_dq_tap_cnt (dbg_calib_dq_tap_cnt),
.dbg_calib_dqs_tap_cnt (dbg_calib_dqs_tap_cnt),
.dbg_calib_gate_tap_cnt (dbg_calib_gate_tap_cnt),
.dbg_calib_rd_data_sel (dbg_calib_rd_data_sel),
.dbg_calib_rden_dly (dbg_calib_rden_dly),
.dbg_calib_gate_dly (dbg_calib_gate_dly)
);
 
ddr2_usr_top #
(
.BANK_WIDTH (BANK_WIDTH),
.COL_WIDTH (COL_WIDTH),
.CS_BITS (CS_BITS),
.DQ_WIDTH (DQ_WIDTH),
.DQ_PER_DQS (DQ_PER_DQS),
.DQS_WIDTH (DQS_WIDTH),
.APPDATA_WIDTH (APPDATA_WIDTH),
.ECC_ENABLE (ECC_ENABLE),
.ROW_WIDTH (ROW_WIDTH)
)
u_usr_top
(
.clk0 (clk0),
.usr_clk (usr_clk), //jb
.clk90 (clk90),
.rst0 (rst0),
.rd_data_in_rise (rd_data_rise),
.rd_data_in_fall (rd_data_fall),
.phy_calib_rden (phy_calib_rden),
.phy_calib_rden_sel(phy_calib_rden_sel),
.rd_data_valid (rd_data_valid),
.rd_ecc_error (rd_ecc_error),
.rd_data_fifo_out (rd_data_fifo_out),
.app_af_cmd (app_af_cmd),
.app_af_addr (app_af_addr),
.app_af_wren (app_af_wren),
.ctrl_af_rden (ctrl_af_rden),
.af_cmd (af_cmd),
.af_addr (af_addr),
.af_empty (af_empty),
.app_af_afull (app_af_afull),
.app_wdf_wren (app_wdf_wren),
.app_wdf_data (app_wdf_data),
.app_wdf_mask_data (app_wdf_mask_data),
.wdf_rden (wdf_rden),
.app_wdf_afull (app_wdf_afull),
.wdf_data (wdf_data),
.wdf_mask_data (wdf_mask_data)
);
 
 
ddr2_ctrl #
(
.BANK_WIDTH (BANK_WIDTH),
.COL_WIDTH (COL_WIDTH),
.CS_BITS (CS_BITS),
.CS_NUM (CS_NUM),
.ROW_WIDTH (ROW_WIDTH),
.ADDITIVE_LAT (ADDITIVE_LAT),
.BURST_LEN (BURST_LEN),
.CAS_LAT (CAS_LAT),
.ECC_ENABLE (ECC_ENABLE),
.REG_ENABLE (REG_ENABLE),
.MULTI_BANK_EN (MULTI_BANK_EN),
.TWO_T_TIME_EN (TWO_T_TIME_EN),
.TREFI_NS (TREFI_NS),
.TRAS (TRAS),
.TRCD (TRCD),
.TRFC (TRFC),
.TRP (TRP),
.TRTP (TRTP),
.TWR (TWR),
.TWTR (TWTR),
.CLK_PERIOD (CLK_PERIOD),
.DDR_TYPE (DDR_TYPE)
)
u_ctrl
(
.clk (clk0),
.rst (rst0),
.af_cmd (af_cmd),
.af_addr (af_addr),
.af_empty (af_empty),
.phy_init_done (phy_init_done),
.ctrl_ref_flag (ctrl_ref_flag),
.ctrl_af_rden (ctrl_af_rden),
.ctrl_wren (ctrl_wren),
.ctrl_rden (ctrl_rden),
.ctrl_addr (ctrl_addr),
.ctrl_ba (ctrl_ba),
.ctrl_ras_n (ctrl_ras_n),
.ctrl_cas_n (ctrl_cas_n),
.ctrl_we_n (ctrl_we_n),
.ctrl_cs_n (ctrl_cs_n)
);
 
endmodule
/verilog/xilinx_ddr2/ddr2_infrastructure.v
0,0 → 1,352
//*****************************************************************************
// DISCLAIMER OF LIABILITY
//
// This file contains proprietary and confidential information of
// Xilinx, Inc. ("Xilinx"), that is distributed under a license
// from Xilinx, and may be used, copied and/or disclosed only
// pursuant to the terms of a valid license agreement with Xilinx.
//
// XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION
// ("MATERIALS") "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
// EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING WITHOUT
// LIMITATION, ANY WARRANTY WITH RESPECT TO NONINFRINGEMENT,
// MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE. Xilinx
// does not warrant that functions included in the Materials will
// meet the requirements of Licensee, or that the operation of the
// Materials will be uninterrupted or error-free, or that defects
// in the Materials will be corrected. Furthermore, Xilinx does
// not warrant or make any representations regarding use, or the
// results of the use, of the Materials in terms of correctness,
// accuracy, reliability or otherwise.
//
// Xilinx products are not designed or intended to be fail-safe,
// or for use in any application requiring fail-safe performance,
// such as life-support or safety devices or systems, Class III
// medical devices, nuclear facilities, applications related to
// the deployment of airbags, or any other applications that could
// lead to death, personal injury or severe property or
// environmental damage (individually and collectively, "critical
// applications"). Customer assumes the sole risk and liability
// of any use of Xilinx products in critical applications,
// subject only to applicable laws and regulations governing
// limitations on product liability.
//
// Copyright 2006, 2007, 2008 Xilinx, Inc.
// All rights reserved.
//
// This disclaimer and copyright notice must be retained as part
// of this file at all times.
//*****************************************************************************
// ____ ____
// / /\/ /
// /___/ \ / Vendor: Xilinx
// \ \ \/ Version: 3.0
// \ \ Application: MIG
// / / Filename: ddr2_infrastructure.v
// /___/ /\ Date Last Modified: $Date: 2008/12/23 14:26:00 $
// \ \ / \ Date Created: Wed Aug 16 2006
// \___\/\___\
//
//Device: Virtex-5
//Design Name: DDR2
//Purpose:
// Clock generation/distribution and reset synchronization
//Reference:
//Revision History:
// Rev 1.1 - Parameter CLK_TYPE added and logic for DIFFERENTIAL and
// SINGLE_ENDED added. PK. 6/20/08
// Rev 1.2 - Loacalparam CLK_GENERATOR added and logic for clocks generation
// using PLL or DCM added as generic code. PK. 10/14/08
//*****************************************************************************
 
`timescale 1ns/1ps
 
module ddr2_infrastructure #
(
// Following parameters are for 72-bit RDIMM design (for ML561 Reference
// board design). Actual values may be different. Actual parameters values
// are passed from design top module ddr2_mig module. Please refer to
// the ddr2_mig module for actual values.
parameter CLK_PERIOD = 3000,
parameter CLK_TYPE = "DIFFERENTIAL",
parameter DLL_FREQ_MODE = "HIGH",
parameter RST_ACT_LOW = 1
)
(
input sys_clk_p,
input sys_clk_n,
input sys_clk,
input clk200_p,
input clk200_n,
input idly_clk_200,
output clk0,
output clk90,
output clk200,
output clkdiv0,
input sys_rst_n,
input idelay_ctrl_rdy,
output rst0,
output rst90,
output rst200,
output rstdiv0
);
 
// # of clock cycles to delay deassertion of reset. Needs to be a fairly
// high number not so much for metastability protection, but to give time
// for reset (i.e. stable clock cycles) to propagate through all state
// machines and to all control signals (i.e. not all control signals have
// resets, instead they rely on base state logic being reset, and the effect
// of that reset propagating through the logic). Need this because we may not
// be getting stable clock cycles while reset asserted (i.e. since reset
// depends on PLL/DCM lock status)
localparam RST_SYNC_NUM = 25;
localparam CLK_PERIOD_NS = CLK_PERIOD / 1000.0;
localparam CLK_PERIOD_INT = CLK_PERIOD/1000;
 
// By default this Parameter (CLK_GENERATOR) value is "PLL". If this
// Parameter is set to "PLL", PLL is used to generate the design clocks.
// If this Parameter is set to "DCM",
// DCM is used to generate the design clocks.
localparam CLK_GENERATOR = "PLL";
 
wire clk0_bufg;
wire clk0_bufg_in;
wire clk90_bufg;
wire clk90_bufg_in;
wire clk200_bufg;
wire clk200_ibufg;
wire clkdiv0_bufg;
wire clkdiv0_bufg_in;
wire clkfbout_clkfbin;
wire locked;
reg [RST_SYNC_NUM-1:0] rst0_sync_r /* synthesis syn_maxfan = 10 */;
reg [RST_SYNC_NUM-1:0] rst200_sync_r /* synthesis syn_maxfan = 10 */;
reg [RST_SYNC_NUM-1:0] rst90_sync_r /* synthesis syn_maxfan = 10 */;
reg [(RST_SYNC_NUM/2)-1:0] rstdiv0_sync_r /* synthesis syn_maxfan = 10 */;
wire rst_tmp;
wire sys_clk_ibufg;
wire sys_rst;
 
assign sys_rst = RST_ACT_LOW ? ~sys_rst_n: sys_rst_n;
 
assign clk0 = clk0_bufg;
assign clk90 = clk90_bufg;
assign clk200 = clk200_bufg;
assign clkdiv0 = clkdiv0_bufg;
 
generate
if(CLK_TYPE == "DIFFERENTIAL") begin : DIFF_ENDED_CLKS_INST
//***************************************************************************
// Differential input clock input buffers
//***************************************************************************
 
IBUFGDS_LVPECL_25 SYS_CLK_INST
(
.I (sys_clk_p),
.IB (sys_clk_n),
.O (sys_clk_ibufg)
);
 
IBUFGDS_LVPECL_25 IDLY_CLK_INST
(
.I (clk200_p),
.IB (clk200_n),
.O (clk200_ibufg)
);
 
end/* else if(CLK_TYPE == "SINGLE_ENDED") begin : SINGLE_ENDED_CLKS_INST
//**************************************************************************
// Single ended input clock input buffers
//**************************************************************************
 
IBUFG SYS_CLK_INST
(
.I (sys_clk),
.O (sys_clk_ibufg)
);
 
IBUFG IDLY_CLK_INST
(
.I (idly_clk_200),
.O (clk200_ibufg)
);
// This is being instantiated inside another design. these signals are properly generated elsewhere -- jb
end*/
endgenerate
assign sys_clk_ibufg = sys_clk;
//assign idly_clk_200 = clk200_ibufg;
assign clk200_bufg = idly_clk_200;
/*
BUFG CLK_200_BUFG
(
.O (clk200_bufg),
.I (clk200_ibufg)
);
*/
//***************************************************************************
// Global clock generation and distribution
//***************************************************************************
 
generate
if (CLK_GENERATOR == "PLL") begin : gen_pll_adv
PLL_ADV #
(
.BANDWIDTH ("OPTIMIZED"),
.CLKIN1_PERIOD (CLK_PERIOD_NS),
.CLKIN2_PERIOD (10.000),
.CLKOUT0_DIVIDE (CLK_PERIOD_INT),
.CLKOUT1_DIVIDE (CLK_PERIOD_INT),
.CLKOUT2_DIVIDE (CLK_PERIOD_INT*2),
.CLKOUT3_DIVIDE (1),
.CLKOUT4_DIVIDE (1),
.CLKOUT5_DIVIDE (1),
.CLKOUT0_PHASE (0.000),
.CLKOUT1_PHASE (90.000),
.CLKOUT2_PHASE (0.000),
.CLKOUT3_PHASE (0.000),
.CLKOUT4_PHASE (0.000),
.CLKOUT5_PHASE (0.000),
.CLKOUT0_DUTY_CYCLE (0.500),
.CLKOUT1_DUTY_CYCLE (0.500),
.CLKOUT2_DUTY_CYCLE (0.500),
.CLKOUT3_DUTY_CYCLE (0.500),
.CLKOUT4_DUTY_CYCLE (0.500),
.CLKOUT5_DUTY_CYCLE (0.500),
.COMPENSATION ("SYSTEM_SYNCHRONOUS"),
.DIVCLK_DIVIDE (1),
.CLKFBOUT_MULT (CLK_PERIOD_INT),
.CLKFBOUT_PHASE (0.0),
.REF_JITTER (0.005000)
)
u_pll_adv
(
.CLKFBIN (clkfbout_clkfbin),
.CLKINSEL (1'b1),
.CLKIN1 (sys_clk_ibufg),
.CLKIN2 (1'b0),
.DADDR (5'b0),
.DCLK (1'b0),
.DEN (1'b0),
.DI (16'b0),
.DWE (1'b0),
.REL (1'b0),
.RST (sys_rst),
.CLKFBDCM (),
.CLKFBOUT (clkfbout_clkfbin),
.CLKOUTDCM0 (),
.CLKOUTDCM1 (),
.CLKOUTDCM2 (),
.CLKOUTDCM3 (),
.CLKOUTDCM4 (),
.CLKOUTDCM5 (),
.CLKOUT0 (clk0_bufg_in),
.CLKOUT1 (clk90_bufg_in),
.CLKOUT2 (clkdiv0_bufg_in),
.CLKOUT3 (),
.CLKOUT4 (),
.CLKOUT5 (),
.DO (),
.DRDY (),
.LOCKED (locked)
);
end else if (CLK_GENERATOR == "DCM") begin: gen_dcm_base
DCM_BASE #
(
.CLKIN_PERIOD (CLK_PERIOD_NS),
.CLKDV_DIVIDE (2.0),
.DLL_FREQUENCY_MODE (DLL_FREQ_MODE),
.DUTY_CYCLE_CORRECTION ("TRUE"),
.FACTORY_JF (16'hF0F0)
)
u_dcm_base
(
.CLK0 (clk0_bufg_in),
.CLK180 (),
.CLK270 (),
.CLK2X (),
.CLK2X180 (),
.CLK90 (clk90_bufg_in),
.CLKDV (clkdiv0_bufg_in),
.CLKFX (),
.CLKFX180 (),
.LOCKED (locked),
.CLKFB (clk0_bufg),
.CLKIN (sys_clk_ibufg),
.RST (sys_rst)
);
end
endgenerate
 
BUFG U_BUFG_CLK0
(
.O (clk0_bufg),
.I (clk0_bufg_in)
);
 
BUFG U_BUFG_CLK90
(
.O (clk90_bufg),
.I (clk90_bufg_in)
);
 
BUFG U_BUFG_CLKDIV0
(
.O (clkdiv0_bufg),
.I (clkdiv0_bufg_in)
);
 
 
//***************************************************************************
// Reset synchronization
// NOTES:
// 1. shut down the whole operation if the PLL/ DCM hasn't yet locked (and
// by inference, this means that external SYS_RST_IN has been asserted -
// PLL/DCM deasserts LOCKED as soon as SYS_RST_IN asserted)
// 2. In the case of all resets except rst200, also assert reset if the
// IDELAY master controller is not yet ready
// 3. asynchronously assert reset. This was we can assert reset even if
// there is no clock (needed for things like 3-stating output buffers).
// reset deassertion is synchronous.
//***************************************************************************
 
assign rst_tmp = sys_rst | ~locked | ~idelay_ctrl_rdy;
 
// synthesis attribute max_fanout of rst0_sync_r is 10
always @(posedge clk0_bufg or posedge rst_tmp)
if (rst_tmp)
rst0_sync_r <= {RST_SYNC_NUM{1'b1}};
else
// logical left shift by one (pads with 0)
rst0_sync_r <= rst0_sync_r << 1;
 
// synthesis attribute max_fanout of rstdiv0_sync_r is 10
always @(posedge clkdiv0_bufg or posedge rst_tmp)
if (rst_tmp)
rstdiv0_sync_r <= {(RST_SYNC_NUM/2){1'b1}};
else
// logical left shift by one (pads with 0)
rstdiv0_sync_r <= rstdiv0_sync_r << 1;
 
// synthesis attribute max_fanout of rst90_sync_r is 10
always @(posedge clk90_bufg or posedge rst_tmp)
if (rst_tmp)
rst90_sync_r <= {RST_SYNC_NUM{1'b1}};
else
rst90_sync_r <= rst90_sync_r << 1;
 
// make sure CLK200 doesn't depend on IDELAY_CTRL_RDY, else chicken n' egg
// synthesis attribute max_fanout of rst200_sync_r is 10
always @(posedge clk200_bufg or negedge locked)
if (!locked)
rst200_sync_r <= {RST_SYNC_NUM{1'b1}};
else
rst200_sync_r <= rst200_sync_r << 1;
 
 
assign rst0 = rst0_sync_r[RST_SYNC_NUM-1];
assign rst90 = rst90_sync_r[RST_SYNC_NUM-1];
assign rst200 = rst200_sync_r[RST_SYNC_NUM-1];
assign rstdiv0 = rstdiv0_sync_r[(RST_SYNC_NUM/2)-1];
 
endmodule
/verilog/xilinx_ddr2/ddr2_usr_wr.v
0,0 → 1,338
//*****************************************************************************
// DISCLAIMER OF LIABILITY
//
// This file contains proprietary and confidential information of
// Xilinx, Inc. ("Xilinx"), that is distributed under a license
// from Xilinx, and may be used, copied and/or disclosed only
// pursuant to the terms of a valid license agreement with Xilinx.
//
// XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION
// ("MATERIALS") "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
// EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING WITHOUT
// LIMITATION, ANY WARRANTY WITH RESPECT TO NONINFRINGEMENT,
// MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE. Xilinx
// does not warrant that functions included in the Materials will
// meet the requirements of Licensee, or that the operation of the
// Materials will be uninterrupted or error-free, or that defects
// in the Materials will be corrected. Furthermore, Xilinx does
// not warrant or make any representations regarding use, or the
// results of the use, of the Materials in terms of correctness,
// accuracy, reliability or otherwise.
//
// Xilinx products are not designed or intended to be fail-safe,
// or for use in any application requiring fail-safe performance,
// such as life-support or safety devices or systems, Class III
// medical devices, nuclear facilities, applications related to
// the deployment of airbags, or any other applications that could
// lead to death, personal injury or severe property or
// environmental damage (individually and collectively, "critical
// applications"). Customer assumes the sole risk and liability
// of any use of Xilinx products in critical applications,
// subject only to applicable laws and regulations governing
// limitations on product liability.
//
// Copyright 2006, 2007 Xilinx, Inc.
// All rights reserved.
//
// This disclaimer and copyright notice must be retained as part
// of this file at all times.
//*****************************************************************************
// ____ ____
// / /\/ /
// /___/ \ / Vendor: Xilinx
// \ \ \/ Version: 3.0
// \ \ Application: MIG
// / / Filename: ddr2_usr_wr.v
// /___/ /\ Date Last Modified: $Date: 2008/12/23 14:26:01 $
// \ \ / \ Date Created: Mon Aug 28 2006
// \___\/\___\
//
//Device: Virtex-5
//Design Name: DDR/DDR2
//Purpose:
// This module instantiates the modules containing internal FIFOs
//Reference:
//Revision History:
//*****************************************************************************
 
`timescale 1ns/1ps
 
module ddr2_usr_wr #
(
// Following parameters are for 72-bit RDIMM design (for ML561 Reference
// board design). Actual values may be different. Actual parameters values
// are passed from design top module ddr2_mig module. Please refer to
// the ddr2_mig module for actual values.
parameter BANK_WIDTH = 2,
parameter COL_WIDTH = 10,
parameter CS_BITS = 0,
parameter DQ_WIDTH = 72,
parameter APPDATA_WIDTH = 144,
parameter ECC_ENABLE = 0,
parameter ROW_WIDTH = 14
)
(
input clk0,
input usr_clk, // jb
input clk90,
input rst0,
// Write data FIFO interface
input app_wdf_wren,
input [APPDATA_WIDTH-1:0] app_wdf_data,
input [(APPDATA_WIDTH/8)-1:0] app_wdf_mask_data,
input wdf_rden,
output app_wdf_afull,
output [(2*DQ_WIDTH)-1:0] wdf_data,
output [((2*DQ_WIDTH)/8)-1:0] wdf_mask_data
);
 
// determine number of FIFO72's to use based on data width
// round up to next integer value when determining WDF_FIFO_NUM
localparam WDF_FIFO_NUM = (ECC_ENABLE) ? (APPDATA_WIDTH+63)/64 :
((2*DQ_WIDTH)+63)/64;
// MASK_WIDTH = number of bytes in data bus
localparam MASK_WIDTH = DQ_WIDTH/8;
 
wire [WDF_FIFO_NUM-1:0] i_wdf_afull;
wire [DQ_WIDTH-1:0] i_wdf_data_fall_in;
wire [DQ_WIDTH-1:0] i_wdf_data_fall_out;
wire [(64*WDF_FIFO_NUM)-1:0] i_wdf_data_in;
wire [(64*WDF_FIFO_NUM)-1:0] i_wdf_data_out;
wire [DQ_WIDTH-1:0] i_wdf_data_rise_in;
wire [DQ_WIDTH-1:0] i_wdf_data_rise_out;
wire [MASK_WIDTH-1:0] i_wdf_mask_data_fall_in;
wire [MASK_WIDTH-1:0] i_wdf_mask_data_fall_out;
wire [(8*WDF_FIFO_NUM)-1:0] i_wdf_mask_data_in;
wire [(8*WDF_FIFO_NUM)-1:0] i_wdf_mask_data_out;
wire [MASK_WIDTH-1:0] i_wdf_mask_data_rise_in;
wire [MASK_WIDTH-1:0] i_wdf_mask_data_rise_out;
reg rst_r;
 
// ECC signals
wire [(2*DQ_WIDTH)-1:0] i_wdf_data_out_ecc;
wire [((2*DQ_WIDTH)/8)-1:0] i_wdf_mask_data_out_ecc;
wire [63:0] i_wdf_mask_data_out_ecc_wire;
wire [((2*DQ_WIDTH)/8)-1:0] mask_data_in_ecc;
wire [63:0] mask_data_in_ecc_wire;
 
//***************************************************************************
 
assign app_wdf_afull = i_wdf_afull[0];
 
always @(posedge clk0 )
rst_r <= rst0;
 
genvar wdf_di_i;
genvar wdf_do_i;
genvar mask_i;
genvar wdf_i;
generate
if(ECC_ENABLE) begin // ECC code
 
assign wdf_data = i_wdf_data_out_ecc;
 
// the byte 9 dm is always held to 0
assign wdf_mask_data = i_wdf_mask_data_out_ecc;
 
 
 
// generate for write data fifo .
for (wdf_i = 0; wdf_i < WDF_FIFO_NUM; wdf_i = wdf_i + 1) begin: gen_wdf
 
FIFO36_72 #
(
.ALMOST_EMPTY_OFFSET (9'h007),
.ALMOST_FULL_OFFSET (9'h00F),
.DO_REG (1), // extra CC output delay
.EN_ECC_WRITE ("TRUE"),
.EN_ECC_READ ("FALSE"),
.EN_SYN ("FALSE"),
.FIRST_WORD_FALL_THROUGH ("FALSE")
)
u_wdf_ecc
(
.ALMOSTEMPTY (),
.ALMOSTFULL (i_wdf_afull[wdf_i]),
.DBITERR (),
.DO (i_wdf_data_out_ecc[((64*(wdf_i+1))+(wdf_i *8))-1:
(64*wdf_i)+(wdf_i *8)]),
.DOP (i_wdf_data_out_ecc[(72*(wdf_i+1))-1:
(64*(wdf_i+1))+ (8*wdf_i) ]),
.ECCPARITY (),
.EMPTY (),
.FULL (),
.RDCOUNT (),
.RDERR (),
.SBITERR (),
.WRCOUNT (),
.WRERR (),
.DI (app_wdf_data[(64*(wdf_i+1))-1:
(64*wdf_i)]),
.DIP (),
.RDCLK (clk90),
.RDEN (wdf_rden),
.RST (rst_r), // or can use rst0
.WRCLK (clk0),
// .WRCLK (usr_clk), //jb
.WREN (app_wdf_wren)
);
end
 
// remapping the mask data. The mask data from user i/f does not have
// the mask for the ECC byte. Assigning 0 to the ECC mask byte.
for (mask_i = 0; mask_i < (DQ_WIDTH)/36;
mask_i = mask_i +1) begin: gen_mask
assign mask_data_in_ecc[((8*(mask_i+1))+ mask_i)-1:((8*mask_i)+mask_i)]
= app_wdf_mask_data[(8*(mask_i+1))-1:8*(mask_i)] ;
assign mask_data_in_ecc[((8*(mask_i+1))+mask_i)] = 1'd0;
end
 
// assign ecc bits to temp variables to avoid
// sim warnings. Not all the 64 bits of the fifo
// are used in ECC mode.
assign mask_data_in_ecc_wire[((2*DQ_WIDTH)/8)-1:0] = mask_data_in_ecc;
assign mask_data_in_ecc_wire[63:((2*DQ_WIDTH)/8)] =
{(64-((2*DQ_WIDTH)/8)){1'b0}};
assign i_wdf_mask_data_out_ecc =
i_wdf_mask_data_out_ecc_wire[((2*DQ_WIDTH)/8)-1:0];
 
 
FIFO36_72 #
(
.ALMOST_EMPTY_OFFSET (9'h007),
.ALMOST_FULL_OFFSET (9'h00F),
.DO_REG (1), // extra CC output delay
.EN_ECC_WRITE ("TRUE"),
.EN_ECC_READ ("FALSE"),
.EN_SYN ("FALSE"),
.FIRST_WORD_FALL_THROUGH ("FALSE")
)
u_wdf_ecc_mask
(
.ALMOSTEMPTY (),
.ALMOSTFULL (),
.DBITERR (),
.DO (i_wdf_mask_data_out_ecc_wire),
.DOP (),
.ECCPARITY (),
.EMPTY (),
.FULL (),
.RDCOUNT (),
.RDERR (),
.SBITERR (),
.WRCOUNT (),
.WRERR (),
.DI (mask_data_in_ecc_wire),
.DIP (),
.RDCLK (clk90),
.RDEN (wdf_rden),
.RST (rst_r), // or can use rst0
.WRCLK (clk0),
// .WRCLK (usr_clk), // jb
.WREN (app_wdf_wren)
);
end else begin
 
//***********************************************************************
 
// Define intermediate buses:
assign i_wdf_data_rise_in
= app_wdf_data[DQ_WIDTH-1:0];
assign i_wdf_data_fall_in
= app_wdf_data[(2*DQ_WIDTH)-1:DQ_WIDTH];
assign i_wdf_mask_data_rise_in
= app_wdf_mask_data[MASK_WIDTH-1:0];
assign i_wdf_mask_data_fall_in
= app_wdf_mask_data[(2*MASK_WIDTH)-1:MASK_WIDTH];
 
//***********************************************************************
// Write data FIFO Input:
// Arrange DQ's so that the rise data and fall data are interleaved.
// the data arrives at the input of the wdf fifo as {fall,rise}.
// It is remapped as:
// {...fall[15:8],rise[15:8],fall[7:0],rise[7:0]}
// This is done to avoid having separate fifo's for rise and fall data
// and to keep rise/fall data for the same DQ's on same FIFO
// Data masks are interleaved in a similar manner
// NOTE: Initialization data from PHY_INIT module does not need to be
// interleaved - it's already in the correct format - and the same
// initialization pattern from PHY_INIT is sent to all write FIFOs
//***********************************************************************
 
for (wdf_di_i = 0; wdf_di_i < MASK_WIDTH;
wdf_di_i = wdf_di_i + 1) begin: gen_wdf_data_in
assign i_wdf_data_in[(16*wdf_di_i)+15:(16*wdf_di_i)]
= {i_wdf_data_fall_in[(8*wdf_di_i)+7:(8*wdf_di_i)],
i_wdf_data_rise_in[(8*wdf_di_i)+7:(8*wdf_di_i)]};
assign i_wdf_mask_data_in[(2*wdf_di_i)+1:(2*wdf_di_i)]
= {i_wdf_mask_data_fall_in[wdf_di_i],
i_wdf_mask_data_rise_in[wdf_di_i]};
end
 
//***********************************************************************
// Write data FIFO Output:
// FIFO DQ and mask outputs must be untangled and put in the standard
// format of {fall,rise}. Same goes for mask output
//***********************************************************************
 
for (wdf_do_i = 0; wdf_do_i < MASK_WIDTH;
wdf_do_i = wdf_do_i + 1) begin: gen_wdf_data_out
assign i_wdf_data_rise_out[(8*wdf_do_i)+7:(8*wdf_do_i)]
= i_wdf_data_out[(16*wdf_do_i)+7:(16*wdf_do_i)];
assign i_wdf_data_fall_out[(8*wdf_do_i)+7:(8*wdf_do_i)]
= i_wdf_data_out[(16*wdf_do_i)+15:(16*wdf_do_i)+8];
assign i_wdf_mask_data_rise_out[wdf_do_i]
= i_wdf_mask_data_out[2*wdf_do_i];
assign i_wdf_mask_data_fall_out[wdf_do_i]
= i_wdf_mask_data_out[(2*wdf_do_i)+1];
end
 
assign wdf_data = {i_wdf_data_fall_out,
i_wdf_data_rise_out};
 
assign wdf_mask_data = {i_wdf_mask_data_fall_out,
i_wdf_mask_data_rise_out};
 
//***********************************************************************
 
for (wdf_i = 0; wdf_i < WDF_FIFO_NUM; wdf_i = wdf_i + 1) begin: gen_wdf
 
FIFO36_72 #
(
.ALMOST_EMPTY_OFFSET (9'h007),
.ALMOST_FULL_OFFSET (9'h00F),
.DO_REG (1), // extra CC output delay
.EN_ECC_WRITE ("FALSE"),
.EN_ECC_READ ("FALSE"),
.EN_SYN ("FALSE"),
.FIRST_WORD_FALL_THROUGH ("FALSE")
)
u_wdf
(
.ALMOSTEMPTY (),
.ALMOSTFULL (i_wdf_afull[wdf_i]),
.DBITERR (),
.DO (i_wdf_data_out[(64*(wdf_i+1))-1:64*wdf_i]),
.DOP (i_wdf_mask_data_out[(8*(wdf_i+1))-1:8*wdf_i]),
.ECCPARITY (),
.EMPTY (),
.FULL (),
.RDCOUNT (),
.RDERR (),
.SBITERR (),
.WRCOUNT (),
.WRERR (),
.DI (i_wdf_data_in[(64*(wdf_i+1))-1:64*wdf_i]),
.DIP (i_wdf_mask_data_in[(8*(wdf_i+1))-1:8*wdf_i]),
.RDCLK (clk90),
.RDEN (wdf_rden),
.RST (rst_r), // or can use rst0
.WRCLK (clk0),
// .WRCLK (usr_clk), //jb
.WREN (app_wdf_wren)
);
end
end
endgenerate
 
endmodule
/verilog/xilinx_ddr2/ddr2_phy_top.v
0,0 → 1,395
//*****************************************************************************
// DISCLAIMER OF LIABILITY
//
// This file contains proprietary and confidential information of
// Xilinx, Inc. ("Xilinx"), that is distributed under a license
// from Xilinx, and may be used, copied and/or disclosed only
// pursuant to the terms of a valid license agreement with Xilinx.
//
// XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION
// ("MATERIALS") "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
// EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING WITHOUT
// LIMITATION, ANY WARRANTY WITH RESPECT TO NONINFRINGEMENT,
// MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE. Xilinx
// does not warrant that functions included in the Materials will
// meet the requirements of Licensee, or that the operation of the
// Materials will be uninterrupted or error-free, or that defects
// in the Materials will be corrected. Furthermore, Xilinx does
// not warrant or make any representations regarding use, or the
// results of the use, of the Materials in terms of correctness,
// accuracy, reliability or otherwise.
//
// Xilinx products are not designed or intended to be fail-safe,
// or for use in any application requiring fail-safe performance,
// such as life-support or safety devices or systems, Class III
// medical devices, nuclear facilities, applications related to
// the deployment of airbags, or any other applications that could
// lead to death, personal injury or severe property or
// environmental damage (individually and collectively, "critical
// applications"). Customer assumes the sole risk and liability
// of any use of Xilinx products in critical applications,
// subject only to applicable laws and regulations governing
// limitations on product liability.
//
// Copyright 2006, 2007, 2008 Xilinx, Inc.
// All rights reserved.
//
// This disclaimer and copyright notice must be retained as part
// of this file at all times.
//*****************************************************************************
// ____ ____
// / /\/ /
// /___/ \ / Vendor: Xilinx
// \ \ \/ Version: 3.0
// \ \ Application: MIG
// / / Filename: ddr2_phy_top.v
// /___/ /\ Date Last Modified: $Date: 2009/02/03 18:50:12 $
// \ \ / \ Date Created: Wed Aug 16 2006
// \___\/\___\
//
//Device: Virtex-5
//Design Name: DDR2
//Purpose:
// Top-level for memory physical layer (PHY) interface
//Reference:
//Revision History:
// Rev 1.1 - Parameter USE_DM_PORT added. PK. 6/25/08
// Rev 1.2 - Parameter HIGH_PERFORMANCE_MODE added. PK. 7/10/08
// Rev 1.3 - Parameter CS_BITS added. PK. 10/8/08
// Rev 1.4 - Parameter IODELAY_GRP added. PK. 11/27/08
//*****************************************************************************
 
`timescale 1ns/1ps
 
(* X_CORE_INFO = "mig_v3_0_ddr2_sdram_v5, Coregen 11.1" , CORE_GENERATION_INFO = "ddr2_sdram_v5,mig_v3_0,{component_name=ddr2_phy_top, BANK_WIDTH=2, CKE_WIDTH=1, CLK_WIDTH=2, COL_WIDTH=10, CS_NUM=1, CS_WIDTH=1, DM_WIDTH=8, DQ_WIDTH=64, DQ_PER_DQS=8, DQS_WIDTH=8, ODT_WIDTH=1, ROW_WIDTH=13, ADDITIVE_LAT=0, BURST_LEN=4, BURST_TYPE=0, CAS_LAT=4, ECC_ENABLE=0, MULTI_BANK_EN=1, TWO_T_TIME_EN=1, ODT_TYPE=1, REDUCE_DRV=0, REG_ENABLE=0, TREFI_NS=7800, TRAS=40000, TRCD=15000, TRFC=105000, TRP=15000, TRTP=7500, TWR=15000, TWTR=7500, DDR2_CLK_PERIOD=3750, RST_ACT_LOW=1}" *)
module ddr2_phy_top #
(
// Following parameters are for 72-bit RDIMM design (for ML561 Reference
// board design). Actual values may be different. Actual parameters values
// are passed from design top module ddr2_mig module. Please refer to
// the ddr2_mig module for actual values.
parameter BANK_WIDTH = 2,
parameter CLK_WIDTH = 1,
parameter CKE_WIDTH = 1,
parameter COL_WIDTH = 10,
parameter CS_BITS = 0,
parameter CS_NUM = 1,
parameter CS_WIDTH = 1,
parameter USE_DM_PORT = 1,
parameter DM_WIDTH = 9,
parameter DQ_WIDTH = 72,
parameter DQ_BITS = 7,
parameter DQ_PER_DQS = 8,
parameter DQS_WIDTH = 9,
parameter DQS_BITS = 4,
parameter HIGH_PERFORMANCE_MODE = "TRUE",
parameter IODELAY_GRP = "IODELAY_MIG",
parameter ODT_WIDTH = 1,
parameter ROW_WIDTH = 14,
parameter ADDITIVE_LAT = 0,
parameter TWO_T_TIME_EN = 0,
parameter BURST_LEN = 4,
parameter BURST_TYPE = 0,
parameter CAS_LAT = 5,
parameter TWR = 15000,
parameter ECC_ENABLE = 0,
parameter ODT_TYPE = 1,
parameter DDR_TYPE = 1,
parameter REDUCE_DRV = 0,
parameter REG_ENABLE = 1,
parameter CLK_PERIOD = 3000,
parameter SIM_ONLY = 0,
parameter DEBUG_EN = 0,
parameter FPGA_SPEED_GRADE = 2
)
(
input clk0,
input clk90,
input clkdiv0,
input rst0,
input rst90,
input rstdiv0,
input ctrl_wren,
input [ROW_WIDTH-1:0] ctrl_addr,
input [BANK_WIDTH-1:0] ctrl_ba,
input ctrl_ras_n,
input ctrl_cas_n,
input ctrl_we_n,
input [CS_NUM-1:0] ctrl_cs_n,
input ctrl_rden,
input ctrl_ref_flag,
input [(2*DQ_WIDTH)-1:0] wdf_data,
input [(2*DQ_WIDTH/8)-1:0] wdf_mask_data,
output wdf_rden,
output phy_init_done,
output [DQS_WIDTH-1:0] phy_calib_rden,
output [DQS_WIDTH-1:0] phy_calib_rden_sel,
output [DQ_WIDTH-1:0] rd_data_rise,
output [DQ_WIDTH-1:0] rd_data_fall,
output [CLK_WIDTH-1:0] ddr_ck,
output [CLK_WIDTH-1:0] ddr_ck_n,
output [ROW_WIDTH-1:0] ddr_addr,
output [BANK_WIDTH-1:0] ddr_ba,
output ddr_ras_n,
output ddr_cas_n,
output ddr_we_n,
output [CS_WIDTH-1:0] ddr_cs_n,
output [CKE_WIDTH-1:0] ddr_cke,
output [ODT_WIDTH-1:0] ddr_odt,
output [DM_WIDTH-1:0] ddr_dm,
inout [DQS_WIDTH-1:0] ddr_dqs,
inout [DQS_WIDTH-1:0] ddr_dqs_n,
inout [DQ_WIDTH-1:0] ddr_dq,
// Debug signals (optional use)
input dbg_idel_up_all,
input dbg_idel_down_all,
input dbg_idel_up_dq,
input dbg_idel_down_dq,
input dbg_idel_up_dqs,
input dbg_idel_down_dqs,
input dbg_idel_up_gate,
input dbg_idel_down_gate,
input [DQ_BITS-1:0] dbg_sel_idel_dq,
input dbg_sel_all_idel_dq,
input [DQS_BITS:0] dbg_sel_idel_dqs,
input dbg_sel_all_idel_dqs,
input [DQS_BITS:0] dbg_sel_idel_gate,
input dbg_sel_all_idel_gate,
output [3:0] dbg_calib_done,
output [3:0] dbg_calib_err,
output [(6*DQ_WIDTH)-1:0] dbg_calib_dq_tap_cnt,
output [(6*DQS_WIDTH)-1:0] dbg_calib_dqs_tap_cnt,
output [(6*DQS_WIDTH)-1:0] dbg_calib_gate_tap_cnt,
output [DQS_WIDTH-1:0] dbg_calib_rd_data_sel,
output [(5*DQS_WIDTH)-1:0] dbg_calib_rden_dly,
output [(5*DQS_WIDTH)-1:0] dbg_calib_gate_dly
);
 
wire [3:0] calib_done;
wire calib_ref_done;
wire calib_ref_req;
wire [3:0] calib_start;
wire dm_ce;
wire [1:0] dq_oe_n;
wire dqs_oe_n;
wire dqs_rst_n;
wire [(DQ_WIDTH/8)-1:0] mask_data_fall;
wire [(DQ_WIDTH/8)-1:0] mask_data_rise;
wire [CS_NUM-1:0] odt;
wire [ROW_WIDTH-1:0] phy_init_addr;
wire [BANK_WIDTH-1:0] phy_init_ba;
wire phy_init_cas_n;
wire [CKE_WIDTH-1:0] phy_init_cke;
wire [CS_NUM-1:0] phy_init_cs_n;
wire phy_init_data_sel;
wire phy_init_ras_n;
wire phy_init_rden;
wire phy_init_we_n;
wire phy_init_wren;
wire [DQ_WIDTH-1:0] wr_data_fall;
wire [DQ_WIDTH-1:0] wr_data_rise;
 
//***************************************************************************
 
ddr2_phy_write #
(
.DQ_WIDTH (DQ_WIDTH),
.CS_NUM (CS_NUM),
.ADDITIVE_LAT (ADDITIVE_LAT),
.CAS_LAT (CAS_LAT),
.ECC_ENABLE (ECC_ENABLE),
.ODT_TYPE (ODT_TYPE),
.REG_ENABLE (REG_ENABLE),
.DDR_TYPE (DDR_TYPE)
)
u_phy_write
(
.clk0 (clk0),
.clk90 (clk90),
.rst90 (rst90),
.wdf_data (wdf_data),
.wdf_mask_data (wdf_mask_data),
.ctrl_wren (ctrl_wren),
.phy_init_wren (phy_init_wren),
.phy_init_data_sel (phy_init_data_sel),
.dm_ce (dm_ce),
.dq_oe_n (dq_oe_n),
.dqs_oe_n (dqs_oe_n),
.dqs_rst_n (dqs_rst_n),
.wdf_rden (wdf_rden),
.odt (odt),
.wr_data_rise (wr_data_rise),
.wr_data_fall (wr_data_fall),
.mask_data_rise (mask_data_rise),
.mask_data_fall (mask_data_fall)
);
 
ddr2_phy_io #
(
.CLK_WIDTH (CLK_WIDTH),
.USE_DM_PORT (USE_DM_PORT),
.DM_WIDTH (DM_WIDTH),
.DQ_WIDTH (DQ_WIDTH),
.DQ_BITS (DQ_BITS),
.DQ_PER_DQS (DQ_PER_DQS),
.DQS_BITS (DQS_BITS),
.DQS_WIDTH (DQS_WIDTH),
.HIGH_PERFORMANCE_MODE (HIGH_PERFORMANCE_MODE),
.IODELAY_GRP (IODELAY_GRP),
.ODT_WIDTH (ODT_WIDTH),
.ADDITIVE_LAT (ADDITIVE_LAT),
.CAS_LAT (CAS_LAT),
.REG_ENABLE (REG_ENABLE),
.CLK_PERIOD (CLK_PERIOD),
.DDR_TYPE (DDR_TYPE),
.SIM_ONLY (SIM_ONLY),
.DEBUG_EN (DEBUG_EN),
.FPGA_SPEED_GRADE (FPGA_SPEED_GRADE)
)
u_phy_io
(
.clk0 (clk0),
.clk90 (clk90),
.clkdiv0 (clkdiv0),
.rst0 (rst0),
.rst90 (rst90),
.rstdiv0 (rstdiv0),
.dm_ce (dm_ce),
.dq_oe_n (dq_oe_n),
.dqs_oe_n (dqs_oe_n),
.dqs_rst_n (dqs_rst_n),
.calib_start (calib_start),
.ctrl_rden (ctrl_rden),
.phy_init_rden (phy_init_rden),
.calib_ref_done (calib_ref_done),
.calib_done (calib_done),
.calib_ref_req (calib_ref_req),
.calib_rden (phy_calib_rden),
.calib_rden_sel (phy_calib_rden_sel),
.wr_data_rise (wr_data_rise),
.wr_data_fall (wr_data_fall),
.mask_data_rise (mask_data_rise),
.mask_data_fall (mask_data_fall),
.rd_data_rise (rd_data_rise),
.rd_data_fall (rd_data_fall),
.ddr_ck (ddr_ck),
.ddr_ck_n (ddr_ck_n),
.ddr_dm (ddr_dm),
.ddr_dqs (ddr_dqs),
.ddr_dqs_n (ddr_dqs_n),
.ddr_dq (ddr_dq),
.dbg_idel_up_all (dbg_idel_up_all),
.dbg_idel_down_all (dbg_idel_down_all),
.dbg_idel_up_dq (dbg_idel_up_dq),
.dbg_idel_down_dq (dbg_idel_down_dq),
.dbg_idel_up_dqs (dbg_idel_up_dqs),
.dbg_idel_down_dqs (dbg_idel_down_dqs),
.dbg_idel_up_gate (dbg_idel_up_gate),
.dbg_idel_down_gate (dbg_idel_down_gate),
.dbg_sel_idel_dq (dbg_sel_idel_dq),
.dbg_sel_all_idel_dq (dbg_sel_all_idel_dq),
.dbg_sel_idel_dqs (dbg_sel_idel_dqs),
.dbg_sel_all_idel_dqs (dbg_sel_all_idel_dqs),
.dbg_sel_idel_gate (dbg_sel_idel_gate),
.dbg_sel_all_idel_gate (dbg_sel_all_idel_gate),
.dbg_calib_done (dbg_calib_done),
.dbg_calib_err (dbg_calib_err),
.dbg_calib_dq_tap_cnt (dbg_calib_dq_tap_cnt),
.dbg_calib_dqs_tap_cnt (dbg_calib_dqs_tap_cnt),
.dbg_calib_gate_tap_cnt (dbg_calib_gate_tap_cnt),
.dbg_calib_rd_data_sel (dbg_calib_rd_data_sel),
.dbg_calib_rden_dly (dbg_calib_rden_dly),
.dbg_calib_gate_dly (dbg_calib_gate_dly)
);
 
ddr2_phy_ctl_io #
(
.BANK_WIDTH (BANK_WIDTH),
.CKE_WIDTH (CKE_WIDTH),
.COL_WIDTH (COL_WIDTH),
.CS_NUM (CS_NUM),
.CS_WIDTH (CS_WIDTH),
.TWO_T_TIME_EN (TWO_T_TIME_EN),
.ODT_WIDTH (ODT_WIDTH),
.ROW_WIDTH (ROW_WIDTH),
.DDR_TYPE (DDR_TYPE)
)
u_phy_ctl_io
(
.clk0 (clk0),
.clk90 (clk90),
.rst0 (rst0),
.rst90 (rst90),
.ctrl_addr (ctrl_addr),
.ctrl_ba (ctrl_ba),
.ctrl_ras_n (ctrl_ras_n),
.ctrl_cas_n (ctrl_cas_n),
.ctrl_we_n (ctrl_we_n),
.ctrl_cs_n (ctrl_cs_n),
.phy_init_addr (phy_init_addr),
.phy_init_ba (phy_init_ba),
.phy_init_ras_n (phy_init_ras_n),
.phy_init_cas_n (phy_init_cas_n),
.phy_init_we_n (phy_init_we_n),
.phy_init_cs_n (phy_init_cs_n),
.phy_init_cke (phy_init_cke),
.phy_init_data_sel (phy_init_data_sel),
.odt (odt),
.ddr_addr (ddr_addr),
.ddr_ba (ddr_ba),
.ddr_ras_n (ddr_ras_n),
.ddr_cas_n (ddr_cas_n),
.ddr_we_n (ddr_we_n),
.ddr_cke (ddr_cke),
.ddr_cs_n (ddr_cs_n),
.ddr_odt (ddr_odt)
);
 
ddr2_phy_init #
(
.BANK_WIDTH (BANK_WIDTH),
.CKE_WIDTH (CKE_WIDTH),
.COL_WIDTH (COL_WIDTH),
.CS_BITS (CS_BITS),
.CS_NUM (CS_NUM),
.DQ_WIDTH (DQ_WIDTH),
.ODT_WIDTH (ODT_WIDTH),
.ROW_WIDTH (ROW_WIDTH),
.ADDITIVE_LAT (ADDITIVE_LAT),
.BURST_LEN (BURST_LEN),
.BURST_TYPE (BURST_TYPE),
.TWO_T_TIME_EN(TWO_T_TIME_EN),
.CAS_LAT (CAS_LAT),
.ODT_TYPE (ODT_TYPE),
.REDUCE_DRV (REDUCE_DRV),
.REG_ENABLE (REG_ENABLE),
.TWR (TWR),
.CLK_PERIOD (CLK_PERIOD),
.DDR_TYPE (DDR_TYPE),
.SIM_ONLY (SIM_ONLY)
)
u_phy_init
(
.clk0 (clk0),
.clkdiv0 (clkdiv0),
.rst0 (rst0),
.rstdiv0 (rstdiv0),
.calib_done (calib_done),
.ctrl_ref_flag (ctrl_ref_flag),
.calib_ref_req (calib_ref_req),
.calib_start (calib_start),
.calib_ref_done (calib_ref_done),
.phy_init_wren (phy_init_wren),
.phy_init_rden (phy_init_rden),
.phy_init_addr (phy_init_addr),
.phy_init_ba (phy_init_ba),
.phy_init_ras_n (phy_init_ras_n),
.phy_init_cas_n (phy_init_cas_n),
.phy_init_we_n (phy_init_we_n),
.phy_init_cs_n (phy_init_cs_n),
.phy_init_cke (phy_init_cke),
.phy_init_done (phy_init_done),
.phy_init_data_sel (phy_init_data_sel)
);
 
endmodule
/verilog/xilinx_ddr2/ddr2_phy_init.v
0,0 → 1,1189
//*****************************************************************************
// DISCLAIMER OF LIABILITY
//
// This file contains proprietary and confidential information of
// Xilinx, Inc. ("Xilinx"), that is distributed under a license
// from Xilinx, and may be used, copied and/or disclosed only
// pursuant to the terms of a valid license agreement with Xilinx.
//
// XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION
// ("MATERIALS") "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
// EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING WITHOUT
// LIMITATION, ANY WARRANTY WITH RESPECT TO NONINFRINGEMENT,
// MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE. Xilinx
// does not warrant that functions included in the Materials will
// meet the requirements of Licensee, or that the operation of the
// Materials will be uninterrupted or error-free, or that defects
// in the Materials will be corrected. Furthermore, Xilinx does
// not warrant or make any representations regarding use, or the
// results of the use, of the Materials in terms of correctness,
// accuracy, reliability or otherwise.
//
// Xilinx products are not designed or intended to be fail-safe,
// or for use in any application requiring fail-safe performance,
// such as life-support or safety devices or systems, Class III
// medical devices, nuclear facilities, applications related to
// the deployment of airbags, or any other applications that could
// lead to death, personal injury or severe property or
// environmental damage (individually and collectively, "critical
// applications"). Customer assumes the sole risk and liability
// of any use of Xilinx products in critical applications,
// subject only to applicable laws and regulations governing
// limitations on product liability.
//
// Copyright 2006, 2007, 2008 Xilinx, Inc.
// All rights reserved.
//
// This disclaimer and copyright notice must be retained as part
// of this file at all times.
//*****************************************************************************
// ____ ____
// / /\/ /
// /___/ \ / Vendor: Xilinx
// \ \ \/ Version: 3.0
// \ \ Application: MIG
// / / Filename: ddr2_phy_init.v
// /___/ /\ Date Last Modified: $Date: 2008/12/23 14:26:00 $
// \ \ / \ Date Created: Thu Aug 24 2006
// \___\/\___\
//
//Device: Virtex-5
//Design Name: DDR2
//Purpose:
//Reference:
// This module is the intialization control logic of the memory interface.
// All commands are issued from here acoording to the burst, CAS Latency and
// the user commands.
//Revision History:
// Rev 1.1 - Localparam WR_RECOVERY added and mapped to
// load mode register. PK. 14/7/08
// Rev 1.2 - To issue an Auto Refresh command to each chip during various
// calibration stages logic modified. PK. 08/10/08
//*****************************************************************************
 
`timescale 1ns/1ps
 
module ddr2_phy_init #
(
// Following parameters are for 72-bit RDIMM design (for ML561 Reference
// board design). Actual values may be different. Actual parameters values
// are passed from design top module ddr2_mig module. Please refer to
// the ddr2_mig module for actual values.
parameter BANK_WIDTH = 2,
parameter CKE_WIDTH = 1,
parameter COL_WIDTH = 10,
parameter CS_BITS = 0,
parameter CS_NUM = 1,
parameter DQ_WIDTH = 72,
parameter ODT_WIDTH = 1,
parameter ROW_WIDTH = 14,
parameter ADDITIVE_LAT = 0,
parameter BURST_LEN = 4,
parameter TWO_T_TIME_EN = 0,
parameter BURST_TYPE = 0,
parameter CAS_LAT = 5,
parameter ODT_TYPE = 1,
parameter REDUCE_DRV = 0,
parameter REG_ENABLE = 1,
parameter TWR = 15000,
parameter CLK_PERIOD = 3000,
parameter DDR_TYPE = 1,
parameter SIM_ONLY = 0
)
(
input clk0,
input clkdiv0,
input rst0,
input rstdiv0,
input [3:0] calib_done,
input ctrl_ref_flag,
input calib_ref_req,
output reg [3:0] calib_start,
output reg calib_ref_done,
output reg phy_init_wren,
output reg phy_init_rden,
output [ROW_WIDTH-1:0] phy_init_addr,
output [BANK_WIDTH-1:0] phy_init_ba,
output phy_init_ras_n,
output phy_init_cas_n,
output phy_init_we_n,
output [CS_NUM-1:0] phy_init_cs_n,
output [CKE_WIDTH-1:0] phy_init_cke,
output reg phy_init_done,
output phy_init_data_sel
);
 
// time to wait between consecutive commands in PHY_INIT - this is a
// generic number, and must be large enough to account for worst case
// timing parameter (tRFC - refresh-to-active) across all memory speed
// grades and operating frequencies. Expressed in CLKDIV clock cycles.
localparam CNTNEXT_CMD = 7'b1111111;
// time to wait between read and read or precharge for stage 3 & 4
// the larger CNTNEXT_CMD can also be used, use smaller number to
// speed up calibration - avoid tRAS violation, and speeds up simulation
localparam CNTNEXT_RD = 4'b1111;
 
// Write recovery (WR) time - is defined by
// tWR (in nanoseconds) by tCK (in nanoseconds) and rounding up a
// noninteger value to the next integer
localparam integer WR_RECOVERY = ((TWR + CLK_PERIOD) - 1)/CLK_PERIOD;
localparam CS_BITS_FIX = (CS_BITS == 0) ? 1 : CS_BITS;
 
localparam INIT_CAL1_READ = 5'h00;
localparam INIT_CAL2_READ = 5'h01;
localparam INIT_CAL3_READ = 5'h02;
localparam INIT_CAL4_READ = 5'h03;
localparam INIT_CAL1_WRITE = 5'h04;
localparam INIT_CAL2_WRITE = 5'h05;
localparam INIT_CAL3_WRITE = 5'h06;
localparam INIT_DUMMY_ACTIVE_WAIT = 5'h07;
localparam INIT_PRECHARGE = 5'h08;
localparam INIT_LOAD_MODE = 5'h09;
localparam INIT_AUTO_REFRESH = 5'h0A;
localparam INIT_IDLE = 5'h0B;
localparam INIT_CNT_200 = 5'h0C;
localparam INIT_CNT_200_WAIT = 5'h0D;
localparam INIT_PRECHARGE_WAIT = 5'h0E;
localparam INIT_MODE_REGISTER_WAIT = 5'h0F;
localparam INIT_AUTO_REFRESH_WAIT = 5'h10;
localparam INIT_DEEP_MEMORY_ST = 5'h11;
localparam INIT_DUMMY_ACTIVE = 5'h12;
localparam INIT_CAL1_WRITE_READ = 5'h13;
localparam INIT_CAL1_READ_WAIT = 5'h14;
localparam INIT_CAL2_WRITE_READ = 5'h15;
localparam INIT_CAL2_READ_WAIT = 5'h16;
localparam INIT_CAL3_WRITE_READ = 5'h17;
localparam INIT_CAL3_READ_WAIT = 5'h18;
localparam INIT_CAL4_READ_WAIT = 5'h19;
localparam INIT_CALIB_REF = 5'h1A;
localparam INIT_ZQCL = 5'h1B;
localparam INIT_WAIT_DLLK_ZQINIT = 5'h1C;
 
localparam INIT_CNTR_INIT = 4'h0;
localparam INIT_CNTR_PRECH_1 = 4'h1;
localparam INIT_CNTR_EMR2_INIT = 4'h2;
localparam INIT_CNTR_EMR3_INIT = 4'h3;
localparam INIT_CNTR_EMR_EN_DLL = 4'h4;
localparam INIT_CNTR_MR_RST_DLL = 4'h5;
localparam INIT_CNTR_CNT_200_WAIT = 4'h6;
localparam INIT_CNTR_PRECH_2 = 4'h7;
localparam INIT_CNTR_AR_1 = 4'h8;
localparam INIT_CNTR_AR_2 = 4'h9;
localparam INIT_CNTR_MR_ACT_DLL = 4'hA;
localparam INIT_CNTR_EMR_DEF_OCD = 4'hB;
localparam INIT_CNTR_EMR_EXIT_OCD = 4'hC;
localparam INIT_CNTR_DEEP_MEM = 4'hD;
localparam INIT_CNTR_PRECH_3 = 4'hE;
localparam INIT_CNTR_DONE = 4'hF;
 
localparam DDR1 = 0;
localparam DDR2 = 1;
localparam DDR3 = 2;
 
reg [CS_BITS_FIX :0] auto_cnt_r;
reg [1:0] burst_addr_r;
reg [1:0] burst_cnt_r;
wire [1:0] burst_val;
wire cal_read;
wire cal_write;
wire cal_write_read;
reg cal1_started_r;
reg cal2_started_r;
reg cal4_started_r;
reg [3:0] calib_done_r;
reg calib_ref_req_posedge;
reg calib_ref_req_r;
reg [15:0] calib_start_shift0_r;
reg [15:0] calib_start_shift1_r;
reg [15:0] calib_start_shift2_r;
reg [15:0] calib_start_shift3_r;
reg [1:0] chip_cnt_r;
reg [4:0] cke_200us_cnt_r;
reg cke_200us_cnt_en_r;
reg [7:0] cnt_200_cycle_r;
reg cnt_200_cycle_done_r;
reg [6:0] cnt_cmd_r;
reg cnt_cmd_ok_r;
reg [3:0] cnt_rd_r;
reg cnt_rd_ok_r;
reg ctrl_ref_flag_r;
reg done_200us_r;
reg [ROW_WIDTH-1:0] ddr_addr_r;
reg [ROW_WIDTH-1:0] ddr_addr_r1;
reg [BANK_WIDTH-1:0] ddr_ba_r;
reg [BANK_WIDTH-1:0] ddr_ba_r1;
reg ddr_cas_n_r;
reg ddr_cas_n_r1;
reg [CKE_WIDTH-1:0] ddr_cke_r;
reg [CS_NUM-1:0] ddr_cs_n_r;
reg [CS_NUM-1:0] ddr_cs_n_r1;
reg [CS_NUM-1:0] ddr_cs_disable_r;
reg ddr_ras_n_r;
reg ddr_ras_n_r1;
reg ddr_we_n_r;
reg ddr_we_n_r1;
wire [15:0] ext_mode_reg;
reg [3:0] init_cnt_r;
reg init_done_r;
reg [4:0] init_next_state;
reg [4:0] init_state_r;
reg [4:0] init_state_r1;
reg [4:0] init_state_r1_2t;
reg [4:0] init_state_r2;
wire [15:0] load_mode_reg;
wire [15:0] load_mode_reg0;
wire [15:0] load_mode_reg1;
wire [15:0] load_mode_reg2;
wire [15:0] load_mode_reg3;
reg phy_init_done_r;
reg phy_init_done_r1;
reg phy_init_done_r2;
reg phy_init_done_r3;
reg refresh_req;
wire [3:0] start_cal;
 
//***************************************************************************
 
//*****************************************************************
// DDR1 and DDR2 Load mode register
// Mode Register (MR):
// [15:14] - unused - 00
// [13] - reserved - 0
// [12] - Power-down mode - 0 (normal)
// [11:9] - write recovery - for Auto Precharge (tWR/tCK)
// [8] - DLL reset - 0 or 1
// [7] - Test Mode - 0 (normal)
// [6:4] - CAS latency - CAS_LAT
// [3] - Burst Type - BURST_TYPE
// [2:0] - Burst Length - BURST_LEN
//*****************************************************************
 
generate
if (DDR_TYPE == DDR2) begin: gen_load_mode_reg_ddr2
assign load_mode_reg[2:0] = (BURST_LEN == 8) ? 3'b011 :
((BURST_LEN == 4) ? 3'b010 : 3'b111);
assign load_mode_reg[3] = BURST_TYPE;
assign load_mode_reg[6:4] = (CAS_LAT == 3) ? 3'b011 :
((CAS_LAT == 4) ? 3'b100 :
((CAS_LAT == 5) ? 3'b101 : 3'b111));
assign load_mode_reg[7] = 1'b0;
assign load_mode_reg[8] = 1'b0; // init value only (DLL not reset)
assign load_mode_reg[11:9] = (WR_RECOVERY == 6) ? 3'b101 :
((WR_RECOVERY == 5) ? 3'b100 :
((WR_RECOVERY == 4) ? 3'b011 :
((WR_RECOVERY == 3) ? 3'b010 :
3'b001)));
assign load_mode_reg[15:12] = 4'b000;
end else if (DDR_TYPE == DDR1)begin: gen_load_mode_reg_ddr1
assign load_mode_reg[2:0] = (BURST_LEN == 8) ? 3'b011 :
((BURST_LEN == 4) ? 3'b010 :
((BURST_LEN == 2) ? 3'b001 : 3'b111));
assign load_mode_reg[3] = BURST_TYPE;
assign load_mode_reg[6:4] = (CAS_LAT == 2) ? 3'b010 :
((CAS_LAT == 3) ? 3'b011 :
((CAS_LAT == 25) ? 3'b110 : 3'b111));
assign load_mode_reg[12:7] = 6'b000000; // init value only
assign load_mode_reg[15:13] = 3'b000;
end
endgenerate
 
//*****************************************************************
// DDR1 and DDR2 ext mode register
// Extended Mode Register (MR):
// [15:14] - unused - 00
// [13] - reserved - 0
// [12] - output enable - 0 (enabled)
// [11] - RDQS enable - 0 (disabled)
// [10] - DQS# enable - 0 (enabled)
// [9:7] - OCD Program - 111 or 000 (first 111, then 000 during init)
// [6] - RTT[1] - RTT[1:0] = 0(no ODT), 1(75), 2(150), 3(50)
// [5:3] - Additive CAS - ADDITIVE_CAS
// [2] - RTT[0]
// [1] - Output drive - REDUCE_DRV (= 0(full), = 1 (reduced)
// [0] - DLL enable - 0 (normal)
//*****************************************************************
 
generate
if (DDR_TYPE == DDR2) begin: gen_ext_mode_reg_ddr2
assign ext_mode_reg[0] = 1'b0;
assign ext_mode_reg[1] = REDUCE_DRV;
assign ext_mode_reg[2] = ((ODT_TYPE == 1) || (ODT_TYPE == 3)) ?
1'b1 : 1'b0;
assign ext_mode_reg[5:3] = (ADDITIVE_LAT == 0) ? 3'b000 :
((ADDITIVE_LAT == 1) ? 3'b001 :
((ADDITIVE_LAT == 2) ? 3'b010 :
((ADDITIVE_LAT == 3) ? 3'b011 :
((ADDITIVE_LAT == 4) ? 3'b100 :
3'b111))));
assign ext_mode_reg[6] = ((ODT_TYPE == 2) || (ODT_TYPE == 3)) ?
1'b1 : 1'b0;
assign ext_mode_reg[9:7] = 3'b000;
assign ext_mode_reg[10] = 1'b0;
assign ext_mode_reg[15:10] = 6'b000000;
end else if (DDR_TYPE == DDR1)begin: gen_ext_mode_reg_ddr1
assign ext_mode_reg[0] = 1'b0;
assign ext_mode_reg[1] = REDUCE_DRV;
assign ext_mode_reg[12:2] = 11'b00000000000;
assign ext_mode_reg[15:13] = 3'b000;
end
endgenerate
 
//*****************************************************************
// DDR3 Load mode reg0
// Mode Register (MR0):
// [15:13] - unused - 000
// [12] - Precharge Power-down DLL usage - 0 (DLL frozen, slow-exit),
// 1 (DLL maintained)
// [11:9] - write recovery for Auto Precharge (tWR/tCK = 6)
// [8] - DLL reset - 0 or 1
// [7] - Test Mode - 0 (normal)
// [6:4],[2] - CAS latency - CAS_LAT
// [3] - Burst Type - BURST_TYPE
// [1:0] - Burst Length - BURST_LEN
//*****************************************************************
 
generate
if (DDR_TYPE == DDR3) begin: gen_load_mode_reg0_ddr3
assign load_mode_reg0[1:0] = (BURST_LEN == 8) ? 2'b00 :
((BURST_LEN == 4) ? 2'b10 : 2'b11);
// Part of CAS latency. This bit is '0' for all CAS latencies
assign load_mode_reg0[2] = 1'b0;
assign load_mode_reg0[3] = BURST_TYPE;
assign load_mode_reg0[6:4] = (CAS_LAT == 5) ? 3'b001 :
(CAS_LAT == 6) ? 3'b010 : 3'b111;
assign load_mode_reg0[7] = 1'b0;
// init value only (DLL reset)
assign load_mode_reg0[8] = 1'b1;
assign load_mode_reg0[11:9] = 3'b010;
// Precharge Power-Down DLL 'slow-exit'
assign load_mode_reg0[12] = 1'b0;
assign load_mode_reg0[15:13] = 3'b000;
end
endgenerate
 
//*****************************************************************
// DDR3 Load mode reg1
// Mode Register (MR1):
// [15:13] - unused - 00
// [12] - output enable - 0 (enabled for DQ, DQS, DQS#)
// [11] - TDQS enable - 0 (TDQS disabled and DM enabled)
// [10] - reserved - 0 (must be '0')
// [9] - RTT[2] - 0
// [8] - reserved - 0 (must be '0')
// [7] - write leveling - 0 (disabled), 1 (enabled)
// [6] - RTT[1] - RTT[1:0] = 0(no ODT), 1(75), 2(150), 3(50)
// [5] - Output driver impedance[1] - 0 (RZQ/6 and RZQ/7)
// [4:3] - Additive CAS - ADDITIVE_CAS
// [2] - RTT[0]
// [1] - Output driver impedance[0] - 0(RZQ/6), or 1 (RZQ/7)
// [0] - DLL enable - 0 (normal)
//*****************************************************************
 
generate
if (DDR_TYPE == DDR3) begin: gen_ext_mode_reg1_ddr3
// DLL enabled during Imitialization
assign load_mode_reg1[0] = 1'b0;
// RZQ/6
assign load_mode_reg1[1] = REDUCE_DRV;
assign load_mode_reg1[2] = ((ODT_TYPE == 1) || (ODT_TYPE == 3)) ?
1'b1 : 1'b0;
assign load_mode_reg1[4:3] = (ADDITIVE_LAT == 0) ? 2'b00 :
((ADDITIVE_LAT == 1) ? 2'b01 :
((ADDITIVE_LAT == 2) ? 2'b10 :
3'b111));
// RZQ/6
assign load_mode_reg1[5] = 1'b0;
assign load_mode_reg1[6] = ((ODT_TYPE == 2) || (ODT_TYPE == 3)) ?
1'b1 : 1'b0;
// Make zero WRITE_LEVEL
assign load_mode_reg1[7] = 0;
assign load_mode_reg1[8] = 1'b0;
assign load_mode_reg1[9] = 1'b0;
assign load_mode_reg1[10] = 1'b0;
assign load_mode_reg1[15:11] = 5'b00000;
end
endgenerate
 
//*****************************************************************
// DDR3 Load mode reg2
// Mode Register (MR2):
// [15:11] - unused - 00
// [10:9] - RTT_WR - 00 (Dynamic ODT off)
// [8] - reserved - 0 (must be '0')
// [7] - self-refresh temperature range -
// 0 (normal), 1 (extended)
// [6] - Auto Self-Refresh - 0 (manual), 1(auto)
// [5:3] - CAS Write Latency (CWL) -
// 000 (5 for 400 MHz device),
// 001 (6 for 400 MHz to 533 MHz devices),
// 010 (7 for 533 MHz to 667 MHz devices),
// 011 (8 for 667 MHz to 800 MHz)
// [2:0] - Partial Array Self-Refresh (Optional) -
// 000 (full array)
//*****************************************************************
 
generate
if (DDR_TYPE == DDR3) begin: gen_ext_mode_reg2_ddr3
assign load_mode_reg2[2:0] = 3'b000;
assign load_mode_reg2[5:3] = (CAS_LAT == 5) ? 3'b000 :
(CAS_LAT == 6) ? 3'b001 : 3'b111;
assign load_mode_reg2[6] = 1'b0; // Manual Self-Refresh
assign load_mode_reg2[7] = 1'b0;
assign load_mode_reg2[8] = 1'b0;
assign load_mode_reg2[10:9] = 2'b00;
assign load_mode_reg2[15:11] = 5'b00000;
end
endgenerate
 
//*****************************************************************
// DDR3 Load mode reg3
// Mode Register (MR3):
// [15:3] - unused - All zeros
// [2] - MPR Operation - 0(normal operation), 1(data flow from MPR)
// [1:0] - MPR location - 00 (Predefined pattern)
//*****************************************************************
 
generate
if (DDR_TYPE == DDR3)begin: gen_ext_mode_reg3_ddr3
assign load_mode_reg3[1:0] = 2'b00;
assign load_mode_reg3[2] = 1'b0;
assign load_mode_reg3[15:3] = 13'b0000000000000;
end
endgenerate
 
//***************************************************************************
// Logic for calibration start, and for auto-refresh during cal request
// CALIB_REF_REQ is used by calibration logic to request auto-refresh
// durign calibration (used to avoid tRAS violation is certain calibration
// stages take a long time). Once the auto-refresh is complete and cal can
// be resumed, CALIB_REF_DONE is asserted by PHY_INIT.
//***************************************************************************
 
// generate pulse for each of calibration start controls
assign start_cal[0] = ((init_state_r1 == INIT_CAL1_READ) &&
(init_state_r2 != INIT_CAL1_READ));
assign start_cal[1] = ((init_state_r1 == INIT_CAL2_READ) &&
(init_state_r2 != INIT_CAL2_READ));
assign start_cal[2] = ((init_state_r1 == INIT_CAL3_READ) &&
(init_state_r2 == INIT_CAL3_WRITE_READ));
assign start_cal[3] = ((init_state_r1 == INIT_CAL4_READ) &&
(init_state_r2 == INIT_DUMMY_ACTIVE_WAIT));
 
// Generate positive-edge triggered, latched signal to force initialization
// to pause calibration, and to issue auto-refresh. Clear flag as soon as
// refresh initiated
always @(posedge clkdiv0)
if (rstdiv0) begin
calib_ref_req_r <= 1'b0;
calib_ref_req_posedge <= 1'b0;
refresh_req <= 1'b0;
end else begin
calib_ref_req_r <= calib_ref_req;
calib_ref_req_posedge <= calib_ref_req & ~calib_ref_req_r;
if (init_state_r1 == INIT_AUTO_REFRESH)
refresh_req <= 1'b0;
else if (calib_ref_req_posedge)
refresh_req <= 1'b1;
end
 
// flag to tell cal1 calibration was started.
// This flag is used for cal1 auto refreshes
// some of these bits may not be needed - only needed for those stages that
// need refreshes within the stage (i.e. very long stages)
always @(posedge clkdiv0)
if (rstdiv0) begin
cal1_started_r <= 1'b0;
cal2_started_r <= 1'b0;
cal4_started_r <= 1'b0;
end else begin
if (calib_start[0])
cal1_started_r <= 1'b1;
if (calib_start[1])
cal2_started_r <= 1'b1;
if (calib_start[3])
cal4_started_r <= 1'b1;
end
 
// Delay start of each calibration by 16 clock cycles to
// ensure that when calibration logic begins, that read data is already
// appearing on the bus. Don't really need it, it's more for simulation
// purposes. Each circuit should synthesize using an SRL16.
// In first stage of calibration periodic auto refreshes
// will be issued to meet memory timing. calib_start_shift0_r[15] will be
// asserted more than once.calib_start[0] is anded with cal1_started_r so
// that it is asserted only once. cal1_refresh_done is anded with
// cal1_started_r so that it is asserted after the auto refreshes.
always @(posedge clkdiv0) begin
calib_start_shift0_r <= {calib_start_shift0_r[14:0], start_cal[0]};
calib_start_shift1_r <= {calib_start_shift1_r[14:0], start_cal[1]};
calib_start_shift2_r <= {calib_start_shift2_r[14:0], start_cal[2]};
calib_start_shift3_r <= {calib_start_shift3_r[14:0], start_cal[3]};
calib_start[0] <= calib_start_shift0_r[15] & ~cal1_started_r;
calib_start[1] <= calib_start_shift1_r[15] & ~cal2_started_r;
calib_start[2] <= calib_start_shift2_r[15];
calib_start[3] <= calib_start_shift3_r[15] & ~cal4_started_r;
calib_ref_done <= calib_start_shift0_r[15] |
calib_start_shift1_r[15] |
calib_start_shift3_r[15];
end
 
// generate delay for various states that require it (no maximum delay
// requirement, make sure that terminal count is large enough to cover
// all cases)
always @(posedge clkdiv0) begin
case (init_state_r)
INIT_PRECHARGE_WAIT,
INIT_MODE_REGISTER_WAIT,
INIT_AUTO_REFRESH_WAIT,
INIT_DUMMY_ACTIVE_WAIT,
INIT_CAL1_WRITE_READ,
INIT_CAL1_READ_WAIT,
INIT_CAL2_WRITE_READ,
INIT_CAL2_READ_WAIT,
INIT_CAL3_WRITE_READ:
cnt_cmd_r <= cnt_cmd_r + 1;
default:
cnt_cmd_r <= 7'b0000000;
endcase
end
 
// assert when count reaches the value
always @(posedge clkdiv0) begin
if(cnt_cmd_r == CNTNEXT_CMD)
cnt_cmd_ok_r <= 1'b1;
else
cnt_cmd_ok_r <= 1'b0;
end
 
always @(posedge clkdiv0) begin
case (init_state_r)
INIT_CAL3_READ_WAIT,
INIT_CAL4_READ_WAIT:
cnt_rd_r <= cnt_rd_r + 1;
default:
cnt_rd_r <= 4'b0000;
endcase
end
 
always @(posedge clkdiv0) begin
if(cnt_rd_r == CNTNEXT_RD)
cnt_rd_ok_r <= 1'b1;
else
cnt_rd_ok_r <= 1'b0;
end
 
//***************************************************************************
// Initial delay after power-on
//***************************************************************************
 
// register the refresh flag from the controller.
// The refresh flag is in full frequency domain - so a pulsed version must
// be generated for half freq domain using 2 consecutive full clk cycles
// The registered version is used for the 200us counter
always @(posedge clk0)
ctrl_ref_flag_r <= ctrl_ref_flag;
always @(posedge clkdiv0)
cke_200us_cnt_en_r <= ctrl_ref_flag || ctrl_ref_flag_r;
 
// 200us counter for cke
always @(posedge clkdiv0)
if (rstdiv0) begin
// skip power-up count if only simulating
if (SIM_ONLY)
cke_200us_cnt_r <= 5'b00001;
else
cke_200us_cnt_r <= 5'd27;
end else if (cke_200us_cnt_en_r)
cke_200us_cnt_r <= cke_200us_cnt_r - 1;
 
always @(posedge clkdiv0)
if (rstdiv0)
done_200us_r <= 1'b0;
else if (!done_200us_r)
done_200us_r <= (cke_200us_cnt_r == 5'b00000);
 
// 200 clocks counter - count value : h'64 required for initialization
// Counts 100 divided by two clocks
always @(posedge clkdiv0)
if (rstdiv0 || (init_state_r == INIT_CNT_200))
cnt_200_cycle_r <= 8'h64;
else if (init_state_r == INIT_ZQCL) // ddr3
cnt_200_cycle_r <= 8'hC8;
else if (cnt_200_cycle_r != 8'h00)
cnt_200_cycle_r <= cnt_200_cycle_r - 1;
 
always @(posedge clkdiv0)
if (rstdiv0 || (init_state_r == INIT_CNT_200)
|| (init_state_r == INIT_ZQCL))
cnt_200_cycle_done_r <= 1'b0;
else if (cnt_200_cycle_r == 8'h00)
cnt_200_cycle_done_r <= 1'b1;
 
//*****************************************************************
// handle deep memory configuration:
// During initialization: Repeat initialization sequence once for each
// chip select. Note that we could perform initalization for all chip
// selects simulataneously. Probably fine - any potential SI issues with
// auto refreshing all chip selects at once?
// Once initialization complete, assert only CS[1] for calibration.
//*****************************************************************
 
always @(posedge clkdiv0)
if (rstdiv0) begin
chip_cnt_r <= 2'b00;
end else if (init_state_r == INIT_DEEP_MEMORY_ST) begin
if (chip_cnt_r != CS_NUM)
chip_cnt_r <= chip_cnt_r + 1;
else
chip_cnt_r <= 2'b00;
// MIG 2.4: Modified to issue an Auto Refresh commmand
// to each chip select during various calibration stages
end else if (init_state_r == INIT_PRECHARGE && init_done_r) begin
chip_cnt_r <= 2'b00;
end else if (init_state_r1 == INIT_AUTO_REFRESH && init_done_r) begin
if (chip_cnt_r < (CS_NUM-1))
chip_cnt_r <= chip_cnt_r + 1;
end
 
// keep track of which chip selects got auto-refreshed (avoid auto-refreshing
// all CS's at once to avoid current spike)
always @(posedge clkdiv0)begin
if (rstdiv0 || init_state_r == INIT_PRECHARGE)
auto_cnt_r <= 'd0;
else if (init_state_r == INIT_AUTO_REFRESH && init_done_r) begin
if (auto_cnt_r < CS_NUM)
auto_cnt_r <= auto_cnt_r + 1;
end
end
 
always @(posedge clkdiv0)
if (rstdiv0) begin
ddr_cs_n_r <= {CS_NUM{1'b1}};
end else begin
ddr_cs_n_r <= {CS_NUM{1'b1}};
if ((init_state_r == INIT_DUMMY_ACTIVE) ||
((init_state_r == INIT_PRECHARGE) && (~init_done_r))||
(init_state_r == INIT_LOAD_MODE) ||
(init_state_r == INIT_AUTO_REFRESH) ||
(init_state_r == INIT_ZQCL ) ||
(((init_state_r == INIT_CAL1_READ) ||
(init_state_r == INIT_CAL2_READ) ||
(init_state_r == INIT_CAL3_READ) ||
(init_state_r == INIT_CAL4_READ) ||
(init_state_r == INIT_CAL1_WRITE) ||
(init_state_r == INIT_CAL2_WRITE) ||
(init_state_r == INIT_CAL3_WRITE)) && (burst_cnt_r == 2'b00)))
ddr_cs_n_r[chip_cnt_r] <= 1'b0;
else if (init_state_r == INIT_PRECHARGE)
ddr_cs_n_r <= {CS_NUM{1'b0}};
else
ddr_cs_n_r[chip_cnt_r] <= 1'b1;
end
 
//***************************************************************************
// Write/read burst logic
//***************************************************************************
 
assign cal_write = ((init_state_r == INIT_CAL1_WRITE) ||
(init_state_r == INIT_CAL2_WRITE) ||
(init_state_r == INIT_CAL3_WRITE));
assign cal_read = ((init_state_r == INIT_CAL1_READ) ||
(init_state_r == INIT_CAL2_READ) ||
(init_state_r == INIT_CAL3_READ) ||
(init_state_r == INIT_CAL4_READ));
assign cal_write_read = ((init_state_r == INIT_CAL1_READ) ||
(init_state_r == INIT_CAL2_READ) ||
(init_state_r == INIT_CAL3_READ) ||
(init_state_r == INIT_CAL4_READ) ||
(init_state_r == INIT_CAL1_WRITE) ||
(init_state_r == INIT_CAL2_WRITE) ||
(init_state_r == INIT_CAL3_WRITE));
 
assign burst_val = (BURST_LEN == 4) ? 2'b00 :
(BURST_LEN == 8) ? 2'b01 : 2'b00;
 
// keep track of current address - need this if burst length < 8 for
// stage 2-4 calibration writes and reads. Make sure value always gets
// initialized to 0 before we enter write/read state. This is used to
// keep track of when another burst must be issued
always @(posedge clkdiv0)
if (cal_write_read)
burst_addr_r <= burst_addr_r + 2;
else
burst_addr_r <= 2'b00;
 
// write/read burst count
always @(posedge clkdiv0)
if (cal_write_read)
if (burst_cnt_r == 2'b00)
burst_cnt_r <= burst_val;
else // SHOULD THIS BE -2 CHECK THIS LOGIC
burst_cnt_r <= burst_cnt_r - 1;
else
burst_cnt_r <= 2'b00;
 
// indicate when a write is occurring
always @(posedge clkdiv0)
// MIG 2.1: Remove (burst_addr_r<4) term - not used
// phy_init_wren <= cal_write && (burst_addr_r < 3'd4);
phy_init_wren <= cal_write;
 
// used for read enable calibration, pulse to indicate when read issued
always @(posedge clkdiv0)
// MIG 2.1: Remove (burst_addr_r<4) term - not used
// phy_init_rden <= cal_read && (burst_addr_r < 3'd4);
phy_init_rden <= cal_read;
 
//***************************************************************************
// Initialization state machine
//***************************************************************************
 
always @(posedge clkdiv0)
// every time we need to initialize another rank of memory, need to
// reset init count, and repeat the entire initialization (but not
// calibration) sequence
if (rstdiv0 || (init_state_r == INIT_DEEP_MEMORY_ST))
init_cnt_r <= INIT_CNTR_INIT;
else if ((DDR_TYPE == DDR1) && (init_state_r == INIT_PRECHARGE) &&
(init_cnt_r == INIT_CNTR_PRECH_1))
// skip EMR(2) and EMR(3) register loads
init_cnt_r <= INIT_CNTR_EMR_EN_DLL;
else if ((DDR_TYPE == DDR1) && (init_state_r == INIT_LOAD_MODE) &&
(init_cnt_r == INIT_CNTR_MR_ACT_DLL))
// skip OCD calibration for DDR1
init_cnt_r <= INIT_CNTR_DEEP_MEM;
else if ((DDR_TYPE == DDR3) && (init_state_r == INIT_ZQCL))
// skip states for DDR3
init_cnt_r <= INIT_CNTR_DEEP_MEM;
else if ((init_state_r == INIT_LOAD_MODE) ||
((init_state_r == INIT_PRECHARGE)
&& (init_state_r1 != INIT_CALIB_REF))||
((init_state_r == INIT_AUTO_REFRESH)
&& (~init_done_r))||
(init_state_r == INIT_CNT_200))
init_cnt_r <= init_cnt_r + 1;
 
always @(posedge clkdiv0) begin
if ((init_state_r == INIT_IDLE) && (init_cnt_r == INIT_CNTR_DONE)) begin
phy_init_done_r <= 1'b1;
end else
phy_init_done_r <= 1'b0;
end
 
// phy_init_done to the controller and the user interface.
// It is delayed by four clocks to account for the
// multi cycle path constraint to the (phy_init_data_sel)
// to the phy layer.
always @(posedge clkdiv0)begin
phy_init_done_r1 <= phy_init_done_r;
phy_init_done_r2 <= phy_init_done_r1;
phy_init_done_r3 <= phy_init_done_r2;
phy_init_done <= phy_init_done_r3;
end
 
// Instantiate primitive to allow this flop to be attached to multicycle
// path constraint in UCF. This signal goes to PHY_WRITE and PHY_CTL_IO
// datapath logic only. Because it is a multi-cycle path, it can be
// clocked by either CLKDIV0 or CLK0.
FDRSE u_ff_phy_init_data_sel
(
.Q (phy_init_data_sel),
.C (clkdiv0),
.CE (1'b1),
.D (phy_init_done_r1),
.R (1'b0),
.S (1'b0)
) /* synthesis syn_preserve=1 */
/* synthesis syn_replicate = 0 */;
 
//synthesis translate_off
always @(posedge calib_done[0])
$display ("First Stage Calibration completed at time %t", $time);
 
always @(posedge calib_done[1])
$display ("Second Stage Calibration completed at time %t", $time);
 
always @(posedge calib_done[2]) begin
$display ("Third Stage Calibration completed at time %t", $time);
end
 
always @(posedge calib_done[3]) begin
$display ("Fourth Stage Calibration completed at time %t", $time);
$display ("Calibration completed at time %t", $time);
end
//synthesis translate_on
 
always @(posedge clkdiv0) begin
if ((init_cnt_r >= INIT_CNTR_DEEP_MEM))begin
init_done_r <= 1'b1;
end else
init_done_r <= 1'b0;
end
 
//*****************************************************************
 
always @(posedge clkdiv0)
if (rstdiv0) begin
init_state_r <= INIT_IDLE;
init_state_r1 <= INIT_IDLE;
init_state_r2 <= INIT_IDLE;
calib_done_r <= 4'b0000;
end else begin
init_state_r <= init_next_state;
init_state_r1 <= init_state_r;
init_state_r2 <= init_state_r1;
calib_done_r <= calib_done; // register for timing
end
 
always @(*) begin
init_next_state = init_state_r;
(* full_case, parallel_case *) case (init_state_r)
INIT_IDLE: begin
if (done_200us_r) begin
(* parallel_case *) case (init_cnt_r)
INIT_CNTR_INIT:
init_next_state = INIT_CNT_200;
INIT_CNTR_PRECH_1:
init_next_state = INIT_PRECHARGE;
INIT_CNTR_EMR2_INIT:
init_next_state = INIT_LOAD_MODE; // EMR(2)
INIT_CNTR_EMR3_INIT:
init_next_state = INIT_LOAD_MODE; // EMR(3);
INIT_CNTR_EMR_EN_DLL:
init_next_state = INIT_LOAD_MODE; // EMR, enable DLL
INIT_CNTR_MR_RST_DLL:
init_next_state = INIT_LOAD_MODE; // MR, reset DLL
INIT_CNTR_CNT_200_WAIT:begin
if(DDR_TYPE == DDR3)
init_next_state = INIT_ZQCL; // DDR3
else
// Wait 200cc after reset DLL
init_next_state = INIT_CNT_200;
end
INIT_CNTR_PRECH_2:
init_next_state = INIT_PRECHARGE;
INIT_CNTR_AR_1:
init_next_state = INIT_AUTO_REFRESH;
INIT_CNTR_AR_2:
init_next_state = INIT_AUTO_REFRESH;
INIT_CNTR_MR_ACT_DLL:
init_next_state = INIT_LOAD_MODE; // MR, unreset DLL
INIT_CNTR_EMR_DEF_OCD:
init_next_state = INIT_LOAD_MODE; // EMR, OCD default
INIT_CNTR_EMR_EXIT_OCD:
init_next_state = INIT_LOAD_MODE; // EMR, enable OCD exit
INIT_CNTR_DEEP_MEM: begin
if ((chip_cnt_r < CS_NUM-1))
init_next_state = INIT_DEEP_MEMORY_ST;
else if (cnt_200_cycle_done_r)
init_next_state = INIT_DUMMY_ACTIVE;
else
init_next_state = INIT_IDLE;
end
INIT_CNTR_PRECH_3:
init_next_state = INIT_PRECHARGE;
INIT_CNTR_DONE:
init_next_state = INIT_IDLE;
default :
init_next_state = INIT_IDLE;
endcase
end
end
INIT_CNT_200:
init_next_state = INIT_CNT_200_WAIT;
INIT_CNT_200_WAIT:
if (cnt_200_cycle_done_r)
init_next_state = INIT_IDLE;
INIT_PRECHARGE:
init_next_state = INIT_PRECHARGE_WAIT;
INIT_PRECHARGE_WAIT:
if (cnt_cmd_ok_r)begin
if (init_done_r && (!(&calib_done_r)))
init_next_state = INIT_AUTO_REFRESH;
else
init_next_state = INIT_IDLE;
end
INIT_ZQCL:
init_next_state = INIT_WAIT_DLLK_ZQINIT;
INIT_WAIT_DLLK_ZQINIT:
if (cnt_200_cycle_done_r)
init_next_state = INIT_IDLE;
INIT_LOAD_MODE:
init_next_state = INIT_MODE_REGISTER_WAIT;
INIT_MODE_REGISTER_WAIT:
if (cnt_cmd_ok_r)
init_next_state = INIT_IDLE;
INIT_AUTO_REFRESH:
init_next_state = INIT_AUTO_REFRESH_WAIT;
INIT_AUTO_REFRESH_WAIT:
// MIG 2.4: Modified to issue an Auto Refresh commmand
// to each chip select during various calibration stages
if (auto_cnt_r < CS_NUM && init_done_r) begin
if (cnt_cmd_ok_r)
init_next_state = INIT_AUTO_REFRESH;
end else if (cnt_cmd_ok_r)begin
if(init_done_r)
init_next_state = INIT_DUMMY_ACTIVE;
else
init_next_state = INIT_IDLE;
end
INIT_DEEP_MEMORY_ST:
init_next_state = INIT_IDLE;
// single row activate. All subsequent calibration writes and
// read will take place in this row
INIT_DUMMY_ACTIVE:
init_next_state = INIT_DUMMY_ACTIVE_WAIT;
INIT_DUMMY_ACTIVE_WAIT:
if (cnt_cmd_ok_r)begin
if (~calib_done_r[0]) begin
// if returning to stg1 after refresh, don't need to write
if (cal1_started_r)
init_next_state = INIT_CAL1_READ;
// if first entering stg1, need to write training pattern
else
init_next_state = INIT_CAL1_WRITE;
end else if (~calib_done[1]) begin
if (cal2_started_r)
init_next_state = INIT_CAL2_READ;
else
init_next_state = INIT_CAL2_WRITE;
end else if (~calib_done_r[2])
init_next_state = INIT_CAL3_WRITE;
else
init_next_state = INIT_CAL4_READ;
end
// Stage 1 calibration (write and continuous read)
INIT_CAL1_WRITE:
if (burst_addr_r == 2'b10)
init_next_state = INIT_CAL1_WRITE_READ;
INIT_CAL1_WRITE_READ:
if (cnt_cmd_ok_r)
init_next_state = INIT_CAL1_READ;
INIT_CAL1_READ:
// Stage 1 requires inter-stage auto-refresh
if (calib_done_r[0] || refresh_req)
init_next_state = INIT_CAL1_READ_WAIT;
INIT_CAL1_READ_WAIT:
if (cnt_cmd_ok_r)
init_next_state = INIT_CALIB_REF;
// Stage 2 calibration (write and continuous read)
INIT_CAL2_WRITE:
if (burst_addr_r == 2'b10)
init_next_state = INIT_CAL2_WRITE_READ;
INIT_CAL2_WRITE_READ:
if (cnt_cmd_ok_r)
init_next_state = INIT_CAL2_READ;
INIT_CAL2_READ:
// Stage 2 requires inter-stage auto-refresh
if (calib_done_r[1] || refresh_req)
init_next_state = INIT_CAL2_READ_WAIT;
INIT_CAL2_READ_WAIT:
if(cnt_cmd_ok_r)
init_next_state = INIT_CALIB_REF;
// Stage 3 calibration (write and continuous read)
INIT_CAL3_WRITE:
if (burst_addr_r == 2'b10)
init_next_state = INIT_CAL3_WRITE_READ;
INIT_CAL3_WRITE_READ:
if (cnt_cmd_ok_r)
init_next_state = INIT_CAL3_READ;
INIT_CAL3_READ:
if (burst_addr_r == 2'b10)
init_next_state = INIT_CAL3_READ_WAIT;
INIT_CAL3_READ_WAIT: begin
if (cnt_rd_ok_r)
if (calib_done_r[2]) begin
init_next_state = INIT_CALIB_REF;
end else
init_next_state = INIT_CAL3_READ;
end
// Stage 4 calibration (continuous read only, same pattern as stage 3)
// only used if DQS_GATE supported
INIT_CAL4_READ:
if (burst_addr_r == 2'b10)
init_next_state = INIT_CAL4_READ_WAIT;
INIT_CAL4_READ_WAIT: begin
if (cnt_rd_ok_r)
// Stage 4 requires inter-stage auto-refresh
if (calib_done_r[3] || refresh_req)
init_next_state = INIT_PRECHARGE;
else
init_next_state = INIT_CAL4_READ;
end
INIT_CALIB_REF:
init_next_state = INIT_PRECHARGE;
endcase
end
 
//***************************************************************************
// Memory control/address
//***************************************************************************
 
always @(posedge clkdiv0)
if ((init_state_r == INIT_DUMMY_ACTIVE) ||
(init_state_r == INIT_PRECHARGE) ||
(init_state_r == INIT_LOAD_MODE) ||
(init_state_r == INIT_AUTO_REFRESH)) begin
ddr_ras_n_r <= 1'b0;
end else begin
ddr_ras_n_r <= 1'b1;
end
 
always @(posedge clkdiv0)
if ((init_state_r == INIT_LOAD_MODE) ||
(init_state_r == INIT_AUTO_REFRESH) ||
(cal_write_read && (burst_cnt_r == 2'b00))) begin
ddr_cas_n_r <= 1'b0;
end else begin
ddr_cas_n_r <= 1'b1;
end
 
always @(posedge clkdiv0)
if ((init_state_r == INIT_LOAD_MODE) ||
(init_state_r == INIT_PRECHARGE) ||
(init_state_r == INIT_ZQCL) ||
(cal_write && (burst_cnt_r == 2'b00)))begin
ddr_we_n_r <= 1'b0;
end else begin
ddr_we_n_r <= 1'b1;
end
 
//*****************************************************************
// memory address during init
//*****************************************************************
 
always @(posedge clkdiv0) begin
if ((init_state_r == INIT_PRECHARGE)
|| (init_state_r == INIT_ZQCL))begin
// Precharge all - set A10 = 1
ddr_addr_r <= {ROW_WIDTH{1'b0}};
ddr_addr_r[10] <= 1'b1;
ddr_ba_r <= {BANK_WIDTH{1'b0}};
end else if (init_state_r == INIT_LOAD_MODE) begin
ddr_ba_r <= {BANK_WIDTH{1'b0}};
ddr_addr_r <= {ROW_WIDTH{1'b0}};
case (init_cnt_r)
// EMR (2)
INIT_CNTR_EMR2_INIT: begin
ddr_ba_r[1:0] <= 2'b10;
ddr_addr_r <= {ROW_WIDTH{1'b0}};
end
// EMR (3)
INIT_CNTR_EMR3_INIT: begin
ddr_ba_r[1:0] <= 2'b11;
if(DDR_TYPE == DDR3)
ddr_addr_r <= load_mode_reg3[ROW_WIDTH-1:0];
else
ddr_addr_r <= {ROW_WIDTH{1'b0}};
end
// EMR write - A0 = 0 for DLL enable
INIT_CNTR_EMR_EN_DLL: begin
ddr_ba_r[1:0] <= 2'b01;
if(DDR_TYPE == DDR3)
ddr_addr_r <= load_mode_reg1[ROW_WIDTH-1:0];
else
ddr_addr_r <= ext_mode_reg[ROW_WIDTH-1:0];
end
// MR write, reset DLL (A8=1)
INIT_CNTR_MR_RST_DLL: begin
if(DDR_TYPE == DDR3)
ddr_addr_r <= load_mode_reg0[ROW_WIDTH-1:0];
else
ddr_addr_r <= load_mode_reg[ROW_WIDTH-1:0];
ddr_ba_r[1:0] <= 2'b00;
ddr_addr_r[8] <= 1'b1;
end
// MR write, unreset DLL (A8=0)
INIT_CNTR_MR_ACT_DLL: begin
ddr_ba_r[1:0] <= 2'b00;
ddr_addr_r <= load_mode_reg[ROW_WIDTH-1:0];
end
// EMR write, OCD default state
INIT_CNTR_EMR_DEF_OCD: begin
ddr_ba_r[1:0] <= 2'b01;
ddr_addr_r <= ext_mode_reg[ROW_WIDTH-1:0];
ddr_addr_r[9:7] <= 3'b111;
end
// EMR write - OCD exit
INIT_CNTR_EMR_EXIT_OCD: begin
ddr_ba_r[1:0] <= 2'b01;
ddr_addr_r <= ext_mode_reg[ROW_WIDTH-1:0];
end
default: begin
ddr_ba_r <= {BANK_WIDTH{1'bx}};
ddr_addr_r <= {ROW_WIDTH{1'bx}};
end
endcase
end else if (cal_write_read) begin
// when writing or reading for Stages 2-4, since training pattern is
// either 4 (stage 2) or 8 (stage 3-4) long, if BURST LEN < 8, then
// need to issue multiple bursts to read entire training pattern
ddr_addr_r[ROW_WIDTH-1:3] <= {ROW_WIDTH-4{1'b0}};
ddr_addr_r[2:0] <= {burst_addr_r, 1'b0};
ddr_ba_r <= {BANK_WIDTH-1{1'b0}};
end else if (init_state_r == INIT_DUMMY_ACTIVE) begin
// all calibration writing read takes place in row 0x0 only
ddr_ba_r <= {BANK_WIDTH{1'b0}};
ddr_addr_r <= {ROW_WIDTH{1'b0}};
end else begin
// otherwise, cry me a river
ddr_ba_r <= {BANK_WIDTH{1'bx}};
ddr_addr_r <= {ROW_WIDTH{1'bx}};
end
end
 
// Keep CKE asserted after initial power-on delay
always @(posedge clkdiv0)
ddr_cke_r <= {CKE_WIDTH{done_200us_r}};
 
// register commands to memory. Two clock cycle delay from state -> output
always @(posedge clk0) begin
ddr_addr_r1 <= ddr_addr_r;
ddr_ba_r1 <= ddr_ba_r;
ddr_cas_n_r1 <= ddr_cas_n_r;
ddr_ras_n_r1 <= ddr_ras_n_r;
ddr_we_n_r1 <= ddr_we_n_r;
ddr_cs_n_r1 <= ddr_cs_n_r;
end // always @ (posedge clk0)
 
always @(posedge clk0)
init_state_r1_2t <= init_state_r1;
 
// logic to toggle chip select. The chip_select is
// clocked of clkdiv0 and will be asserted for
// two clock cycles.
always @(posedge clk0) begin
if(rst0)
ddr_cs_disable_r <= {CS_NUM{1'b0}};
else begin
if(| ddr_cs_disable_r)
ddr_cs_disable_r <= {CS_NUM{1'b0}};
else begin
if (TWO_T_TIME_EN) begin
if (init_state_r1_2t == INIT_PRECHARGE && init_done_r)
ddr_cs_disable_r <= 'd3;
else
ddr_cs_disable_r[chip_cnt_r] <= ~ddr_cs_n_r1[chip_cnt_r];
end
else begin
if (init_state_r1 == INIT_PRECHARGE && init_done_r)
ddr_cs_disable_r <= 'd3;
else
ddr_cs_disable_r[chip_cnt_r] <= ~ddr_cs_n_r[chip_cnt_r];
end
end
end
end
 
 
assign phy_init_addr = ddr_addr_r;
assign phy_init_ba = ddr_ba_r;
assign phy_init_cas_n = ddr_cas_n_r;
assign phy_init_cke = ddr_cke_r;
assign phy_init_ras_n = ddr_ras_n_r;
assign phy_init_we_n = ddr_we_n_r;
assign phy_init_cs_n = (TWO_T_TIME_EN) ?
ddr_cs_n_r1 | ddr_cs_disable_r
: ddr_cs_n_r| ddr_cs_disable_r;
 
endmodule
/verilog/xilinx_ddr2/ddr2_phy_io.v
0,0 → 1,353
//*****************************************************************************
// DISCLAIMER OF LIABILITY
//
// This file contains proprietary and confidential information of
// Xilinx, Inc. ("Xilinx"), that is distributed under a license
// from Xilinx, and may be used, copied and/or disclosed only
// pursuant to the terms of a valid license agreement with Xilinx.
//
// XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION
// ("MATERIALS") "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
// EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING WITHOUT
// LIMITATION, ANY WARRANTY WITH RESPECT TO NONINFRINGEMENT,
// MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE. Xilinx
// does not warrant that functions included in the Materials will
// meet the requirements of Licensee, or that the operation of the
// Materials will be uninterrupted or error-free, or that defects
// in the Materials will be corrected. Furthermore, Xilinx does
// not warrant or make any representations regarding use, or the
// results of the use, of the Materials in terms of correctness,
// accuracy, reliability or otherwise.
//
// Xilinx products are not designed or intended to be fail-safe,
// or for use in any application requiring fail-safe performance,
// such as life-support or safety devices or systems, Class III
// medical devices, nuclear facilities, applications related to
// the deployment of airbags, or any other applications that could
// lead to death, personal injury or severe property or
// environmental damage (individually and collectively, "critical
// applications"). Customer assumes the sole risk and liability
// of any use of Xilinx products in critical applications,
// subject only to applicable laws and regulations governing
// limitations on product liability.
//
// Copyright 2006, 2007, 2008 Xilinx, Inc.
// All rights reserved.
//
// This disclaimer and copyright notice must be retained as part
// of this file at all times.
//*****************************************************************************
// ____ ____
// / /\/ /
// /___/ \ / Vendor: Xilinx
// \ \ \/ Version: 3.0
// \ \ Application: MIG
// / / Filename: ddr2_phy_io.v
// /___/ /\ Date Last Modified: $Date: 2009/01/15 14:22:14 $
// \ \ / \ Date Created: Wed Aug 16 2006
// \___\/\___\
//
//Device: Virtex-5
//Design Name: DDR2
//Purpose:
// This module instantiates calibration logic, data, data strobe and the
// data mask iobs.
//Reference:
//Revision History:
// Rev 1.1 - DM_IOB instance made based on USE_DM_PORT value . PK. 25/6/08
// Rev 1.2 - Parameter HIGH_PERFORMANCE_MODE added. PK. 7/10/08
// Rev 1.3 - Parameter IODELAY_GRP added. PK. 11/27/08
//*****************************************************************************
 
`timescale 1ns/1ps
 
module ddr2_phy_io #
(
// Following parameters are for 72-bit RDIMM design (for ML561 Reference
// board design). Actual values may be different. Actual parameters values
// are passed from design top module ddr2_mig module. Please refer to
// the ddr2_mig module for actual values.
parameter CLK_WIDTH = 1,
parameter USE_DM_PORT = 1,
parameter DM_WIDTH = 9,
parameter DQ_WIDTH = 72,
parameter DQ_BITS = 7,
parameter DQ_PER_DQS = 8,
parameter DQS_BITS = 4,
parameter DQS_WIDTH = 9,
parameter HIGH_PERFORMANCE_MODE = "TRUE",
parameter IODELAY_GRP = "IODELAY_MIG",
parameter ODT_WIDTH = 1,
parameter ADDITIVE_LAT = 0,
parameter CAS_LAT = 5,
parameter REG_ENABLE = 1,
parameter CLK_PERIOD = 3000,
parameter DDR_TYPE = 1,
parameter SIM_ONLY = 0,
parameter DEBUG_EN = 0,
parameter FPGA_SPEED_GRADE = 2
)
(
input clk0,
input clk90,
input clkdiv0,
input rst0,
input rst90,
input rstdiv0,
input dm_ce,
input [1:0] dq_oe_n,
input dqs_oe_n,
input dqs_rst_n,
input [3:0] calib_start,
input ctrl_rden,
input phy_init_rden,
input calib_ref_done,
output [3:0] calib_done,
output calib_ref_req,
output [DQS_WIDTH-1:0] calib_rden,
output [DQS_WIDTH-1:0] calib_rden_sel,
input [DQ_WIDTH-1:0] wr_data_rise,
input [DQ_WIDTH-1:0] wr_data_fall,
input [(DQ_WIDTH/8)-1:0] mask_data_rise,
input [(DQ_WIDTH/8)-1:0] mask_data_fall,
output [(DQ_WIDTH)-1:0] rd_data_rise,
output [(DQ_WIDTH)-1:0] rd_data_fall,
output [CLK_WIDTH-1:0] ddr_ck,
output [CLK_WIDTH-1:0] ddr_ck_n,
output [DM_WIDTH-1:0] ddr_dm,
inout [DQS_WIDTH-1:0] ddr_dqs,
inout [DQS_WIDTH-1:0] ddr_dqs_n,
inout [DQ_WIDTH-1:0] ddr_dq,
// Debug signals (optional use)
input dbg_idel_up_all,
input dbg_idel_down_all,
input dbg_idel_up_dq,
input dbg_idel_down_dq,
input dbg_idel_up_dqs,
input dbg_idel_down_dqs,
input dbg_idel_up_gate,
input dbg_idel_down_gate,
input [DQ_BITS-1:0] dbg_sel_idel_dq,
input dbg_sel_all_idel_dq,
input [DQS_BITS:0] dbg_sel_idel_dqs,
input dbg_sel_all_idel_dqs,
input [DQS_BITS:0] dbg_sel_idel_gate,
input dbg_sel_all_idel_gate,
output [3:0] dbg_calib_done,
output [3:0] dbg_calib_err,
output [(6*DQ_WIDTH)-1:0] dbg_calib_dq_tap_cnt,
output [(6*DQS_WIDTH)-1:0] dbg_calib_dqs_tap_cnt,
output [(6*DQS_WIDTH)-1:0] dbg_calib_gate_tap_cnt,
output [DQS_WIDTH-1:0] dbg_calib_rd_data_sel,
output [(5*DQS_WIDTH)-1:0] dbg_calib_rden_dly,
output [(5*DQS_WIDTH)-1:0] dbg_calib_gate_dly
);
 
// ratio of # of physical DM outputs to bytes in data bus
// may be different - e.g. if using x4 components
localparam DM_TO_BYTE_RATIO = DM_WIDTH / (DQ_WIDTH/8);
 
wire [CLK_WIDTH-1:0] ddr_ck_q;
wire [DQS_WIDTH-1:0] delayed_dqs;
wire [DQ_WIDTH-1:0] dlyce_dq;
wire [DQS_WIDTH-1:0] dlyce_dqs;
wire [DQS_WIDTH-1:0] dlyce_gate;
wire [DQ_WIDTH-1:0] dlyinc_dq;
wire [DQS_WIDTH-1:0] dlyinc_dqs;
wire [DQS_WIDTH-1:0] dlyinc_gate;
wire dlyrst_dq;
wire dlyrst_dqs;
wire [DQS_WIDTH-1:0] dlyrst_gate;
wire [DQS_WIDTH-1:0] dq_ce;
(* KEEP = "TRUE" *) wire [DQS_WIDTH-1:0] en_dqs /* synthesis syn_keep = 1 */;
wire [DQS_WIDTH-1:0] rd_data_sel;
 
//***************************************************************************
 
ddr2_phy_calib #
(
.DQ_WIDTH (DQ_WIDTH),
.DQ_BITS (DQ_BITS),
.DQ_PER_DQS (DQ_PER_DQS),
.DQS_BITS (DQS_BITS),
.DQS_WIDTH (DQS_WIDTH),
.ADDITIVE_LAT (ADDITIVE_LAT),
.CAS_LAT (CAS_LAT),
.REG_ENABLE (REG_ENABLE),
.CLK_PERIOD (CLK_PERIOD),
.SIM_ONLY (SIM_ONLY),
.DEBUG_EN (DEBUG_EN)
)
u_phy_calib
(
.clk (clk0),
.clkdiv (clkdiv0),
.rstdiv (rstdiv0),
.calib_start (calib_start),
.ctrl_rden (ctrl_rden),
.phy_init_rden (phy_init_rden),
.rd_data_rise (rd_data_rise),
.rd_data_fall (rd_data_fall),
.calib_ref_done (calib_ref_done),
.calib_done (calib_done),
.calib_ref_req (calib_ref_req),
.calib_rden (calib_rden),
.calib_rden_sel (calib_rden_sel),
.dlyrst_dq (dlyrst_dq),
.dlyce_dq (dlyce_dq),
.dlyinc_dq (dlyinc_dq),
.dlyrst_dqs (dlyrst_dqs),
.dlyce_dqs (dlyce_dqs),
.dlyinc_dqs (dlyinc_dqs),
.dlyrst_gate (dlyrst_gate),
.dlyce_gate (dlyce_gate),
.dlyinc_gate (dlyinc_gate),
.en_dqs (en_dqs),
.rd_data_sel (rd_data_sel),
.dbg_idel_up_all (dbg_idel_up_all),
.dbg_idel_down_all (dbg_idel_down_all),
.dbg_idel_up_dq (dbg_idel_up_dq),
.dbg_idel_down_dq (dbg_idel_down_dq),
.dbg_idel_up_dqs (dbg_idel_up_dqs),
.dbg_idel_down_dqs (dbg_idel_down_dqs),
.dbg_idel_up_gate (dbg_idel_up_gate),
.dbg_idel_down_gate (dbg_idel_down_gate),
.dbg_sel_idel_dq (dbg_sel_idel_dq),
.dbg_sel_all_idel_dq (dbg_sel_all_idel_dq),
.dbg_sel_idel_dqs (dbg_sel_idel_dqs),
.dbg_sel_all_idel_dqs (dbg_sel_all_idel_dqs),
.dbg_sel_idel_gate (dbg_sel_idel_gate),
.dbg_sel_all_idel_gate (dbg_sel_all_idel_gate),
.dbg_calib_done (dbg_calib_done),
.dbg_calib_err (dbg_calib_err),
.dbg_calib_dq_tap_cnt (dbg_calib_dq_tap_cnt),
.dbg_calib_dqs_tap_cnt (dbg_calib_dqs_tap_cnt),
.dbg_calib_gate_tap_cnt (dbg_calib_gate_tap_cnt),
.dbg_calib_rd_data_sel (dbg_calib_rd_data_sel),
.dbg_calib_rden_dly (dbg_calib_rden_dly),
.dbg_calib_gate_dly (dbg_calib_gate_dly)
);
 
//***************************************************************************
// Memory clock generation
//***************************************************************************
 
genvar ck_i;
generate
for(ck_i = 0; ck_i < CLK_WIDTH; ck_i = ck_i+1) begin: gen_ck
ODDR #
(
.SRTYPE ("SYNC"),
.DDR_CLK_EDGE ("OPPOSITE_EDGE")
)
u_oddr_ck_i
(
.Q (ddr_ck_q[ck_i]),
.C (clk0),
.CE (1'b1),
.D1 (1'b0),
.D2 (1'b1),
.R (1'b0),
.S (1'b0)
);
// Can insert ODELAY here if required
OBUFDS u_obuf_ck_i
(
.I (ddr_ck_q[ck_i]),
.O (ddr_ck[ck_i]),
.OB (ddr_ck_n[ck_i])
);
end
endgenerate
 
//***************************************************************************
// DQS instances
//***************************************************************************
 
genvar dqs_i;
generate
for(dqs_i = 0; dqs_i < DQS_WIDTH; dqs_i = dqs_i+1) begin: gen_dqs
ddr2_phy_dqs_iob #
(
.DDR_TYPE (DDR_TYPE),
.HIGH_PERFORMANCE_MODE (HIGH_PERFORMANCE_MODE),
.IODELAY_GRP (IODELAY_GRP)
)
u_iob_dqs
(
.clk0 (clk0),
.clkdiv0 (clkdiv0),
.rst0 (rst0),
.dlyinc_dqs (dlyinc_dqs[dqs_i]),
.dlyce_dqs (dlyce_dqs[dqs_i]),
.dlyrst_dqs (dlyrst_dqs),
.dlyinc_gate (dlyinc_gate[dqs_i]),
.dlyce_gate (dlyce_gate[dqs_i]),
.dlyrst_gate (dlyrst_gate[dqs_i]),
.dqs_oe_n (dqs_oe_n),
.dqs_rst_n (dqs_rst_n),
.en_dqs (en_dqs[dqs_i]),
.ddr_dqs (ddr_dqs[dqs_i]),
.ddr_dqs_n (ddr_dqs_n[dqs_i]),
.dq_ce (dq_ce[dqs_i]),
.delayed_dqs (delayed_dqs[dqs_i])
);
end
endgenerate
 
//***************************************************************************
// DM instances
//***************************************************************************
 
genvar dm_i;
generate
if (USE_DM_PORT) begin: gen_dm_inst
for(dm_i = 0; dm_i < DM_WIDTH; dm_i = dm_i+1) begin: gen_dm
ddr2_phy_dm_iob u_iob_dm
(
.clk90 (clk90),
.dm_ce (dm_ce),
.mask_data_rise (mask_data_rise[dm_i/DM_TO_BYTE_RATIO]),
.mask_data_fall (mask_data_fall[dm_i/DM_TO_BYTE_RATIO]),
.ddr_dm (ddr_dm[dm_i])
);
end
end
endgenerate
 
//***************************************************************************
// DQ IOB instances
//***************************************************************************
 
genvar dq_i;
generate
for(dq_i = 0; dq_i < DQ_WIDTH; dq_i = dq_i+1) begin: gen_dq
ddr2_phy_dq_iob #
(
.HIGH_PERFORMANCE_MODE (HIGH_PERFORMANCE_MODE),
.IODELAY_GRP (IODELAY_GRP),
.FPGA_SPEED_GRADE (FPGA_SPEED_GRADE)
)
u_iob_dq
(
.clk0 (clk0),
.clk90 (clk90),
.clkdiv0 (clkdiv0),
.rst90 (rst90),
.dlyinc (dlyinc_dq[dq_i]),
.dlyce (dlyce_dq[dq_i]),
.dlyrst (dlyrst_dq),
.dq_oe_n (dq_oe_n),
.dqs (delayed_dqs[dq_i/DQ_PER_DQS]),
.ce (dq_ce[dq_i/DQ_PER_DQS]),
.rd_data_sel (rd_data_sel[dq_i/DQ_PER_DQS]),
.wr_data_rise (wr_data_rise[dq_i]),
.wr_data_fall (wr_data_fall[dq_i]),
.rd_data_rise (rd_data_rise[dq_i]),
.rd_data_fall (rd_data_fall[dq_i]),
.ddr_dq (ddr_dq[dq_i])
);
end
endgenerate
 
endmodule
/verilog/xilinx_ddr2/ddr2_phy_ctl_io.v
0,0 → 1,302
//*****************************************************************************
// DISCLAIMER OF LIABILITY
//
// This file contains proprietary and confidential information of
// Xilinx, Inc. ("Xilinx"), that is distributed under a license
// from Xilinx, and may be used, copied and/or disclosed only
// pursuant to the terms of a valid license agreement with Xilinx.
//
// XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION
// ("MATERIALS") "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
// EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING WITHOUT
// LIMITATION, ANY WARRANTY WITH RESPECT TO NONINFRINGEMENT,
// MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE. Xilinx
// does not warrant that functions included in the Materials will
// meet the requirements of Licensee, or that the operation of the
// Materials will be uninterrupted or error-free, or that defects
// in the Materials will be corrected. Furthermore, Xilinx does
// not warrant or make any representations regarding use, or the
// results of the use, of the Materials in terms of correctness,
// accuracy, reliability or otherwise.
//
// Xilinx products are not designed or intended to be fail-safe,
// or for use in any application requiring fail-safe performance,
// such as life-support or safety devices or systems, Class III
// medical devices, nuclear facilities, applications related to
// the deployment of airbags, or any other applications that could
// lead to death, personal injury or severe property or
// environmental damage (individually and collectively, "critical
// applications"). Customer assumes the sole risk and liability
// of any use of Xilinx products in critical applications,
// subject only to applicable laws and regulations governing
// limitations on product liability.
//
// Copyright 2006, 2007, 2008 Xilinx, Inc.
// All rights reserved.
//
// This disclaimer and copyright notice must be retained as part
// of this file at all times.
//*****************************************************************************
// ____ ____
// / /\/ /
// /___/ \ / Vendor: Xilinx
// \ \ \/ Version: 3.0
// \ \ Application: MIG
// / / Filename: ddr2_phy_ctl_io.v
// /___/ /\ Date Last Modified: $Date: 2008/12/23 14:26:00 $
// \ \ / \ Date Created: Thu Aug 24 2006
// \___\/\___\
//
//Device: Virtex-5
//Design Name: DDR2
//Purpose:
// This module puts the memory control signals like address, bank address,
// row address strobe, column address strobe, write enable and clock enable
// in the IOBs.
//Reference:
//Revision History:
//*****************************************************************************
 
`timescale 1ns/1ps
 
module ddr2_phy_ctl_io #
(
// Following parameters are for 72-bit RDIMM design (for ML561 Reference
// board design). Actual values may be different. Actual parameters values
// are passed from design top module ddr2_mig module. Please refer to
// the ddr2_mig module for actual values.
parameter BANK_WIDTH = 2,
parameter CKE_WIDTH = 1,
parameter COL_WIDTH = 10,
parameter CS_NUM = 1,
parameter TWO_T_TIME_EN = 0,
parameter CS_WIDTH = 1,
parameter ODT_WIDTH = 1,
parameter ROW_WIDTH = 14,
parameter DDR_TYPE = 1
)
(
input clk0,
input clk90,
input rst0,
input rst90,
input [ROW_WIDTH-1:0] ctrl_addr,
input [BANK_WIDTH-1:0] ctrl_ba,
input ctrl_ras_n,
input ctrl_cas_n,
input ctrl_we_n,
input [CS_NUM-1:0] ctrl_cs_n,
input [ROW_WIDTH-1:0] phy_init_addr,
input [BANK_WIDTH-1:0] phy_init_ba,
input phy_init_ras_n,
input phy_init_cas_n,
input phy_init_we_n,
input [CS_NUM-1:0] phy_init_cs_n,
input [CKE_WIDTH-1:0] phy_init_cke,
input phy_init_data_sel,
input [CS_NUM-1:0] odt,
output [ROW_WIDTH-1:0] ddr_addr,
output [BANK_WIDTH-1:0] ddr_ba,
output ddr_ras_n,
output ddr_cas_n,
output ddr_we_n,
output [CKE_WIDTH-1:0] ddr_cke,
output [CS_WIDTH-1:0] ddr_cs_n,
output [ODT_WIDTH-1:0] ddr_odt
);
 
reg [ROW_WIDTH-1:0] addr_mux;
reg [BANK_WIDTH-1:0] ba_mux;
reg cas_n_mux;
reg [CS_NUM-1:0] cs_n_mux;
reg ras_n_mux;
reg we_n_mux;
 
 
 
//***************************************************************************
 
 
 
 
// MUX to choose from either PHY or controller for SDRAM control
 
generate // in 2t timing mode the extra register stage cannot be used.
if(TWO_T_TIME_EN) begin // the control signals are asserted for two cycles
always @(*)begin
if (phy_init_data_sel) begin
addr_mux = ctrl_addr;
ba_mux = ctrl_ba;
cas_n_mux = ctrl_cas_n;
cs_n_mux = ctrl_cs_n;
ras_n_mux = ctrl_ras_n;
we_n_mux = ctrl_we_n;
end else begin
addr_mux = phy_init_addr;
ba_mux = phy_init_ba;
cas_n_mux = phy_init_cas_n;
cs_n_mux = phy_init_cs_n;
ras_n_mux = phy_init_ras_n;
we_n_mux = phy_init_we_n;
end
end
end else begin
always @(posedge clk0)begin // register the signals in non 2t mode
if (phy_init_data_sel) begin
addr_mux <= ctrl_addr;
ba_mux <= ctrl_ba;
cas_n_mux <= ctrl_cas_n;
cs_n_mux <= ctrl_cs_n;
ras_n_mux <= ctrl_ras_n;
we_n_mux <= ctrl_we_n;
end else begin
addr_mux <= phy_init_addr;
ba_mux <= phy_init_ba;
cas_n_mux <= phy_init_cas_n;
cs_n_mux <= phy_init_cs_n;
ras_n_mux <= phy_init_ras_n;
we_n_mux <= phy_init_we_n;
end
end
end
endgenerate
 
//***************************************************************************
// Output flop instantiation
// NOTE: Make sure all control/address flops are placed in IOBs
//***************************************************************************
 
// RAS: = 1 at reset
(* IOB = "FORCE" *) FDCPE u_ff_ras_n
(
.Q (ddr_ras_n),
.C (clk0),
.CE (1'b1),
.CLR (1'b0),
.D (ras_n_mux),
.PRE (rst0)
) /* synthesis syn_useioff = 1 */;
 
// CAS: = 1 at reset
(* IOB = "FORCE" *) FDCPE u_ff_cas_n
(
.Q (ddr_cas_n),
.C (clk0),
.CE (1'b1),
.CLR (1'b0),
.D (cas_n_mux),
.PRE (rst0)
) /* synthesis syn_useioff = 1 */;
 
// WE: = 1 at reset
(* IOB = "FORCE" *) FDCPE u_ff_we_n
(
.Q (ddr_we_n),
.C (clk0),
.CE (1'b1),
.CLR (1'b0),
.D (we_n_mux),
.PRE (rst0)
) /* synthesis syn_useioff = 1 */;
 
// CKE: = 0 at reset
genvar cke_i;
generate
for (cke_i = 0; cke_i < CKE_WIDTH; cke_i = cke_i + 1) begin: gen_cke
(* IOB = "FORCE" *) FDCPE u_ff_cke
(
.Q (ddr_cke[cke_i]),
.C (clk0),
.CE (1'b1),
.CLR (rst0),
.D (phy_init_cke[cke_i]),
.PRE (1'b0)
) /* synthesis syn_useioff = 1 */;
end
endgenerate
 
// chip select: = 1 at reset
// For unbuffered dimms the loading will be high. The chip select
// can be asserted early if the loading is very high. The
// code as is uses clock 0. If needed clock 270 can be used to
// toggle chip select 1/4 clock cycle early. The code has
// the clock 90 input for the early assertion of chip select.
 
genvar cs_i;
generate
for(cs_i = 0; cs_i < CS_WIDTH; cs_i = cs_i + 1) begin: gen_cs_n
if(TWO_T_TIME_EN) begin
(* IOB = "FORCE" *) FDCPE u_ff_cs_n
(
.Q (ddr_cs_n[cs_i]),
.C (clk0),
.CE (1'b1),
.CLR (1'b0),
.D (cs_n_mux[(cs_i*CS_NUM)/CS_WIDTH]),
.PRE (rst0)
) /* synthesis syn_useioff = 1 */;
end else begin // if (TWO_T_TIME_EN)
(* IOB = "FORCE" *) FDCPE u_ff_cs_n
(
.Q (ddr_cs_n[cs_i]),
.C (clk0),
.CE (1'b1),
.CLR (1'b0),
.D (cs_n_mux[(cs_i*CS_NUM)/CS_WIDTH]),
.PRE (rst0)
) /* synthesis syn_useioff = 1 */;
end // else: !if(TWO_T_TIME_EN)
end
endgenerate
 
// address: = X at reset
genvar addr_i;
generate
for (addr_i = 0; addr_i < ROW_WIDTH; addr_i = addr_i + 1) begin: gen_addr
(* IOB = "FORCE" *) FDCPE u_ff_addr
(
.Q (ddr_addr[addr_i]),
.C (clk0),
.CE (1'b1),
.CLR (1'b0),
.D (addr_mux[addr_i]),
.PRE (1'b0)
) /* synthesis syn_useioff = 1 */;
end
endgenerate
 
// bank address = X at reset
genvar ba_i;
generate
for (ba_i = 0; ba_i < BANK_WIDTH; ba_i = ba_i + 1) begin: gen_ba
(* IOB = "FORCE" *) FDCPE u_ff_ba
(
.Q (ddr_ba[ba_i]),
.C (clk0),
.CE (1'b1),
.CLR (1'b0),
.D (ba_mux[ba_i]),
.PRE (1'b0)
) /* synthesis syn_useioff = 1 */;
end
endgenerate
 
// ODT control = 0 at reset
genvar odt_i;
generate
if (DDR_TYPE > 0) begin: gen_odt_ddr2
for (odt_i = 0; odt_i < ODT_WIDTH; odt_i = odt_i + 1) begin: gen_odt
(* IOB = "FORCE" *) FDCPE u_ff_odt
(
.Q (ddr_odt[odt_i]),
.C (clk0),
.CE (1'b1),
.CLR (rst0),
.D (odt[(odt_i*CS_NUM)/ODT_WIDTH]),
.PRE (1'b0)
) /* synthesis syn_useioff = 1 */;
end
end
endgenerate
 
endmodule
/verilog/xilinx_ddr2/xilinx_ddr2_if.v
0,0 → 1,488
//////////////////////////////////////////////////////////////////////
//// ////
//// Xilinx DDR2 controller Wishbone Interface ////
//// ////
//// Description ////
//// Simple interface to the Xilinx MIG generated DDR2 controller////
//// ////
//// To Do: ////
//// Increase usage of cache BRAM to maximum (currently only ////
//// 256 bytes out of about 8192) ////
//// Make this a Wishbone B3 registered feedback burst friendly ////
//// server. ////
//// ////
//// Author(s): ////
//// - Julius Baxter, julius.baxter@orsoc.se ////
//// ////
//// ////
//////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2010 Authors and OPENCORES.ORG ////
//// ////
//// This source file may be used and distributed without ////
//// restriction provided that this copyright statement is not ////
//// removed from the file and that any derivative work contains ////
//// the original copyright notice and the associated disclaimer. ////
//// ////
//// This source file is free software; you can redistribute it ////
//// and/or modify it under the terms of the GNU Lesser General ////
//// Public License as published by the Free Software Foundation; ////
//// either version 2.1 of the License, or (at your option) any ////
//// later version. ////
//// ////
//// This source is distributed in the hope that it will be ////
//// useful, but WITHOUT ANY WARRANTY; without even the implied ////
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ////
//// PURPOSE. See the GNU Lesser General Public License for more ////
//// details. ////
//// ////
//// You should have received a copy of the GNU Lesser General ////
//// Public License along with this source; if not, download it ////
//// from http://www.opencores.org/lgpl.shtml ////
//// ////
//////////////////////////////////////////////////////////////////////
/*
* The controller is design to stream lots of data out at the DDR2 controller's
* rate. All we implement here is enough to do the simplest accesses into a
* small cache, which eases the domain crossing headaches.
*
* This was originally written to handle a DDR2 part which is doing burst length
* of 4 as a minimum via a databus which is 64-bits wide.
*
* This means the smallest accesses is 4*64=256-bits or 32-bytes.
*
* We are bridging to a 32-bit wide system bus, so this means we must handle
* accesses in 8-word lots.
*
* A simple cache mechanism has been implemented, meaning we check if the cached
* data has been written to, and therefore needs writing back to the main memory
* before any other access can occur.
*
* Cache memory:
* The cache memory is a core-generated module, instantiating something out
* of the XilinxCoreLib. The reason is because an arrangement or RAMB36s with
* different sized A and B data in/out ports can't be instantiated directly
* for some reason.
* What we have is side A with 32-bits, and side B with 128-bits wide.
*
* TODO:
* This only supports 8-words for now but can easily be expanded, although
* multiple way/associativity caching will require some extra work to handle
* multiple cached addresses.
*
* But it should be easy enough to make this thing cache as much as its RAMB
* resources allow (4-RAMB16s becuase due to the 128-bit DDR2-side interface)
* which is about 8Kbyte.
*
* Multi-cycle paths:
* Write:
* To indicate that a writeback is occuring, a system-bus domain (wishbone, in
* this case) signal is set, and then sampled in the controller domain whenever
* a system-bus domain clock edge is detected. This register is "do_writeback"
* and then the controller domain register "ddr2_write_done" is asserted when
* the data has been written out of the RAMs and into the controller's fifos.
* "ddr2_write_done" is then sampled by the system-bus domain and "do_writeback"
* So there are paths between:
* ( register -> (sampled by) -> register )
* wb_clk:do_writeback -> ddr2_clk:do_writeback_ddr2_shifter
* wb_clk:do_writeback -> ddr2_clk:ddr2_write_done
* ddr2_clk:ddr2_write_done -> wb_clk:do_writeback
*
* Read:
* The only signal crossing we have here is the one indicating the read data
* has arrived into the cache RAM from the controller. The controller domain
* register "ddr2_read_done" is set, and sampled in the system-bus domain by the
* logic controlling the "do_readfrom" register. "ddr2_read_done" is cleared
* when the controller domain sees that "do_readfrom" has been de-asserted.
* So there are paths between:
* ( register -> (sampled by) -> register )
* ddr2_clk:ddr2_read_done -> wb_clk:do_readfrom
* wb_clk:do_readfrom -> ddr2_clk:ddr2_read_done
*
*/
module xilinx_ddr2_if (
input [31:0] wb_adr_i,
input wb_stb_i,
input wb_cyc_i,
input wb_we_i,
input [3:0] wb_sel_i,
input [31:0] wb_dat_i,
output [31:0] wb_dat_o,
output reg wb_ack_o,
 
output [12:0] ddr2_a,
output [1:0] ddr2_ba,
output ddr2_ras_n,
output ddr2_cas_n,
output ddr2_we_n,
output [1:0] ddr2_cs_n,
output [1:0] ddr2_odt,
output [1:0] ddr2_cke,
output [7:0] ddr2_dm,
 
inout [63:0] ddr2_dq,
inout [7:0] ddr2_dqs,
inout [7:0] ddr2_dqs_n,
output [1:0] ddr2_ck,
output [1:0] ddr2_ck_n,
 
input ddr2_if_clk,
input ddr2_if_rst,
input idly_clk_200,
input wb_clk,
input wb_rst);
`include "xilinx_ddr2_params.v"
 
wire ddr2_clk; // DDR2 iface domain clock.
wire ddr2_rst; // reset from the ddr2 module
wire wb_req;
reg wb_req_r;
reg wb_ack_o_r;
wire wb_req_new;
reg wb_req_new_r;
reg wb_req_addr_hit;
reg cached_addr_valid;
reg [31:6] cached_addr;
wire cache_hit;
reg cache_dirty;
reg [2:0] wb_req_cache_word_addr;
wire wb_cache_en;
reg do_writeback, do_writeback_r;
wire do_writeback_start, do_writeback_finished;
wire doing_writeback;
reg do_readfrom, do_readfrom_r;
wire do_readfrom_start, do_readfrom_finished;
wire doing_readfrom;
// Domain crossing logic
reg wb_clk_r;
reg wb_clk_in_ddr2_clk;
reg wb_clk_in_ddr2_clk_r;
wire wb_clk_edge;
reg [2:0] ddr2_clk_phase;
// Sample when clk phase is 0
reg [7:0] do_writeback_ddr2_shifter;
reg [7:0] do_writeback_ddr2_shifter_r;
reg do_writeback_ddr2_fifo_we;
reg ddr2_write_done;
// Currently, ddr2-side of cache is address is a single bit
reg [1:0] ddr2_cache_addr;
wire [127:0] ddr2_cache_data_o;
reg rd_data_valid_r;
reg ddr2_read_done;
// DDR2 MIG interface wires
wire app_af_afull;
wire app_wdf_afull;
wire app_wdf_wren;
wire app_af_wren;
wire [30:0] app_af_addr;
wire [2:0] app_af_cmd;
wire [(APPDATA_WIDTH)-1:0] app_wdf_data;
wire [(APPDATA_WIDTH/8)-1:0] app_wdf_mask_data;
wire rd_data_valid;
wire [(APPDATA_WIDTH)-1:0] rd_data_fifo_out;
wire phy_init_done;
assign cache_hit = (cached_addr == wb_adr_i[31:6]) & cached_addr_valid;
// Wishbone request detection
assign wb_req = wb_stb_i & wb_cyc_i & phy_init_done;
always @(posedge wb_clk)
wb_req_r <= wb_req;
assign wb_req_new = wb_req & !wb_req_r;
always @(posedge wb_clk)
wb_req_new_r <= wb_req_new;
// Register whether it's a hit or not
// As more lines are added, add them to this check.
always @(posedge wb_clk)
if (wb_rst)
wb_req_addr_hit <= 0;
else
wb_req_addr_hit <= wb_req & cache_hit & cached_addr_valid;
always @(posedge wb_clk)
if (wb_rst)
wb_ack_o <= 0;
else
wb_ack_o <= wb_req_addr_hit & !wb_ack_o & !wb_ack_o_r;
always @(posedge wb_clk)
wb_ack_o_r <= wb_ack_o;
// Address valid logic
always @(posedge wb_clk)
if (wb_rst)
cached_addr_valid <= 0;
else if (do_readfrom_finished)
cached_addr_valid <= 1;
else if ( do_writeback_finished ) // Data written back, cache not valid
cached_addr_valid <= 0;
else if (wb_req & !cache_hit & cached_addr_valid & !cache_dirty)
// Invalidate cache so a readfrom begins
cached_addr_valid <= 0;
// Address cacheing
always @(posedge wb_clk)
if (wb_rst)
cached_addr <= 0;
else if (do_readfrom_start)
cached_addr <= wb_adr_i[31:6];
// Cache dirty signal
always @(posedge wb_clk)
if (wb_rst)
cache_dirty <= 0;
else if (wb_req & wb_we_i & wb_req_addr_hit & wb_ack_o)
cache_dirty <= 1;
else if (!cached_addr_valid & cache_dirty)
cache_dirty <= 0;
 
// Wishbone side of cache enable. Important!
// 1. Enable on first access, if it's not a write
// 2. Enable if we've just refreshed the cache
// 3. Enable on ACK'ing for a write
assign wb_cache_en = (wb_req_new & !wb_we_i) | do_readfrom_finished |
(wb_req_addr_hit & wb_stb_i & !wb_we_i & !wb_ack_o) |
(wb_ack_o & wb_we_i);
// Writeback detect logic
always @(posedge wb_clk)
if (wb_rst)
do_writeback <= 0;
else if (ddr2_write_done) // DDR2 domain signal
do_writeback <= 0;
else if (wb_req & !cache_hit & cached_addr_valid & !doing_writeback & cache_dirty)
do_writeback <= 1;
always @(posedge wb_clk)
do_writeback_r <= do_writeback;
assign do_writeback_start = do_writeback & !do_writeback_r;
assign do_writeback_finished = !do_writeback & do_writeback_r;
assign doing_writeback = do_writeback | do_writeback_r;
// DDR2 Read detect logic
always @(posedge wb_clk)
if (wb_rst)
do_readfrom <= 0;
else if (ddr2_read_done) // DDR2 domain signal
do_readfrom <= 0;
else if (wb_req & !cache_hit & !cached_addr_valid & !doing_readfrom & !cache_dirty)
do_readfrom <= 1;
 
always @(posedge wb_clk)
do_readfrom_r <= do_readfrom;
 
assign do_readfrom_start = do_readfrom & !do_readfrom_r;
assign do_readfrom_finished = !do_readfrom & do_readfrom_r;
assign doing_readfrom = do_readfrom | do_readfrom_r;
 
// Address fifo signals
assign app_af_wren = (do_writeback_finished | do_readfrom_start);
assign app_af_cmd[0] = do_readfrom_start; // 1 - read, 0 - write
assign app_af_cmd[2:1] = 0;
assign app_af_addr = do_readfrom_start ? {2'd0, wb_adr_i[31:6],3'd0} :
{2'd0,cached_addr,3'd0};
assign app_wdf_wren = do_writeback_ddr2_fifo_we;
assign app_wdf_data = ddr2_cache_data_o;
assign app_wdf_mask_data = 0;
always @(posedge wb_clk) if (wb_rst) wb_clk_r <= 0; else wb_clk_r <= ~wb_clk_r;
always @(posedge ddr2_clk) wb_clk_in_ddr2_clk <= wb_clk_r;
always @(posedge ddr2_clk) wb_clk_in_ddr2_clk_r <= wb_clk_in_ddr2_clk;
assign wb_clk_edge = wb_clk_in_ddr2_clk & !wb_clk_in_ddr2_clk_r;
always @(posedge ddr2_clk)
if (ddr2_rst)
ddr2_clk_phase <= 0;
else if (wb_clk_edge)
ddr2_clk_phase <= 0;
else
ddr2_clk_phase <= ddr2_clk_phase + 1;
always @(posedge ddr2_clk)
do_writeback_ddr2_fifo_we <= (do_writeback_ddr2_shifter_r[0]) |
(do_writeback_ddr2_shifter_r[2]) |
(do_writeback_ddr2_shifter_r[4]) |
(do_writeback_ddr2_shifter_r[6]);
 
// Kick off counting when we see that the wb_clk domain is
// doing a writeback.
always @(posedge ddr2_clk)
if (ddr2_rst)
do_writeback_ddr2_shifter <= 4'h0;
else if (|do_writeback_ddr2_shifter)
do_writeback_ddr2_shifter <= {do_writeback_ddr2_shifter[6:0], 1'b0};
else if (!(|ddr2_clk_phase) & do_writeback & !ddr2_write_done) // sample WB domain
do_writeback_ddr2_shifter <= 1;
 
 
always @(posedge ddr2_clk)
do_writeback_ddr2_shifter_r <= do_writeback_ddr2_shifter;
always @(posedge ddr2_clk)
if (ddr2_rst)
ddr2_write_done <= 0;
else if (do_writeback_ddr2_shifter[7])
ddr2_write_done <= 1;
else if ((!(|ddr2_clk_phase)) & !do_writeback) // sample WB domain
ddr2_write_done <= 0;
always @(posedge ddr2_clk)
if (ddr2_rst)
ddr2_cache_addr <= 0;
else if (rd_data_valid | do_writeback_ddr2_fifo_we)
ddr2_cache_addr <= ddr2_cache_addr + 1;
always @(posedge ddr2_clk)
rd_data_valid_r <= rd_data_valid;
// Read done signaling to WB domain
always @(posedge ddr2_clk)
if (ddr2_rst)
ddr2_read_done <= 0;
else if (!rd_data_valid & rd_data_valid_r) // Detect read data valid falling edge
ddr2_read_done <= 1;
else if (!(|ddr2_clk_phase) & !do_readfrom) // Read WB domain
ddr2_read_done <= 0;
 
wire [3:0] wb_cache_adr;
assign wb_cache_adr = wb_adr_i[5:2];
wire [3:0] wb_cache_sel_we;
assign wb_cache_sel_we = {4{wb_we_i}} & wb_sel_i;
wire ddr2_cache_en;
wire [15:0] ddr2_cache_we;
assign ddr2_cache_en = rd_data_valid | (|do_writeback_ddr2_shifter);
assign ddr2_cache_we = {16{rd_data_valid}};
// Xilinx Coregen true dual-port RAMB array.
// Wishbone side : 32-bit
// DDR2 side : 128-bit
xilinx_ddr2_if_cache cache_mem0
(
// Wishbone side
.clka(wb_clk),
.ena(wb_cache_en),
.wea(wb_cache_sel_we),
.addra({8'd0,wb_cache_adr}),
.dina(wb_dat_i),
.douta(wb_dat_o),
 
// DDR2 controller side
.clkb(ddr2_clk),
.enb(ddr2_cache_en),
.web(ddr2_cache_we),
.addrb({8'd0,ddr2_cache_addr}),
.dinb(rd_data_fifo_out),
.doutb(ddr2_cache_data_o));
ddr2_mig #
(
.BANK_WIDTH (BANK_WIDTH),
.CKE_WIDTH (CKE_WIDTH),
.CLK_WIDTH (CLK_WIDTH),
.COL_WIDTH (COL_WIDTH),
.CS_NUM (CS_NUM),
.CS_WIDTH (CS_WIDTH),
.CS_BITS (CS_BITS),
.DM_WIDTH (DM_WIDTH),
.DQ_WIDTH (DQ_WIDTH),
.DQ_PER_DQS (DQ_PER_DQS),
.DQ_BITS (DQ_BITS),
.DQS_WIDTH (DQS_WIDTH),
.DQS_BITS (DQS_BITS),
.HIGH_PERFORMANCE_MODE (HIGH_PERFORMANCE_MODE),
.ODT_WIDTH (ODT_WIDTH),
.ROW_WIDTH (ROW_WIDTH),
.APPDATA_WIDTH (APPDATA_WIDTH),
.ADDITIVE_LAT (ADDITIVE_LAT),
.BURST_LEN (BURST_LEN),
.BURST_TYPE (BURST_TYPE),
.CAS_LAT (CAS_LAT),
.ECC_ENABLE (ECC_ENABLE),
.MULTI_BANK_EN (MULTI_BANK_EN),
.ODT_TYPE (ODT_TYPE),
.REDUCE_DRV (REDUCE_DRV),
.REG_ENABLE (REG_ENABLE),
.TREFI_NS (TREFI_NS),
.TRAS (TRAS),
.TRCD (TRCD),
.TRFC (TRFC),
.TRP (TRP),
.TRTP (TRTP),
.TWR (TWR),
.TWTR (TWTR),
.SIM_ONLY (SIM_ONLY),
.RST_ACT_LOW (RST_ACT_LOW),
.CLK_TYPE (CLK_TYPE),
.DLL_FREQ_MODE (DLL_FREQ_MODE),
.CLK_PERIOD (CLK_PERIOD)
)
ddr2_mig0
(
.sys_clk (ddr2_if_clk),
.idly_clk_200 (idly_clk_200),
.sys_rst_n (ddr2_if_rst), // Act. high, sync. to ddr2_if_clk
.ddr2_ras_n (ddr2_ras_n),
.ddr2_cas_n (ddr2_cas_n),
.ddr2_we_n (ddr2_we_n),
.ddr2_cs_n (ddr2_cs_n),
.ddr2_cke (ddr2_cke),
.ddr2_odt (ddr2_odt),
.ddr2_dm (ddr2_dm),
.ddr2_dq (ddr2_dq),
.ddr2_dqs (ddr2_dqs),
.ddr2_dqs_n (ddr2_dqs_n),
.ddr2_ck (ddr2_ck),
.ddr2_ck_n (ddr2_ck_n),
.ddr2_ba (ddr2_ba),
.ddr2_a (ddr2_a),
.clk0_tb (ddr2_clk),
.rst0_tb (ddr2_rst),
.usr_clk (wb_clk),
.app_af_afull (app_af_afull),
.app_wdf_afull (app_wdf_afull),
.rd_data_valid (rd_data_valid),
.rd_data_fifo_out (rd_data_fifo_out),
.app_af_wren (app_af_wren),
.app_af_cmd (app_af_cmd),
.app_af_addr (app_af_addr),
.app_wdf_wren (app_wdf_wren),
.app_wdf_data (app_wdf_data),
.app_wdf_mask_data (app_wdf_mask_data),
.phy_init_done (phy_init_done)
);
 
endmodule // ml501_ddr2_if
// Local Variables:
// verilog-library-directories:("." "ddr2_mig")
// verilog-library-extensions:(".v" ".h")
// End:
/verilog/xilinx_ddr2/ddr2_phy_calib.v
0,0 → 1,2349
//*****************************************************************************
// DISCLAIMER OF LIABILITY
//
// This file contains proprietary and confidential information of
// Xilinx, Inc. ("Xilinx"), that is distributed under a license
// from Xilinx, and may be used, copied and/or disclosed only
// pursuant to the terms of a valid license agreement with Xilinx.
//
// XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION
// ("MATERIALS") "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
// EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING WITHOUT
// LIMITATION, ANY WARRANTY WITH RESPECT TO NONINFRINGEMENT,
// MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE. Xilinx
// does not warrant that functions included in the Materials will
// meet the requirements of Licensee, or that the operation of the
// Materials will be uninterrupted or error-free, or that defects
// in the Materials will be corrected. Furthermore, Xilinx does
// not warrant or make any representations regarding use, or the
// results of the use, of the Materials in terms of correctness,
// accuracy, reliability or otherwise.
//
// Xilinx products are not designed or intended to be fail-safe,
// or for use in any application requiring fail-safe performance,
// such as life-support or safety devices or systems, Class III
// medical devices, nuclear facilities, applications related to
// the deployment of airbags, or any other applications that could
// lead to death, personal injury or severe property or
// environmental damage (individually and collectively, "critical
// applications"). Customer assumes the sole risk and liability
// of any use of Xilinx products in critical applications,
// subject only to applicable laws and regulations governing
// limitations on product liability.
//
// Copyright 2006, 2007, 2008 Xilinx, Inc.
// All rights reserved.
//
// This disclaimer and copyright notice must be retained as part
// of this file at all times.
//*****************************************************************************
// ____ ____
// / /\/ /
// /___/ \ / Vendor: Xilinx
// \ \ \/ Version: 3.0
// \ \ Application: MIG
// / / Filename: ddr2_phy_calib.v
// /___/ /\ Date Last Modified: $Date: 2008/12/23 14:26:00 $
// \ \ / \ Date Created: Thu Aug 10 2006
// \___\/\___\
//
//Device: Virtex-5
//Design Name: DDR2
//Purpose:
// This module handles calibration after memory initialization.
//Reference:
//Revision History:
//*****************************************************************************
 
`timescale 1ns/1ps
 
module ddr2_phy_calib #
(
// Following parameters are for 72-bit RDIMM design (for ML561 Reference
// board design). Actual values may be different. Actual parameters values
// are passed from design top module ddr2_mig module. Please refer to
// the ddr2_mig module for actual values.
parameter DQ_WIDTH = 72,
parameter DQ_BITS = 7,
parameter DQ_PER_DQS = 8,
parameter DQS_BITS = 4,
parameter DQS_WIDTH = 9,
parameter ADDITIVE_LAT = 0,
parameter CAS_LAT = 5,
parameter REG_ENABLE = 1,
parameter CLK_PERIOD = 3000,
parameter SIM_ONLY = 0,
parameter DEBUG_EN = 0
)
(
input clk,
input clkdiv,
input rstdiv,
input [3:0] calib_start,
input ctrl_rden,
input phy_init_rden,
input [DQ_WIDTH-1:0] rd_data_rise,
input [DQ_WIDTH-1:0] rd_data_fall,
input calib_ref_done,
output reg [3:0] calib_done,
output reg calib_ref_req,
output [DQS_WIDTH-1:0] calib_rden,
output reg [DQS_WIDTH-1:0] calib_rden_sel,
output reg dlyrst_dq,
output reg [DQ_WIDTH-1:0] dlyce_dq,
output reg [DQ_WIDTH-1:0] dlyinc_dq,
output reg dlyrst_dqs,
output reg [DQS_WIDTH-1:0] dlyce_dqs,
output reg [DQS_WIDTH-1:0] dlyinc_dqs,
output reg [DQS_WIDTH-1:0] dlyrst_gate,
output reg [DQS_WIDTH-1:0] dlyce_gate,
output reg [DQS_WIDTH-1:0] dlyinc_gate,
output [DQS_WIDTH-1:0] en_dqs,
output [DQS_WIDTH-1:0] rd_data_sel,
// Debug signals (optional use)
input dbg_idel_up_all,
input dbg_idel_down_all,
input dbg_idel_up_dq,
input dbg_idel_down_dq,
input dbg_idel_up_dqs,
input dbg_idel_down_dqs,
input dbg_idel_up_gate,
input dbg_idel_down_gate,
input [DQ_BITS-1:0] dbg_sel_idel_dq,
input dbg_sel_all_idel_dq,
input [DQS_BITS:0] dbg_sel_idel_dqs,
input dbg_sel_all_idel_dqs,
input [DQS_BITS:0] dbg_sel_idel_gate,
input dbg_sel_all_idel_gate,
output [3:0] dbg_calib_done,
output [3:0] dbg_calib_err,
output [(6*DQ_WIDTH)-1:0] dbg_calib_dq_tap_cnt,
output [(6*DQS_WIDTH)-1:0] dbg_calib_dqs_tap_cnt,
output [(6*DQS_WIDTH)-1:0] dbg_calib_gate_tap_cnt,
output [DQS_WIDTH-1:0] dbg_calib_rd_data_sel,
output [(5*DQS_WIDTH)-1:0] dbg_calib_rden_dly,
output [(5*DQS_WIDTH)-1:0] dbg_calib_gate_dly
);
 
// minimum time (in IDELAY taps) for which capture data must be stable for
// algorithm to consider
localparam MIN_WIN_SIZE = 5;
// IDEL_SET_VAL = (# of cycles - 1) to wait after changing IDELAY value
// we only have to wait enough for input with new IDELAY value to
// propagate through pipeline stages.
localparam IDEL_SET_VAL = 3'b111;
// # of clock cycles to delay read enable to determine if read data pattern
// is correct for stage 3/4 (RDEN, DQS gate) calibration
localparam CALIB_RDEN_PIPE_LEN = 31;
// translate CAS latency into number of clock cycles for read valid delay
// determination. Really only needed for CL = 2.5 (set to 2)
localparam CAS_LAT_RDEN = (CAS_LAT == 25) ? 2 : CAS_LAT;
// an SRL32 is used to delay CTRL_RDEN to generate read valid signal. This
// is min possible value delay through SRL32 can be
localparam RDEN_BASE_DELAY = CAS_LAT_RDEN + ADDITIVE_LAT + REG_ENABLE;
// an SRL32 is used to delay the CTRL_RDEN from the read postamble DQS
// gate. This is min possible value the SRL32 delay can be:
// - Delay from end of deassertion of CTRL_RDEN to last falling edge of
// read burst = 3.5 (CTRL_RDEN -> CAS delay) + 3 (min CAS latency) = 6.5
// - Minimum time for DQS gate circuit to be generated:
// * 1 cyc to register CTRL_RDEN from controller
// * 1 cyc after RDEN_CTRL falling edge
// * 1 cyc min through SRL32
// * 1 cyc through SRL32 output flop
// * 0 (<1) cyc of synchronization to DQS domain via IDELAY
// * 1 cyc of delay through IDDR to generate CE to DQ IDDR's
// Total = 5 cyc < 6.5 cycles
// The total should be less than 5.5 cycles to account prop delays
// adding one cycle to the synchronization time via the IDELAY.
// NOTE: Value differs because of optional pipeline register added
// for case of RDEN_BASE_DELAY > 3 to improve timing
localparam GATE_BASE_DELAY = RDEN_BASE_DELAY - 3;
localparam GATE_BASE_INIT = (GATE_BASE_DELAY <= 1) ? 0 : GATE_BASE_DELAY;
// used for RDEN calibration: difference between shift value used during
// calibration, and shift value for actual RDEN SRL. Only applies when
// RDEN edge is immediately captured by CLKDIV0. If not (depends on phase
// of CLK0 and CLKDIV0 when RDEN is asserted), then add 1 to this value.
localparam CAL3_RDEN_SRL_DLY_DELTA = 6;
// fix minimum value of DQS to be 1 to handle the case where's there's only
// one DQS group. We could also enforce that user always inputs minimum
// value of 1 for DQS_BITS (even when DQS_WIDTH=1). Leave this as safeguard
// Assume we don't have to do this for DQ, DQ_WIDTH always > 1
localparam DQS_BITS_FIX = (DQS_BITS == 0) ? 1 : DQS_BITS;
// how many taps to "pre-delay" DQ before stg 1 calibration - not needed for
// current calibration, but leave for debug
localparam DQ_IDEL_INIT = 6'b000000;
// # IDELAY taps per bit time (i.e. half cycle). Limit to 63.
localparam integer BIT_TIME_TAPS = (CLK_PERIOD/150 < 64) ?
CLK_PERIOD/150 : 63;
 
// used in various places during stage 4 cal: (1) determines maximum taps
// to increment when finding right edge, (2) amount to decrement after
// finding left edge, (3) amount to increment after finding right edge
localparam CAL4_IDEL_BIT_VAL = (BIT_TIME_TAPS >= 6'b100000) ?
6'b100000 : BIT_TIME_TAPS;
 
localparam CAL1_IDLE = 4'h0;
localparam CAL1_INIT = 4'h1;
localparam CAL1_INC_IDEL = 4'h2;
localparam CAL1_FIND_FIRST_EDGE = 4'h3;
localparam CAL1_FIRST_EDGE_IDEL_WAIT = 4'h4;
localparam CAL1_FOUND_FIRST_EDGE_WAIT = 4'h5;
localparam CAL1_FIND_SECOND_EDGE = 4'h6;
localparam CAL1_SECOND_EDGE_IDEL_WAIT = 4'h7;
localparam CAL1_CALC_IDEL = 4'h8;
localparam CAL1_DEC_IDEL = 4'h9;
localparam CAL1_DONE = 4'hA;
 
localparam CAL2_IDLE = 4'h0;
localparam CAL2_INIT = 4'h1;
localparam CAL2_INIT_IDEL_WAIT = 4'h2;
localparam CAL2_FIND_EDGE_POS = 4'h3;
localparam CAL2_FIND_EDGE_IDEL_WAIT_POS = 4'h4;
localparam CAL2_FIND_EDGE_NEG = 4'h5;
localparam CAL2_FIND_EDGE_IDEL_WAIT_NEG = 4'h6;
localparam CAL2_DEC_IDEL = 4'h7;
localparam CAL2_DONE = 4'h8;
 
localparam CAL3_IDLE = 3'h0;
localparam CAL3_INIT = 3'h1;
localparam CAL3_DETECT = 3'h2;
localparam CAL3_RDEN_PIPE_CLR_WAIT = 3'h3;
localparam CAL3_DONE = 3'h4;
 
localparam CAL4_IDLE = 3'h0;
localparam CAL4_INIT = 3'h1;
localparam CAL4_FIND_WINDOW = 3'h2;
localparam CAL4_FIND_EDGE = 3'h3;
localparam CAL4_IDEL_WAIT = 3'h4;
localparam CAL4_RDEN_PIPE_CLR_WAIT = 3'h5;
localparam CAL4_ADJ_IDEL = 3'h6;
localparam CAL4_DONE = 3'h7;
 
integer i, j;
 
reg [5:0] cal1_bit_time_tap_cnt;
reg [1:0] cal1_data_chk_last;
reg cal1_data_chk_last_valid;
reg [1:0] cal1_data_chk_r;
reg cal1_dlyce_dq;
reg cal1_dlyinc_dq;
reg cal1_dqs_dq_init_phase;
reg cal1_detect_edge;
reg cal1_detect_stable;
reg cal1_found_second_edge;
reg cal1_found_rising;
reg cal1_found_window;
reg cal1_first_edge_done;
reg [5:0] cal1_first_edge_tap_cnt;
reg [6:0] cal1_idel_dec_cnt;
reg [5:0] cal1_idel_inc_cnt;
reg [5:0] cal1_idel_max_tap;
reg cal1_idel_max_tap_we;
reg [5:0] cal1_idel_tap_cnt;
reg cal1_idel_tap_limit_hit;
reg [6:0] cal1_low_freq_idel_dec;
reg cal1_ref_req;
wire cal1_refresh;
reg [3:0] cal1_state;
reg [3:0] cal1_window_cnt;
reg cal2_curr_sel;
wire cal2_detect_edge;
reg cal2_dlyce_dqs;
reg cal2_dlyinc_dqs;
reg [5:0] cal2_idel_dec_cnt;
reg [5:0] cal2_idel_tap_cnt;
reg [5:0] cal2_idel_tap_limit;
reg cal2_idel_tap_limit_hit;
reg cal2_rd_data_fall_last_neg;
reg cal2_rd_data_fall_last_pos;
reg cal2_rd_data_last_valid_neg;
reg cal2_rd_data_last_valid_pos;
reg cal2_rd_data_rise_last_neg;
reg cal2_rd_data_rise_last_pos;
reg [DQS_WIDTH-1:0] cal2_rd_data_sel;
wire cal2_rd_data_sel_edge;
reg [DQS_WIDTH-1:0] cal2_rd_data_sel_r;
reg cal2_ref_req;
reg [3:0] cal2_state;
reg cal3_data_match;
reg cal3_data_match_stgd;
wire cal3_data_valid;
wire cal3_match_found;
wire [4:0] cal3_rden_dly;
reg [4:0] cal3_rden_srl_a;
reg [2:0] cal3_state;
wire cal4_data_good;
reg cal4_data_match;
reg cal4_data_match_stgd;
wire cal4_data_valid;
reg cal4_dlyce_gate;
reg cal4_dlyinc_gate;
reg cal4_dlyrst_gate;
reg [4:0] cal4_gate_srl_a;
reg [5:0] cal4_idel_adj_cnt;
reg cal4_idel_adj_inc;
reg cal4_idel_bit_tap;
reg [5:0] cal4_idel_tap_cnt;
reg cal4_idel_max_tap;
reg [4:0] cal4_rden_srl_a;
reg cal4_ref_req;
reg cal4_seek_left;
reg cal4_stable_window;
reg [2:0] cal4_state;
reg [3:0] cal4_window_cnt;
reg [3:0] calib_done_tmp; // only for stg1/2/4
reg calib_ctrl_gate_pulse_r;
reg calib_ctrl_rden;
reg calib_ctrl_rden_r;
wire calib_ctrl_rden_negedge;
reg calib_ctrl_rden_negedge_r;
reg [3:0] calib_done_r;
reg [3:0] calib_err;
reg [1:0] calib_err_2;
wire calib_init_gate_pulse;
reg calib_init_gate_pulse_r;
reg calib_init_gate_pulse_r1;
reg calib_init_rden;
reg calib_init_rden_r;
reg [4:0] calib_rden_srl_a;
wire [4:0] calib_rden_srl_a_r;
reg [(5*DQS_WIDTH)-1:0] calib_rden_dly;
reg calib_rden_edge_r;
reg [4:0] calib_rden_pipe_cnt;
wire calib_rden_srl_out;
wire calib_rden_srl_out_r;
reg calib_rden_srl_out_r1;
reg calib_rden_valid;
reg calib_rden_valid_stgd;
reg [DQ_BITS-1:0] count_dq;
reg [DQS_BITS_FIX-1:0] count_dqs;
reg [DQS_BITS_FIX-1:0] count_gate;
reg [DQS_BITS_FIX-1:0] count_rden;
reg ctrl_rden_r;
wire dlyce_or;
reg [(5*DQS_WIDTH)-1:0] gate_dly;
wire [(5*DQS_WIDTH)-1:0] gate_dly_r;
wire gate_srl_in;
wire [DQS_WIDTH-1:0] gate_srl_out;
wire [DQS_WIDTH-1:0] gate_srl_out_r;
reg [2:0] idel_set_cnt;
wire idel_set_wait;
reg [DQ_BITS-1:0] next_count_dq;
reg [DQS_BITS_FIX-1:0] next_count_dqs;
reg [DQS_BITS_FIX-1:0] next_count_gate;
reg phy_init_rden_r;
reg phy_init_rden_r1;
reg [DQ_WIDTH-1:0] rd_data_fall_1x_r;
reg [DQS_WIDTH-1:0] rd_data_fall_1x_r1;
reg [DQS_WIDTH-1:0] rd_data_fall_2x_r;
wire [DQS_WIDTH-1:0] rd_data_fall_chk_q1;
wire [DQS_WIDTH-1:0] rd_data_fall_chk_q2;
reg [DQ_WIDTH-1:0] rd_data_rise_1x_r;
reg [DQS_WIDTH-1:0] rd_data_rise_1x_r1;
reg [DQS_WIDTH-1:0] rd_data_rise_2x_r;
wire [DQS_WIDTH-1:0] rd_data_rise_chk_q1;
wire [DQS_WIDTH-1:0] rd_data_rise_chk_q2;
reg rdd_fall_q1;
reg rdd_fall_q1_r;
reg rdd_fall_q1_r1;
reg rdd_fall_q2;
reg rdd_fall_q2_r;
reg rdd_rise_q1;
reg rdd_rise_q1_r;
reg rdd_rise_q1_r1;
reg rdd_rise_q2;
reg rdd_rise_q2_r;
reg [DQS_BITS_FIX-1:0] rdd_mux_sel;
reg rden_dec;
reg [(5*DQS_WIDTH)-1:0] rden_dly;
wire [(5*DQS_WIDTH)-1:0] rden_dly_r;
reg [4:0] rden_dly_0;
reg rden_inc;
reg [DQS_WIDTH-1:0] rden_mux;
wire [DQS_WIDTH-1:0] rden_srl_out;
 
// Debug
integer x;
reg [5:0] dbg_dq_tap_cnt [DQ_WIDTH-1:0];
reg [5:0] dbg_dqs_tap_cnt [DQS_WIDTH-1:0];
reg [5:0] dbg_gate_tap_cnt [DQS_WIDTH-1:0];
 
//***************************************************************************
// Debug output ("dbg_phy_calib_*")
// NOTES:
// 1. All debug outputs coming out of PHY_CALIB are clocked off CLKDIV0,
// although they are also static after calibration is complete. This
// means the user can either connect them to a Chipscope ILA, or to
// either a sync/async VIO input block. Using an async VIO has the
// advantage of not requiring these paths to meet cycle-to-cycle timing.
// 2. The widths of most of these debug buses are dependent on the # of
// DQS/DQ bits (e.g. dq_tap_cnt width = 6 * (# of DQ bits)
// SIGNAL DESCRIPTION:
// 1. calib_done: 4 bits - each one asserted as each phase of calibration
// is completed.
// 2. calib_err: 4 bits - each one asserted when a calibration error
// encountered for that stage. Some of these bits may not
// be used (not all cal stages report an error).
// 3. dq_tap_cnt: final IDELAY tap counts for all DQ IDELAYs
// 4. dqs_tap_cnt: final IDELAY tap counts for all DQS IDELAYs
// 5. gate_tap_cnt: final IDELAY tap counts for all DQS gate
// synchronization IDELAYs
// 6. rd_data_sel: final read capture MUX (either "positive" or "negative"
// edge capture) settings for all DQS groups
// 7. rden_dly: related to # of cycles after issuing a read until when
// read data is valid - for all DQS groups
// 8. gate_dly: related to # of cycles after issuing a read until when
// clock enable for all DQ's is deasserted to prevent
// effect of DQS postamble glitch - for all DQS groups
//***************************************************************************
 
//*****************************************************************
// Record IDELAY tap values by "snooping" IDELAY control signals
//*****************************************************************
 
// record DQ IDELAY tap values
genvar dbg_dq_tc_i;
generate
for (dbg_dq_tc_i = 0; dbg_dq_tc_i < DQ_WIDTH;
dbg_dq_tc_i = dbg_dq_tc_i + 1) begin: gen_dbg_dq_tap_cnt
assign dbg_calib_dq_tap_cnt[(6*dbg_dq_tc_i)+5:(6*dbg_dq_tc_i)]
= dbg_dq_tap_cnt[dbg_dq_tc_i];
always @(posedge clkdiv)
if (rstdiv | dlyrst_dq)
dbg_dq_tap_cnt[dbg_dq_tc_i] <= 6'b000000;
else
if (dlyce_dq[dbg_dq_tc_i])
if (dlyinc_dq[dbg_dq_tc_i])
dbg_dq_tap_cnt[dbg_dq_tc_i]
<= dbg_dq_tap_cnt[dbg_dq_tc_i] + 1;
else
dbg_dq_tap_cnt[dbg_dq_tc_i]
<= dbg_dq_tap_cnt[dbg_dq_tc_i] - 1;
end
endgenerate
 
// record DQS IDELAY tap values
genvar dbg_dqs_tc_i;
generate
for (dbg_dqs_tc_i = 0; dbg_dqs_tc_i < DQS_WIDTH;
dbg_dqs_tc_i = dbg_dqs_tc_i + 1) begin: gen_dbg_dqs_tap_cnt
assign dbg_calib_dqs_tap_cnt[(6*dbg_dqs_tc_i)+5:(6*dbg_dqs_tc_i)]
= dbg_dqs_tap_cnt[dbg_dqs_tc_i];
always @(posedge clkdiv)
if (rstdiv | dlyrst_dqs)
dbg_dqs_tap_cnt[dbg_dqs_tc_i] <= 6'b000000;
else
if (dlyce_dqs[dbg_dqs_tc_i])
if (dlyinc_dqs[dbg_dqs_tc_i])
dbg_dqs_tap_cnt[dbg_dqs_tc_i]
<= dbg_dqs_tap_cnt[dbg_dqs_tc_i] + 1;
else
dbg_dqs_tap_cnt[dbg_dqs_tc_i]
<= dbg_dqs_tap_cnt[dbg_dqs_tc_i] - 1;
end
endgenerate
 
// record DQS gate IDELAY tap values
genvar dbg_gate_tc_i;
generate
for (dbg_gate_tc_i = 0; dbg_gate_tc_i < DQS_WIDTH;
dbg_gate_tc_i = dbg_gate_tc_i + 1) begin: gen_dbg_gate_tap_cnt
assign dbg_calib_gate_tap_cnt[(6*dbg_gate_tc_i)+5:(6*dbg_gate_tc_i)]
= dbg_gate_tap_cnt[dbg_gate_tc_i];
always @(posedge clkdiv)
if (rstdiv | dlyrst_gate[dbg_gate_tc_i])
dbg_gate_tap_cnt[dbg_gate_tc_i] <= 6'b000000;
else
if (dlyce_gate[dbg_gate_tc_i])
if (dlyinc_gate[dbg_gate_tc_i])
dbg_gate_tap_cnt[dbg_gate_tc_i]
<= dbg_gate_tap_cnt[dbg_gate_tc_i] + 1;
else
dbg_gate_tap_cnt[dbg_gate_tc_i]
<= dbg_gate_tap_cnt[dbg_gate_tc_i] - 1;
end
endgenerate
 
assign dbg_calib_done = calib_done;
assign dbg_calib_err = calib_err;
assign dbg_calib_rd_data_sel = cal2_rd_data_sel;
assign dbg_calib_rden_dly = rden_dly;
assign dbg_calib_gate_dly = gate_dly;
 
//***************************************************************************
// Read data pipelining, and read data "ISERDES" data width expansion
//***************************************************************************
 
// For all data bits, register incoming capture data to slow clock to improve
// timing. Adding single pipeline stage does not affect functionality (as
// long as we make sure to wait extra clock cycle after changing DQ IDELAY)
// Also note in this case that we're "missing" every other clock cycle's
// worth of data capture since we're sync'ing to the slow clock. This is
// fine for stage 1 and stage 2 cal, but not for stage 3 and 4 (see below
// for different circuit to handle those stages)
always @(posedge clkdiv) begin
rd_data_rise_1x_r <= rd_data_rise;
rd_data_fall_1x_r <= rd_data_fall;
end
 
// For every DQ_PER_DQS bit, generate what is essentially a ISERDES-type
// data width expander. Will need this for stage 3 and 4 cal, where we need
// to compare data over consecutive clock cycles. We can also use this for
// stage 2 as well (stage 2 doesn't require every bit to be looked at, only
// one bit per DQS group)
genvar rdd_i;
generate
for (rdd_i = 0; rdd_i < DQS_WIDTH; rdd_i = rdd_i + 1) begin: gen_rdd
// first stage: keep data in fast clk domain. Store data over two
// consecutive clock cycles for rise/fall data for proper transfer
// to slow clock domain
always @(posedge clk) begin
rd_data_rise_2x_r[rdd_i] <= rd_data_rise[(rdd_i*DQ_PER_DQS)];
rd_data_fall_2x_r[rdd_i] <= rd_data_fall[(rdd_i*DQ_PER_DQS)];
end
// second stage, register first stage to slow clock domain, 2nd stage
// consists of both these flops, and the rd_data_rise_1x_r flops
always @(posedge clkdiv) begin
rd_data_rise_1x_r1[rdd_i] <= rd_data_rise_2x_r[rdd_i];
rd_data_fall_1x_r1[rdd_i] <= rd_data_fall_2x_r[rdd_i];
end
// now we have four outputs - representing rise/fall outputs over last
// 2 fast clock cycles. However, the ordering these represent can either
// be: (1) Q2 = data @ time = n, Q1 = data @ time = n+1, or (2)
// Q2 = data @ time = n - 1, Q1 = data @ time = n (and data at [Q1,Q2]
// is "staggered") - leave it up to the stage of calibration using this
// to figure out which is which, if they care at all (e.g. stage 2 cal
// doesn't care about the ordering)
assign rd_data_rise_chk_q1[rdd_i]
= rd_data_rise_1x_r[(rdd_i*DQ_PER_DQS)];
assign rd_data_rise_chk_q2[rdd_i]
= rd_data_rise_1x_r1[rdd_i];
assign rd_data_fall_chk_q1[rdd_i]
= rd_data_fall_1x_r[(rdd_i*DQ_PER_DQS)];
assign rd_data_fall_chk_q2[rdd_i]
= rd_data_fall_1x_r1[rdd_i];
end
endgenerate
 
//*****************************************************************
// Outputs of these simplified ISERDES circuits then feed MUXes based on
// which DQ the current calibration algorithm needs to look at
//*****************************************************************
 
// generate MUX control; assume that adding an extra pipeline stage isn't
// an issue - whatever stage cal logic is using output of MUX will wait
// enough time after changing it
always @(posedge clkdiv) begin
(* full_case, parallel_case *) case (calib_done[2:0])
3'b001: rdd_mux_sel <= next_count_dqs;
3'b011: rdd_mux_sel <= count_rden;
3'b111: rdd_mux_sel <= next_count_gate;
endcase
end
 
always @(posedge clkdiv) begin
rdd_rise_q1 <= rd_data_rise_chk_q1[rdd_mux_sel];
rdd_rise_q2 <= rd_data_rise_chk_q2[rdd_mux_sel];
rdd_fall_q1 <= rd_data_fall_chk_q1[rdd_mux_sel];
rdd_fall_q2 <= rd_data_fall_chk_q2[rdd_mux_sel];
end
 
//***************************************************************************
// Demultiplexor to control (reset, increment, decrement) IDELAY tap values
// For DQ:
// STG1: for per-bit-deskew, only inc/dec the current DQ. For non-per
// deskew, increment all bits in the current DQS set
// STG2: inc/dec all DQ's in the current DQS set.
// NOTE: Nice to add some error checking logic here (or elsewhere in the
// code) to check if logic attempts to overflow tap value
//***************************************************************************
 
// don't use DLYRST to reset value of IDELAY after reset. Need to change this
// if we want to allow user to recalibrate after initial reset
always @(posedge clkdiv)
if (rstdiv) begin
dlyrst_dq <= 1'b1;
dlyrst_dqs <= 1'b1;
end else begin
dlyrst_dq <= 1'b0;
dlyrst_dqs <= 1'b0;
end
 
always @(posedge clkdiv) begin
if (rstdiv) begin
dlyce_dq <= 'b0;
dlyinc_dq <= 'b0;
dlyce_dqs <= 'b0;
dlyinc_dqs <= 'b0;
end else begin
dlyce_dq <= 'b0;
dlyinc_dq <= 'b0;
dlyce_dqs <= 'b0;
dlyinc_dqs <= 'b0;
 
// stage 1 cal: change only specified DQ
if (cal1_dlyce_dq) begin
if (SIM_ONLY == 0) begin
dlyce_dq[count_dq] <= 1'b1;
dlyinc_dq[count_dq] <= cal1_dlyinc_dq;
end else begin
// if simulation, then calibrate only first DQ, apply results
// to all DQs (i.e. assume delay on all DQs is the same)
for (i = 0; i < DQ_WIDTH; i = i + 1) begin: loop_sim_dq_dly
dlyce_dq[i] <= 1'b1;
dlyinc_dq[i] <= cal1_dlyinc_dq;
end
end
end else if (cal2_dlyce_dqs) begin
// stage 2 cal: change DQS and all corresponding DQ's
if (SIM_ONLY == 0) begin
dlyce_dqs[count_dqs] <= 1'b1;
dlyinc_dqs[count_dqs] <= cal2_dlyinc_dqs;
for (i = 0; i < DQ_PER_DQS; i = i + 1) begin: loop_dqs_dly
dlyce_dq[(DQ_PER_DQS*count_dqs)+i] <= 1'b1;
dlyinc_dq[(DQ_PER_DQS*count_dqs)+i] <= cal2_dlyinc_dqs;
end
end else begin
for (i = 0; i < DQS_WIDTH; i = i + 1) begin: loop_sim_dqs_dly
// if simulation, then calibrate only first DQS
dlyce_dqs[i] <= 1'b1;
dlyinc_dqs[i] <= cal2_dlyinc_dqs;
for (j = 0; j < DQ_PER_DQS; j = j + 1) begin: loop_sim_dq_dqs_dly
dlyce_dq[(DQ_PER_DQS*i)+j] <= 1'b1;
dlyinc_dq[(DQ_PER_DQS*i)+j] <= cal2_dlyinc_dqs;
end
end
end
end else if (DEBUG_EN != 0) begin
// DEBUG: allow user to vary IDELAY tap settings
// For DQ IDELAY taps
if (dbg_idel_up_all || dbg_idel_down_all ||
dbg_sel_all_idel_dq) begin
for (x = 0; x < DQ_WIDTH; x = x + 1) begin: loop_dly_inc_dq
dlyce_dq[x] <= dbg_idel_up_all | dbg_idel_down_all |
dbg_idel_up_dq | dbg_idel_down_dq;
dlyinc_dq[x] <= dbg_idel_up_all | dbg_idel_up_dq;
end
end else begin
dlyce_dq <= 'b0;
dlyce_dq[dbg_sel_idel_dq] <= dbg_idel_up_dq |
dbg_idel_down_dq;
dlyinc_dq[dbg_sel_idel_dq] <= dbg_idel_up_dq;
end
// For DQS IDELAY taps
if (dbg_idel_up_all || dbg_idel_down_all ||
dbg_sel_all_idel_dqs) begin
for (x = 0; x < DQS_WIDTH; x = x + 1) begin: loop_dly_inc_dqs
dlyce_dqs[x] <= dbg_idel_up_all | dbg_idel_down_all |
dbg_idel_up_dqs | dbg_idel_down_dqs;
dlyinc_dqs[x] <= dbg_idel_up_all | dbg_idel_up_dqs;
end
end else begin
dlyce_dqs <= 'b0;
dlyce_dqs[dbg_sel_idel_dqs] <= dbg_idel_up_dqs |
dbg_idel_down_dqs;
dlyinc_dqs[dbg_sel_idel_dqs] <= dbg_idel_up_dqs;
end
end
end
end
 
// GATE synchronization is handled directly by Stage 4 calibration FSM
always @(posedge clkdiv)
if (rstdiv) begin
dlyrst_gate <= {DQS_WIDTH{1'b1}};
dlyce_gate <= {DQS_WIDTH{1'b0}};
dlyinc_gate <= {DQS_WIDTH{1'b0}};
end else begin
dlyrst_gate <= {DQS_WIDTH{1'b0}};
dlyce_gate <= {DQS_WIDTH{1'b0}};
dlyinc_gate <= {DQS_WIDTH{1'b0}};
 
if (cal4_dlyrst_gate) begin
if (SIM_ONLY == 0)
dlyrst_gate[count_gate] <= 1'b1;
else
for (i = 0; i < DQS_WIDTH; i = i + 1) begin: loop_gate_sim_dly_rst
dlyrst_gate[i] <= 1'b1;
end
end
 
if (cal4_dlyce_gate) begin
if (SIM_ONLY == 0) begin
dlyce_gate[count_gate] <= 1'b1;
dlyinc_gate[count_gate] <= cal4_dlyinc_gate;
end else begin
// if simulation, then calibrate only first gate
for (i = 0; i < DQS_WIDTH; i = i + 1) begin: loop_gate_sim_dly
dlyce_gate[i] <= 1'b1;
dlyinc_gate[i] <= cal4_dlyinc_gate;
end
end
end else if (DEBUG_EN != 0) begin
// DEBUG: allow user to vary IDELAY tap settings
if (dbg_idel_up_all || dbg_idel_down_all ||
dbg_sel_all_idel_gate) begin
for (x = 0; x < DQS_WIDTH; x = x + 1) begin: loop_dly_inc_gate
dlyce_gate[x] <= dbg_idel_up_all | dbg_idel_down_all |
dbg_idel_up_gate | dbg_idel_down_gate;
dlyinc_gate[x] <= dbg_idel_up_all | dbg_idel_up_gate;
end
end else begin
dlyce_gate <= {DQS_WIDTH{1'b0}};
dlyce_gate[dbg_sel_idel_gate] <= dbg_idel_up_gate |
dbg_idel_down_gate;
dlyinc_gate[dbg_sel_idel_gate] <= dbg_idel_up_gate;
end
end
end
 
//***************************************************************************
// signal to tell calibration state machines to wait and give IDELAY time to
// settle after it's value is changed (both time for IDELAY chain to settle,
// and for settled output to propagate through ISERDES). For general use: use
// for any calibration state machines that modify any IDELAY.
// Should give at least enough time for IDELAY output to settle (technically
// for V5, this should be "glitchless" when IDELAY taps are changed, so don't
// need any time here), and also time for new data to propagate through both
// ISERDES and the "RDD" MUX + associated pipelining
// For now, give very "generous" delay - doesn't really matter since only
// needed during calibration
//***************************************************************************
 
// determine if calibration polarity has changed
always @(posedge clkdiv)
cal2_rd_data_sel_r <= cal2_rd_data_sel;
 
assign cal2_rd_data_sel_edge = |(cal2_rd_data_sel ^ cal2_rd_data_sel_r);
 
// combine requests to modify any of the IDELAYs into one. Also when second
// stage capture "edge" polarity is changed (IDELAY isn't changed in this
// case, but use the same counter to stall cal logic)
assign dlyce_or = cal1_dlyce_dq |
cal2_dlyce_dqs |
cal2_rd_data_sel_edge |
cal4_dlyce_gate |
cal4_dlyrst_gate;
 
// SYN_NOTE: Can later recode to avoid combinational path
assign idel_set_wait = dlyce_or || (idel_set_cnt != IDEL_SET_VAL);
 
always @(posedge clkdiv)
if (rstdiv)
idel_set_cnt <= 4'b0000;
else if (dlyce_or)
idel_set_cnt <= 4'b0000;
else if (idel_set_cnt != IDEL_SET_VAL)
idel_set_cnt <= idel_set_cnt + 1;
 
// generate request to PHY_INIT logic to issue auto-refresh
// used by certain states to force prech/auto-refresh part way through
// calibration to avoid a tRAS violation (which will happen if that
// stage of calibration lasts long enough). This signal must meet the
// following requirements: (1) only transition from 0->1 when the refresh
// request is needed, (2) stay at 1 and only transition 1->0 when
// CALIB_REF_DONE is asserted
always @(posedge clkdiv)
if (rstdiv)
calib_ref_req <= 1'b0;
else
calib_ref_req <= cal1_ref_req | cal2_ref_req | cal4_ref_req;
 
// stage 1 calibration requests auto-refresh every 4 bits
generate
if (DQ_BITS < 2) begin: gen_cal1_refresh_dq_lte4
assign cal1_refresh = 1'b0;
end else begin: gen_cal1_refresh_dq_gt4
assign cal1_refresh = (next_count_dq[1:0] == 2'b00);
end
endgenerate
 
//***************************************************************************
// First stage calibration: DQ-DQS
// Definitions:
// edge: detected when varying IDELAY, and current capture data != prev
// capture data
// valid bit window: detected when current capture data == prev capture
// data for more than half the bit time
// starting conditions for DQS-DQ phase:
// case 1: when DQS starts somewhere in rising edge bit window, or
// on the right edge of the rising bit window.
// case 2: when DQS starts somewhere in falling edge bit window, or
// on the right edge of the falling bit window.
// Algorithm Description:
// 1. Increment DQ IDELAY until we find an edge.
// 2. While we're finding the first edge, note whether a valid bit window
// has been detected before we found an edge. If so, then figure out if
// this is the rising or falling bit window. If rising, then our starting
// DQS-DQ phase is case 1. If falling, then it's case 2. If don't detect
// a valid bit window, then we must have started on the edge of a window.
// Need to wait until later on to decide which case we are.
// - Store FIRST_EDGE IDELAY value
// 3. Now look for second edge.
// 4. While we're finding the second edge, note whether valid bit window
// is detected. If so, then use to, along with results from (2) to figure
// out what the starting case is. If in rising bit window, then we're in
// case 2. If falling, then case 1.
// - Store SECOND_EDGE IDELAY value
// NOTES:
// a. Finding two edges allows us to calculate the bit time (although
// not the "same" bit time polarity - need to investigate this
// more).
// b. If we run out of taps looking for the second edge, then the bit
// time must be too long (>= 2.5ns, and DQS-DQ starting phase must be
// case 1).
// 5. Calculate absolute amount to delay DQ as:
// If second edge found, and case 1:
// - DQ_IDELAY = FIRST_EDGE - 0.5*(SECOND_EDGE - FIRST_EDGE)
// If second edge found, and case 2:
// - DQ_IDELAY = SECOND_EDGE - 0.5*(SECOND_EDGE - FIRST_EDGE)
// If second edge not found, then need to make an approximation on
// how much to shift by (should be okay, because we have more timing
// margin):
// - DQ_IDELAY = FIRST_EDGE - 0.5 * (bit_time)
// NOTE: Does this account for either case 1 or case 2?????
// NOTE: It's also possible even when we find the second edge, that
// to instead just use half the bit time to subtract from either
// FIRST or SECOND_EDGE. Finding the actual bit time (which is
// what (SECOND_EDGE - FIRST_EDGE) is, is slightly more accurate,
// since it takes into account duty cycle distortion.
// 6. Repeat for each DQ in current DQS set.
//***************************************************************************
 
//*****************************************************************
// for first stage calibration - used for checking if DQS is aligned to the
// particular DQ, such that we're in the data valid window. Basically, this
// is one giant MUX.
// = [falling data, rising data]
// = [0, 1] = rising DQS aligned in proper (rising edge) bit window
// = [1, 0] = rising DQS aligned in wrong (falling edge) bit window
// = [0, 0], or [1,1] = in uncertain region between windows
//*****************************************************************
 
// SYN_NOTE: May have to split this up into multiple levels - MUX can get
// very wide - as wide as the data bus width
always @(posedge clkdiv)
cal1_data_chk_r <= {rd_data_fall_1x_r[next_count_dq],
rd_data_rise_1x_r[next_count_dq]};
 
//*****************************************************************
// determine when an edge has occurred - when either the current value
// is different from the previous latched value or when the DATA_CHK
// outputs are the same (rare, but indicates that we're at an edge)
// This is only valid when the IDELAY output and propagation of the
// data through the capture flops has had a chance to settle out.
//*****************************************************************
 
// write CAL1_DETECT_EDGE and CAL1_DETECT_STABLE in such a way that
// if X's are captured on the bus during functional simulation, that
// the logic will register this as an edge detected. Do this to allow
// use of this HDL with Denali memory models (Denali models drive DQ
// to X's on both edges of the data valid window to simulate jitter)
// This is only done for functional simulation purposes. **Should not**
// make the final synthesized logic more complicated, but it does make
// the HDL harder to understand b/c we have to "phrase" the logic
// slightly differently than when not worrying about X's
always @(*) begin
// no edge found if: (1) we have recorded prev edge, and rise
// data == fall data, (2) we haven't yet recorded prev edge, but
// rise/fall data is equal to either [0,1] or [1,0] (i.e. rise/fall
// data isn't either X's, or [0,0] or [1,1], which indicates we're
// in the middle of an edge, since normally rise != fall data for stg1)
if ((cal1_data_chk_last_valid &&
(cal1_data_chk_r == cal1_data_chk_last)) ||
(!cal1_data_chk_last_valid &&
((cal1_data_chk_r == 2'b01) || (cal1_data_chk_r == 2'b10))))
cal1_detect_edge = 1'b0;
else
cal1_detect_edge = 1'b1;
end
 
always @(*) begin
// assert if we've found a region where data valid window is stable
// over consecutive IDELAY taps, and either rise/fall = [1,0], or [0,1]
if ((cal1_data_chk_last_valid &&
(cal1_data_chk_r == cal1_data_chk_last)) &&
((cal1_data_chk_r == 2'b01) || (cal1_data_chk_r == 2'b10)))
cal1_detect_stable <= 1'b1;
else
cal1_detect_stable <= 1'b0;
end
 
//*****************************************************************
// Find valid window: keep track of how long we've been in the same data
// window. If it's been long enough, then declare that we've found a valid
// window. Also returns whether we found a rising or falling window (only
// valid when found_window is asserted)
//*****************************************************************
 
always @(posedge clkdiv) begin
if (cal1_state == CAL1_INIT) begin
cal1_window_cnt <= 4'b0000;
cal1_found_window <= 1'b0;
cal1_found_rising <= 1'bx;
end else if (!cal1_data_chk_last_valid) begin
// if we haven't stored a previous value of CAL1_DATA_CHK (or it got
// invalidated because we detected an edge, and are now looking for the
// second edge), then make sure FOUND_WINDOW deasserted on following
// clock edge (to avoid finding a false window immediately after finding
// an edge). Note that because of jitter, it's possible to not find an
// edge at the end of the IDELAY increment settling time, but to find an
// edge on the next clock cycle (e.g. during CAL1_FIND_FIRST_EDGE)
cal1_window_cnt <= 4'b0000;
cal1_found_window <= 1'b0;
cal1_found_rising <= 1'bx;
end else if (((cal1_state == CAL1_FIRST_EDGE_IDEL_WAIT) ||
(cal1_state == CAL1_SECOND_EDGE_IDEL_WAIT)) &&
!idel_set_wait) begin
// while finding the first and second edges, see if we can detect a
// stable bit window (occurs over MIN_WIN_SIZE number of taps). If
// so, then we're away from an edge, and can conclusively determine the
// starting DQS-DQ phase.
if (cal1_detect_stable) begin
cal1_window_cnt <= cal1_window_cnt + 1;
if (cal1_window_cnt == MIN_WIN_SIZE-1) begin
cal1_found_window <= 1'b1;
if (cal1_data_chk_r == 2'b01)
cal1_found_rising <= 1'b1;
else
cal1_found_rising <= 1'b0;
end
end else begin
// otherwise, we're not in a data valid window, reset the window
// counter, and indicate we're not currently in window. This should
// happen by design at least once after finding the first edge.
cal1_window_cnt <= 4'b0000;
cal1_found_window <= 1'b0;
cal1_found_rising <= 1'bx;
end
end
end
 
//*****************************************************************
// keep track of edge tap counts found, and whether we've
// incremented to the maximum number of taps allowed
//*****************************************************************
 
always @(posedge clkdiv)
if (cal1_state == CAL1_INIT) begin
cal1_idel_tap_limit_hit <= 1'b0;
cal1_idel_tap_cnt <= 6'b000000;
end else if (cal1_dlyce_dq) begin
if (cal1_dlyinc_dq) begin
cal1_idel_tap_cnt <= cal1_idel_tap_cnt + 1;
cal1_idel_tap_limit_hit <= (cal1_idel_tap_cnt == 6'b111110);
end else begin
cal1_idel_tap_cnt <= cal1_idel_tap_cnt - 1;
cal1_idel_tap_limit_hit <= 1'b0;
end
end
 
//*****************************************************************
// Pipeline for better timing - amount to decrement by if second
// edge not found
//*****************************************************************
// if only one edge found (possible for low frequencies), then:
// 1. Assume starting DQS-DQ phase has DQS in DQ window (aka "case 1")
// 2. We have to decrement by (63 - first_edge_tap_cnt) + (BIT_TIME_TAPS/2)
// (i.e. decrement by 63-first_edge_tap_cnt to get to right edge of
// DQ window. Then decrement again by (BIT_TIME_TAPS/2) to get to center
// of DQ window.
// 3. Clamp the above value at 63 to ensure we don't underflow IDELAY
// (note: clamping happens in the CAL1 state machine)
always @(posedge clkdiv)
cal1_low_freq_idel_dec
<= (7'b0111111 - {1'b0, cal1_first_edge_tap_cnt}) +
(BIT_TIME_TAPS/2);
 
//*****************************************************************
// Keep track of max taps used during stage 1, use this to limit
// the number of taps that can be used in stage 2
//*****************************************************************
 
always @(posedge clkdiv)
if (rstdiv) begin
cal1_idel_max_tap <= 6'b000000;
cal1_idel_max_tap_we <= 1'b0;
end else begin
// pipeline latch enable for CAL1_IDEL_MAX_TAP - we have plenty
// of time, tap count gets updated, then dead cycles waiting for
// IDELAY output to settle
cal1_idel_max_tap_we <= (cal1_idel_max_tap < cal1_idel_tap_cnt);
// record maximum # of taps used for stg 1 cal
if ((cal1_state == CAL1_DONE) && cal1_idel_max_tap_we)
cal1_idel_max_tap <= cal1_idel_tap_cnt;
end
 
//*****************************************************************
 
always @(posedge clkdiv)
if (rstdiv) begin
calib_done[0] <= 1'b0;
calib_done_tmp[0] <= 1'bx;
calib_err[0] <= 1'b0;
count_dq <= {DQ_BITS{1'b0}};
next_count_dq <= {DQ_BITS{1'b0}};
cal1_bit_time_tap_cnt <= 6'bxxxxxx;
cal1_data_chk_last <= 2'bxx;
cal1_data_chk_last_valid <= 1'bx;
cal1_dlyce_dq <= 1'b0;
cal1_dlyinc_dq <= 1'b0;
cal1_dqs_dq_init_phase <= 1'bx;
cal1_first_edge_done <= 1'bx;
cal1_found_second_edge <= 1'bx;
cal1_first_edge_tap_cnt <= 6'bxxxxxx;
cal1_idel_dec_cnt <= 7'bxxxxxxx;
cal1_idel_inc_cnt <= 6'bxxxxxx;
cal1_ref_req <= 1'b0;
cal1_state <= CAL1_IDLE;
end else begin
// default values for all "pulse" outputs
cal1_ref_req <= 1'b0;
cal1_dlyce_dq <= 1'b0;
cal1_dlyinc_dq <= 1'b0;
 
case (cal1_state)
CAL1_IDLE: begin
count_dq <= {DQ_BITS{1'b0}};
next_count_dq <= {DQ_BITS{1'b0}};
if (calib_start[0]) begin
calib_done[0] <= 1'b0;
calib_done_tmp[0] <= 1'b0;
cal1_state <= CAL1_INIT;
end
end
 
CAL1_INIT: begin
cal1_data_chk_last_valid <= 1'b0;
cal1_found_second_edge <= 1'b0;
cal1_dqs_dq_init_phase <= 1'b0;
cal1_idel_inc_cnt <= 6'b000000;
cal1_state <= CAL1_INC_IDEL;
end
 
// increment DQ IDELAY so that either: (1) DQS starts somewhere in
// first rising DQ window, or (2) DQS starts in first falling DQ
// window. The amount to shift is frequency dependent (and is either
// precalculated by MIG or possibly adjusted by the user)
CAL1_INC_IDEL:
if ((cal1_idel_inc_cnt == DQ_IDEL_INIT) && !idel_set_wait) begin
cal1_state <= CAL1_FIND_FIRST_EDGE;
end else if (cal1_idel_inc_cnt != DQ_IDEL_INIT) begin
cal1_idel_inc_cnt <= cal1_idel_inc_cnt + 1;
cal1_dlyce_dq <= 1'b1;
cal1_dlyinc_dq <= 1'b1;
end
 
// look for first edge
CAL1_FIND_FIRST_EDGE: begin
// Determine DQS-DQ phase if we can detect enough of a valid window
if (cal1_found_window)
cal1_dqs_dq_init_phase <= ~cal1_found_rising;
// find first edge - if found then record position
if (cal1_detect_edge) begin
cal1_state <= CAL1_FOUND_FIRST_EDGE_WAIT;
cal1_first_edge_done <= 1'b0;
cal1_first_edge_tap_cnt <= cal1_idel_tap_cnt;
cal1_data_chk_last_valid <= 1'b0;
end else begin
// otherwise, store the current value of DATA_CHK, increment
// DQ IDELAY, and compare again
cal1_state <= CAL1_FIRST_EDGE_IDEL_WAIT;
cal1_data_chk_last <= cal1_data_chk_r;
// avoid comparing against DATA_CHK_LAST for previous iteration
cal1_data_chk_last_valid <= 1'b1;
cal1_dlyce_dq <= 1'b1;
cal1_dlyinc_dq <= 1'b1;
end
end
 
// wait for DQ IDELAY to settle
CAL1_FIRST_EDGE_IDEL_WAIT:
if (!idel_set_wait)
cal1_state <= CAL1_FIND_FIRST_EDGE;
 
// delay state between finding first edge and looking for second
// edge. Necessary in order to invalidate CAL1_FOUND_WINDOW before
// starting to look for second edge
CAL1_FOUND_FIRST_EDGE_WAIT:
cal1_state <= CAL1_FIND_SECOND_EDGE;
 
// Try and find second edge
CAL1_FIND_SECOND_EDGE: begin
// When looking for 2nd edge, first make sure data stabilized (by
// detecting valid data window) - needed to avoid false edges
if (cal1_found_window) begin
cal1_first_edge_done <= 1'b1;
cal1_dqs_dq_init_phase <= cal1_found_rising;
end
// exit if run out of taps to increment
if (cal1_idel_tap_limit_hit)
cal1_state <= CAL1_CALC_IDEL;
else begin
// found second edge, record the current edge count
if (cal1_first_edge_done && cal1_detect_edge) begin
cal1_state <= CAL1_CALC_IDEL;
cal1_found_second_edge <= 1'b1;
cal1_bit_time_tap_cnt <= cal1_idel_tap_cnt -
cal1_first_edge_tap_cnt + 1;
end else begin
cal1_state <= CAL1_SECOND_EDGE_IDEL_WAIT;
cal1_data_chk_last <= cal1_data_chk_r;
cal1_data_chk_last_valid <= 1'b1;
cal1_dlyce_dq <= 1'b1;
cal1_dlyinc_dq <= 1'b1;
end
end
end
 
// wait for DQ IDELAY to settle, then store ISERDES output
CAL1_SECOND_EDGE_IDEL_WAIT:
if (!idel_set_wait)
cal1_state <= CAL1_FIND_SECOND_EDGE;
 
// pipeline delay state to calculate amount to decrement DQ IDELAY
// NOTE: We're calculating the amount to decrement by, not the
// absolute setting for DQ IDELAY
CAL1_CALC_IDEL: begin
// if two edges found
if (cal1_found_second_edge)
// case 1: DQS was in DQ window to start with. First edge found
// corresponds to left edge of DQ rising window. Backup by 1.5*BT
// NOTE: In this particular case, it is possible to decrement
// "below 0" in the case where DQS delay is less than 0.5*BT,
// need to limit decrement to prevent IDELAY tap underflow
if (!cal1_dqs_dq_init_phase)
cal1_idel_dec_cnt <= {1'b0, cal1_bit_time_tap_cnt} +
{1'b0, (cal1_bit_time_tap_cnt >> 1)};
// case 2: DQS was in wrong DQ window (in DQ falling window).
// First edge found is right edge of DQ rising window. Second
// edge is left edge of DQ rising window. Backup by 0.5*BT
else
cal1_idel_dec_cnt <= {1'b0, (cal1_bit_time_tap_cnt >> 1)};
// if only one edge found - assume will always be case 1 - DQS in
// DQS window. Case 2 only possible if path delay on DQS > 5ns
else
cal1_idel_dec_cnt <= cal1_low_freq_idel_dec;
cal1_state <= CAL1_DEC_IDEL;
end
 
// decrement DQ IDELAY for final adjustment
CAL1_DEC_IDEL:
// once adjustment is complete, we're done with calibration for
// this DQ, now return to IDLE state and repeat for next DQ
// Add underflow protection for case of 2 edges found and DQS
// starting in DQ window (see comments for above state) - note we
// have to take into account delayed value of CAL1_IDEL_TAP_CNT -
// gets updated one clock cycle after CAL1_DLYCE/INC_DQ
if ((cal1_idel_dec_cnt == 7'b0000000) ||
(cal1_dlyce_dq && (cal1_idel_tap_cnt == 6'b000001))) begin
cal1_state <= CAL1_DONE;
// stop when all DQ's calibrated, or DQ[0] cal'ed (for sim)
if ((count_dq == DQ_WIDTH-1) || (SIM_ONLY != 0))
calib_done_tmp[0] <= 1'b1;
else
// need for VHDL simulation to prevent out-of-index error
next_count_dq <= count_dq + 1;
end else begin
// keep decrementing until final tap count reached
cal1_idel_dec_cnt <= cal1_idel_dec_cnt - 1;
cal1_dlyce_dq <= 1'b1;
cal1_dlyinc_dq <= 1'b0;
end
 
// delay state to allow count_dq and DATA_CHK to point to the next
// DQ bit (allows us to potentially begin checking for an edge on
// next DQ right away).
CAL1_DONE:
if (!idel_set_wait) begin
count_dq <= next_count_dq;
if (calib_done_tmp[0]) begin
calib_done[0] <= 1'b1;
cal1_state <= CAL1_IDLE;
end else begin
// request auto-refresh after every 8-bits calibrated to
// avoid tRAS violation
if (cal1_refresh) begin
cal1_ref_req <= 1'b1;
if (calib_ref_done)
cal1_state <= CAL1_INIT;
end else
// if no need this time for refresh, proceed to next bit
cal1_state <= CAL1_INIT;
end
end
endcase
end
 
//***************************************************************************
// Second stage calibration: DQS-FPGA Clock
// Algorithm Description:
// 1. Assumes a training pattern that will produce a pattern oscillating at
// half the core clock frequency each on rise and fall outputs, and such
// that rise and fall outputs are 180 degrees out of phase from each
// other. Note that since the calibration logic runs at half the speed
// of the interface, expect that data sampled with the slow clock always
// to be constant (either always = 1, or = 0, and rise data != fall data)
// unless we cross the edge of the data valid window
// 2. Start by setting RD_DATA_SEL = 0. This selects the rising capture data
// sync'ed to rising edge of core clock, and falling edge data sync'ed
// to falling edge of core clock
// 3. Start looking for an edge. An edge is defined as either: (1) a
// change in capture value or (2) an invalid capture value (e.g. rising
// data != falling data for that same clock cycle).
// 4. If an edge is found, go to step (6). If edge hasn't been found, then
// set RD_DATA_SEL = 1, and try again.
// 5. If no edge is found, then increment IDELAY and return to step (3)
// 6. If an edge if found, then invert RD_DATA_SEL - this shifts the
// capture point 180 degrees from the edge of the window (minus duty
// cycle distortion, delay skew between rising/falling edge capture
// paths, etc.)
// 7. If no edge is found by CAL2_IDEL_TAP_LIMIT (= 63 - # taps used for
// stage 1 calibration), then decrement IDELAY (without reinverting
// RD_DATA_SEL) by CAL2_IDEL_TAP_LIMIT/2. This guarantees we at least
// have CAL2_IDEL_TAP_LIMIT/2 of slack both before and after the
// capture point (not optimal, but best we can do not having found an
// of the window). This happens only for very low frequencies.
// 8. Repeat for each DQS group.
// NOTE: Step 6 is not optimal. A better (and perhaps more complicated)
// algorithm might be to find both edges of the data valid window (using
// the same polarity of RD_DATA_SEL), and then decrement to the midpoint.
//***************************************************************************
 
// RD_DATA_SEL should be tagged with FROM-TO (multi-cycle) constraint in
// UCF file to relax timing. This net is "pseudo-static" (after value is
// changed, FSM waits number of cycles before using the output).
// Note that we are adding one clock cycle of delay (to isolate it from
// the other logic CAL2_RD_DATA_SEL feeds), make sure FSM waits long
// enough to compensate (by default it does, it waits a few cycles more
// than minimum # of clock cycles)
genvar rd_i;
generate
for (rd_i = 0; rd_i < DQS_WIDTH; rd_i = rd_i+1) begin: gen_rd_data_sel
FDRSE u_ff_rd_data_sel
(
.Q (rd_data_sel[rd_i]),
.C (clkdiv),
.CE (1'b1),
.D (cal2_rd_data_sel[rd_i]),
.R (1'b0),
.S (1'b0)
) /* synthesis syn_preserve = 1 */
/* synthesis syn_replicate = 0 */;
end
endgenerate
 
//*****************************************************************
// Max number of taps used for stg2 cal dependent on number of taps
// used for stg1 (give priority to stg1 cal - let it use as many
// taps as it needs - the remainder of the IDELAY taps can be used
// by stg2)
//*****************************************************************
 
always @(posedge clkdiv)
cal2_idel_tap_limit <= 6'b111111 - cal1_idel_max_tap;
 
//*****************************************************************
// second stage calibration uses readback pattern of "1100" (i.e.
// 1st rising = 1, 1st falling = 1, 2nd rising = 0, 2nd falling = 0)
// only look at the first bit of each DQS group
//*****************************************************************
 
// deasserted when captured data has changed since IDELAY was
// incremented, or when we're right on the edge (i.e. rise data =
// fall data).
assign cal2_detect_edge =
((((rdd_rise_q1 != cal2_rd_data_rise_last_pos) ||
(rdd_fall_q1 != cal2_rd_data_fall_last_pos)) &&
cal2_rd_data_last_valid_pos && (!cal2_curr_sel)) ||
(((rdd_rise_q1 != cal2_rd_data_rise_last_neg) ||
(rdd_fall_q1 != cal2_rd_data_fall_last_neg)) &&
cal2_rd_data_last_valid_neg && (cal2_curr_sel)) ||
(rdd_rise_q1 != rdd_fall_q1));
 
//*****************************************************************
// keep track of edge tap counts found, and whether we've
// incremented to the maximum number of taps allowed
// NOTE: Assume stage 2 cal always increments the tap count (never
// decrements) when searching for edge of the data valid window
//*****************************************************************
 
always @(posedge clkdiv)
if (cal2_state == CAL2_INIT) begin
cal2_idel_tap_limit_hit <= 1'b0;
cal2_idel_tap_cnt <= 6'b000000;
end else if (cal2_dlyce_dqs) begin
cal2_idel_tap_cnt <= cal2_idel_tap_cnt + 1;
cal2_idel_tap_limit_hit <= (cal2_idel_tap_cnt ==
cal2_idel_tap_limit - 1);
end
 
//*****************************************************************
 
always @(posedge clkdiv)
if (rstdiv) begin
calib_done[1] <= 1'b0;
calib_done_tmp[1] <= 1'bx;
calib_err[1] <= 1'b0;
count_dqs <= 'b0;
next_count_dqs <= 'b0;
cal2_dlyce_dqs <= 1'b0;
cal2_dlyinc_dqs <= 1'b0;
cal2_idel_dec_cnt <= 6'bxxxxxx;
cal2_rd_data_last_valid_neg <= 1'bx;
cal2_rd_data_last_valid_pos <= 1'bx;
cal2_rd_data_sel <= 'b0;
cal2_ref_req <= 1'b0;
cal2_state <= CAL2_IDLE;
end else begin
cal2_ref_req <= 1'b0;
cal2_dlyce_dqs <= 1'b0;
cal2_dlyinc_dqs <= 1'b0;
 
case (cal2_state)
CAL2_IDLE: begin
count_dqs <= 'b0;
next_count_dqs <= 'b0;
if (calib_start[1]) begin
cal2_rd_data_sel <= {DQS_WIDTH{1'b0}};
calib_done[1] <= 1'b0;
calib_done_tmp[1] <= 1'b0;
cal2_state <= CAL2_INIT;
end
end
 
// Pass through this state every time we calibrate a new DQS group
CAL2_INIT: begin
cal2_curr_sel <= 1'b0;
cal2_rd_data_last_valid_neg <= 1'b0;
cal2_rd_data_last_valid_pos <= 1'b0;
cal2_state <= CAL2_INIT_IDEL_WAIT;
end
 
// Stall state only used if calibration run more than once. Can take
// this state out if design never runs calibration more than once.
// We need this state to give time for MUX'ed data to settle after
// resetting RD_DATA_SEL
CAL2_INIT_IDEL_WAIT:
if (!idel_set_wait)
cal2_state <= CAL2_FIND_EDGE_POS;
 
// Look for an edge - first check "positive-edge" stage 2 capture
CAL2_FIND_EDGE_POS: begin
// if found an edge, then switch to the opposite edge stage 2
// capture and we're done - no need to decrement the tap count,
// since switching to the opposite edge will shift the capture
// point by 180 degrees
if (cal2_detect_edge) begin
cal2_curr_sel <= 1'b1;
cal2_state <= CAL2_DONE;
// set all DQS groups to be the same for simulation
if (SIM_ONLY != 0)
cal2_rd_data_sel <= {DQS_WIDTH{1'b1}};
else
cal2_rd_data_sel[count_dqs] <= 1'b1;
if ((count_dqs == DQS_WIDTH-1) || (SIM_ONLY != 0))
calib_done_tmp[1] <= 1'b1;
else
// MIG 2.1: Fix for simulation out-of-bounds error when
// SIM_ONLY=0, and DQS_WIDTH=(power of 2) (needed for VHDL)
next_count_dqs <= count_dqs + 1;
end else begin
// otherwise, invert polarity of stage 2 capture and look for
// an edge with opposite capture clock polarity
cal2_curr_sel <= 1'b1;
cal2_rd_data_sel[count_dqs] <= 1'b1;
cal2_state <= CAL2_FIND_EDGE_IDEL_WAIT_POS;
cal2_rd_data_rise_last_pos <= rdd_rise_q1;
cal2_rd_data_fall_last_pos <= rdd_fall_q1;
cal2_rd_data_last_valid_pos <= 1'b1;
end
end
 
// Give time to switch from positive-edge to negative-edge second
// stage capture (need time for data to filter though pipe stages)
CAL2_FIND_EDGE_IDEL_WAIT_POS:
if (!idel_set_wait)
cal2_state <= CAL2_FIND_EDGE_NEG;
 
// Look for an edge - check "negative-edge" stage 2 capture
CAL2_FIND_EDGE_NEG:
if (cal2_detect_edge) begin
cal2_curr_sel <= 1'b0;
cal2_state <= CAL2_DONE;
// set all DQS groups to be the same for simulation
if (SIM_ONLY != 0)
cal2_rd_data_sel <= {DQS_WIDTH{1'b0}};
else
cal2_rd_data_sel[count_dqs] <= 1'b0;
if ((count_dqs == DQS_WIDTH-1) || (SIM_ONLY != 0))
calib_done_tmp[1] <= 1'b1;
else
// MIG 2.1: Fix for simulation out-of-bounds error when
// SIM_ONLY=0, and DQS_WIDTH=(power of 2) (needed for VHDL)
next_count_dqs <= count_dqs + 1;
end else if (cal2_idel_tap_limit_hit) begin
// otherwise, if we've run out of taps, then immediately
// backoff by half # of taps used - that's our best estimate
// for optimal calibration point. Doesn't matter whether which
// polarity we're using for capture (we don't know which one is
// best to use)
cal2_idel_dec_cnt <= {1'b0, cal2_idel_tap_limit[5:1]};
cal2_state <= CAL2_DEC_IDEL;
if ((count_dqs == DQS_WIDTH-1) || (SIM_ONLY != 0))
calib_done_tmp[1] <= 1'b1;
else
// MIG 2.1: Fix for simulation out-of-bounds error when
// SIM_ONLY=0, and DQS_WIDTH=(power of 2) (needed for VHDL)
next_count_dqs <= count_dqs + 1;
end else begin
// otherwise, increment IDELAY, and start looking for edge again
cal2_curr_sel <= 1'b0;
cal2_rd_data_sel[count_dqs] <= 1'b0;
cal2_state <= CAL2_FIND_EDGE_IDEL_WAIT_NEG;
cal2_rd_data_rise_last_neg <= rdd_rise_q1;
cal2_rd_data_fall_last_neg <= rdd_fall_q1;
cal2_rd_data_last_valid_neg <= 1'b1;
cal2_dlyce_dqs <= 1'b1;
cal2_dlyinc_dqs <= 1'b1;
end
 
CAL2_FIND_EDGE_IDEL_WAIT_NEG:
if (!idel_set_wait)
cal2_state <= CAL2_FIND_EDGE_POS;
 
// if no edge found, then decrement by half # of taps used
CAL2_DEC_IDEL: begin
if (cal2_idel_dec_cnt == 6'b000000)
cal2_state <= CAL2_DONE;
else begin
cal2_idel_dec_cnt <= cal2_idel_dec_cnt - 1;
cal2_dlyce_dqs <= 1'b1;
cal2_dlyinc_dqs <= 1'b0;
end
end
 
// delay state to allow count_dqs and ISERDES data to point to next
// DQ bit (DQS group) before going to INIT
CAL2_DONE:
if (!idel_set_wait) begin
count_dqs <= next_count_dqs;
if (calib_done_tmp[1]) begin
calib_done[1] <= 1'b1;
cal2_state <= CAL2_IDLE;
end else begin
// request auto-refresh after every DQS group calibrated to
// avoid tRAS violation
cal2_ref_req <= 1'b1;
if (calib_ref_done)
cal2_state <= CAL2_INIT;
end
end
endcase
end
 
//***************************************************************************
// Stage 3 calibration: Read Enable
// Description:
// read enable calibration determines the "round-trip" time (in # of CLK0
// cycles) between when a read command is issued by the controller, and
// when the corresponding read data is synchronized by into the CLK0 domain
// this is a long delay chain to delay read enable signal from controller/
// initialization logic (i.e. this is used for both initialization and
// during normal controller operation). Stage 3 calibration logic decides
// which delayed version is appropriate to use (which is affected by the
// round trip delay of DQ/DQS) as a "valid" signal to tell rest of logic
// when the captured data output from ISERDES is valid.
//***************************************************************************
 
//*****************************************************************
// Delay chains: Use shift registers
// Two sets of delay chains are used:
// 1. One to delay RDEN from PHY_INIT module for calibration
// purposes (delay required for RDEN for calibration is different
// than during normal operation)
// 2. One per DQS group to delay RDEN from controller for normal
// operation - the value to delay for each DQS group can be different
// as is determined during calibration
//*****************************************************************
 
//*****************************************************************
// First delay chain, use only for calibration
// input = asserted on rising edge of RDEN from PHY_INIT module
//*****************************************************************
 
always @(posedge clk) begin
ctrl_rden_r <= ctrl_rden;
phy_init_rden_r <= phy_init_rden;
phy_init_rden_r1 <= phy_init_rden_r;
calib_rden_edge_r <= phy_init_rden_r & ~phy_init_rden_r1;
end
 
// Calibration shift register used for both Stage 3 and Stage 4 cal
// (not strictly necessary for stage 4, but use as an additional check
// to make sure we're checking for correct data on the right clock cycle)
always @(posedge clkdiv)
if (!calib_done[2])
calib_rden_srl_a <= cal3_rden_srl_a;
else
calib_rden_srl_a <= cal4_rden_srl_a;
 
// Flops for targetting of multi-cycle path in UCF
genvar cal_rden_ff_i;
generate
for (cal_rden_ff_i = 0; cal_rden_ff_i < 5;
cal_rden_ff_i = cal_rden_ff_i+1) begin: gen_cal_rden_dly
FDRSE u_ff_cal_rden_dly
(
.Q (calib_rden_srl_a_r[cal_rden_ff_i]),
.C (clkdiv),
.CE (1'b1),
.D (calib_rden_srl_a[cal_rden_ff_i]),
.R (1'b0),
.S (1'b0)
) /* synthesis syn_preserve = 1 */
/* synthesis syn_replicate = 0 */;
end
endgenerate
 
SRLC32E u_calib_rden_srl
(
.Q (calib_rden_srl_out),
.Q31 (),
.A (calib_rden_srl_a_r),
.CE (1'b1),
.CLK (clk),
.D (calib_rden_edge_r)
);
 
FDRSE u_calib_rden_srl_out_r
(
.Q (calib_rden_srl_out_r),
.C (clk),
.CE (1'b1),
.D (calib_rden_srl_out),
.R (1'b0),
.S (1'b0)
) /* synthesis syn_preserve = 1 */;
 
// convert to CLKDIV domain. Two version are generated because we need
// to be able to tell exactly which fast (clk) clock cycle the read
// enable was asserted in. Only one of CALIB_DATA_VALID or
// CALIB_DATA_VALID_STGD will be asserted for any given shift value
always @(posedge clk)
calib_rden_srl_out_r1 <= calib_rden_srl_out_r;
 
always @(posedge clkdiv) begin
calib_rden_valid <= calib_rden_srl_out_r;
calib_rden_valid_stgd <= calib_rden_srl_out_r1;
end
 
//*****************************************************************
// Second set of delays chain, use for normal reads
// input = RDEN from controller
//*****************************************************************
 
// Flops for targetting of multi-cycle path in UCF
genvar rden_ff_i;
generate
for (rden_ff_i = 0; rden_ff_i < 5*DQS_WIDTH;
rden_ff_i = rden_ff_i+1) begin: gen_rden_dly
FDRSE u_ff_rden_dly
(
.Q (rden_dly_r[rden_ff_i]),
.C (clkdiv),
.CE (1'b1),
.D (rden_dly[rden_ff_i]),
.R (1'b0),
.S (1'b0)
) /* synthesis syn_preserve = 1 */
/* synthesis syn_replicate = 0 */;
end
endgenerate
 
// NOTE: Comment this section explaining purpose of SRL's
genvar rden_i;
generate
for (rden_i = 0; rden_i < DQS_WIDTH; rden_i = rden_i + 1) begin: gen_rden
SRLC32E u_rden_srl
(
.Q (rden_srl_out[rden_i]),
.Q31 (),
.A ({rden_dly_r[(rden_i*5)+4],
rden_dly_r[(rden_i*5)+3],
rden_dly_r[(rden_i*5)+2],
rden_dly_r[(rden_i*5)+1],
rden_dly_r[(rden_i*5)]}),
.CE (1'b1),
.CLK (clk),
.D (ctrl_rden_r)
);
FDRSE u_calib_rden_r
(
.Q (calib_rden[rden_i]),
.C (clk),
.CE (1'b1),
.D (rden_srl_out[rden_i]),
.R (1'b0),
.S (1'b0)
) /* synthesis syn_preserve = 1 */;
end
endgenerate
 
//*****************************************************************
// indicates that current received data is the correct pattern. Check both
// rising and falling data for first DQ in each DQS group. Note that
// we're checking using a pipelined version of read data, so need to take
// this inherent delay into account in determining final read valid delay
// Data is written to the memory in the following order (first -> last):
// 0x1, 0xE, 0xE, 0x1, 0x1, 0xE, 0xE, 0x1
// Looking just at LSb, expect data in sequence (in binary):
// 1, 0, 0, 1, 1, 0, 0, 1
// Check for the presence of the first 7 words, and compensate read valid
// delay accordingly. Don't check last falling edge data, it may be
// corrupted by the DQS tri-state glitch at end of read postamble
// (glitch protection not yet active until stage 4 cal)
//*****************************************************************
 
always @(posedge clkdiv) begin
rdd_rise_q1_r <= rdd_rise_q1;
rdd_fall_q1_r <= rdd_fall_q1;
rdd_rise_q2_r <= rdd_rise_q2;
rdd_fall_q2_r <= rdd_fall_q2;
rdd_rise_q1_r1 <= rdd_rise_q1_r;
rdd_fall_q1_r1 <= rdd_fall_q1_r;
end
 
always @(posedge clkdiv) begin
// For the following sequence from memory:
// rise[0], fall[0], rise[1], fall[1]
// if data is aligned out of fabric ISERDES:
// RDD_RISE_Q2 = rise[0]
// RDD_FALL_Q2 = fall[0]
// RDD_RISE_Q1 = rise[1]
// RDD_FALL_Q1 = fall[1]
cal3_data_match <= ((rdd_rise_q2_r == 1) &&
(rdd_fall_q2_r == 0) &&
(rdd_rise_q1_r == 0) &&
(rdd_fall_q1_r == 1) &&
(rdd_rise_q2 == 1) &&
(rdd_fall_q2 == 0) &&
(rdd_rise_q1 == 0));
 
// if data is staggered out of fabric ISERDES:
// RDD_RISE_Q1_R = rise[0]
// RDD_FALL_Q1_R = fall[0]
// RDD_RISE_Q2 = rise[1]
// RDD_FALL_Q2 = fall[1]
cal3_data_match_stgd <= ((rdd_rise_q1_r1 == 1) &&
(rdd_fall_q1_r1 == 0) &&
(rdd_rise_q2_r == 0) &&
(rdd_fall_q2_r == 1) &&
(rdd_rise_q1_r == 1) &&
(rdd_fall_q1_r == 0) &&
(rdd_rise_q2 == 0));
end
 
assign cal3_rden_dly = cal3_rden_srl_a - CAL3_RDEN_SRL_DLY_DELTA;
assign cal3_data_valid = (calib_rden_valid | calib_rden_valid_stgd);
assign cal3_match_found
= ((calib_rden_valid && cal3_data_match) ||
(calib_rden_valid_stgd && cal3_data_match_stgd));
 
// when calibrating, check to see which clock cycle (after the read is
// issued) does the expected data pattern arrive. Record this result
// NOTE: Can add error checking here in case valid data not found on any
// of the available pipeline stages
always @(posedge clkdiv) begin
if (rstdiv) begin
cal3_rden_srl_a <= 5'bxxxxx;
cal3_state <= CAL3_IDLE;
calib_done[2] <= 1'b0;
calib_err_2[0] <= 1'b0;
count_rden <= {DQS_WIDTH{1'b0}};
rden_dly <= {5*DQS_WIDTH{1'b0}};
end else begin
 
case (cal3_state)
CAL3_IDLE: begin
count_rden <= {DQS_WIDTH{1'b0}};
if (calib_start[2]) begin
calib_done[2] <= 1'b0;
cal3_state <= CAL3_INIT;
end
end
 
CAL3_INIT: begin
cal3_rden_srl_a <= RDEN_BASE_DELAY;
// let SRL pipe clear after loading initial shift value
cal3_state <= CAL3_RDEN_PIPE_CLR_WAIT;
end
 
CAL3_DETECT:
if (cal3_data_valid)
// if match found at the correct clock cycle
if (cal3_match_found) begin
 
// For simulation, load SRL addresses for all DQS with same value
if (SIM_ONLY != 0) begin
for (i = 0; i < DQS_WIDTH; i = i + 1) begin: loop_sim_rden_dly
rden_dly[(i*5)] <= cal3_rden_dly[0];
rden_dly[(i*5)+1] <= cal3_rden_dly[1];
rden_dly[(i*5)+2] <= cal3_rden_dly[2];
rden_dly[(i*5)+3] <= cal3_rden_dly[3];
rden_dly[(i*5)+4] <= cal3_rden_dly[4];
end
end else begin
rden_dly[(count_rden*5)] <= cal3_rden_dly[0];
rden_dly[(count_rden*5)+1] <= cal3_rden_dly[1];
rden_dly[(count_rden*5)+2] <= cal3_rden_dly[2];
rden_dly[(count_rden*5)+3] <= cal3_rden_dly[3];
rden_dly[(count_rden*5)+4] <= cal3_rden_dly[4];
end
 
// Use for stage 4 calibration
calib_rden_dly[(count_rden*5)] <= cal3_rden_srl_a[0];
calib_rden_dly[(count_rden*5)+1] <= cal3_rden_srl_a[1];
calib_rden_dly[(count_rden*5)+2] <= cal3_rden_srl_a[2];
calib_rden_dly[(count_rden*5)+3] <= cal3_rden_srl_a[3];
calib_rden_dly[(count_rden*5)+4] <= cal3_rden_srl_a[4];
cal3_state <= CAL3_DONE;
end else begin
// If we run out of stages to shift, without finding correct
// result, the stop and assert error
if (cal3_rden_srl_a == 5'b11111) begin
calib_err_2[0] <= 1'b1;
cal3_state <= CAL3_IDLE;
end else begin
// otherwise, increase the shift value and try again
cal3_rden_srl_a <= cal3_rden_srl_a + 1;
cal3_state <= CAL3_RDEN_PIPE_CLR_WAIT;
end
end
 
// give additional time for RDEN_R pipe to clear from effects of
// previous pipeline or IDELAY tap change
CAL3_RDEN_PIPE_CLR_WAIT:
if (calib_rden_pipe_cnt == 5'b00000)
cal3_state <= CAL3_DETECT;
 
CAL3_DONE: begin
if ((count_rden == DQS_WIDTH-1) || (SIM_ONLY != 0)) begin
calib_done[2] <= 1'b1;
cal3_state <= CAL3_IDLE;
end else begin
count_rden <= count_rden + 1;
cal3_state <= CAL3_INIT;
end
end
endcase
end
end
 
//*****************************************************************
// Last part of stage 3 calibration - compensate for differences
// in delay between different DQS groups. Assume that in the worst
// case, DQS groups can only differ by one clock cycle. Data for
// certain DQS groups must be delayed by one clock cycle.
// NOTE: May need to increase allowable variation to greater than
// one clock cycle in certain customer designs.
// Algorithm is:
// 1. Record shift delay value for DQS[0]
// 2. Compare each DQS[x] delay value to that of DQS[0]:
// - If different, than record this fact (RDEN_MUX)
// - If greater than DQS[0], set RDEN_INC. Assume greater by
// one clock cycle only - this is a key assumption, assume no
// more than a one clock cycle variation.
// - If less than DQS[0], set RDEN_DEC
// 3. After calibration is complete, set control for DQS group
// delay (CALIB_RDEN_SEL):
// - If RDEN_DEC = 1, then assume that DQS[0] is the lowest
// delay (and at least one other DQS group has a higher
// delay).
// - If RDEN_INC = 1, then assume that DQS[0] is the highest
// delay (and that all other DQS groups have the same or
// lower delay).
// - If both RDEN_INC and RDEN_DEC = 1, then flag error
// (variation is too high for this algorithm to handle)
//*****************************************************************
 
always @(posedge clkdiv) begin
if (rstdiv) begin
calib_err_2[1] <= 1'b0;
calib_rden_sel <= {DQS_WIDTH{1'bx}};
rden_dec <= 1'b0;
rden_dly_0 <= 5'bxxxxx;
rden_inc <= 1'b0;
rden_mux <= {DQS_WIDTH{1'b0}};
end else begin
// if a match if found, then store the value of rden_dly
if (!calib_done[2]) begin
if ((cal3_state == CAL3_DETECT) && cal3_match_found) begin
// store the value for DQS[0] as a reference
if (count_rden == 0) begin
// for simulation, RDEN calibration only happens for DQS[0]
// set RDEN_MUX for all DQS groups to be the same as DQS[0]
if (SIM_ONLY != 0)
rden_mux <= {DQS_WIDTH{1'b0}};
else begin
// otherwise, load values for DQS[0]
rden_dly_0 <= cal3_rden_srl_a;
rden_mux[0] <= 1'b0;
end
end else if (SIM_ONLY == 0) begin
// for all other DQS groups, compare RDEN_DLY delay value with
// that of DQS[0]
if (rden_dly_0 != cal3_rden_srl_a) begin
// record that current DQS group has a different delay
// than DQS[0] (the "reference" DQS group)
rden_mux[count_rden] <= 1'b1;
if (rden_dly_0 > cal3_rden_srl_a)
rden_inc <= 1'b1;
else if (rden_dly_0 < cal3_rden_srl_a)
rden_dec <= 1'b1;
// otherwise, if current DQS group has same delay as DQS[0],
// then rden_mux[count_rden] remains at 0 (since rden_mux
// array contents initialized to 0)
end
end
end
end else begin
// Otherwise - if we're done w/ stage 2 calibration:
// set final value for RDEN data delay
// flag error if there's more than one cycle variation from DQS[0]
calib_err_2[1] <= (rden_inc && rden_dec);
if (rden_inc)
// if DQS[0] delay represents max delay
calib_rden_sel <= ~rden_mux;
else
// if DQS[0] delay represents min delay (or all the delays are
// the same between DQS groups)
calib_rden_sel <= rden_mux;
end
end
end
 
// flag error for stage 3 if appropriate
always @(posedge clkdiv)
calib_err[2] <= calib_err_2[0] | calib_err_2[1];
 
//***************************************************************************
// Stage 4 calibration: DQS gate
//***************************************************************************
 
//*****************************************************************
// indicates that current received data is the correct pattern. Same as
// for READ VALID calibration, except that the expected data sequence is
// different since DQS gate is asserted after the 6th word.
// Data sequence:
// Arrives from memory (at FPGA input) (R, F): 1 0 0 1 1 0 0 1
// After gating the sequence looks like: 1 0 0 1 1 0 1 0 (7th word =
// 5th word, 8th word = 6th word)
// What is the gate timing is off? Need to make sure we can distinquish
// between the results of correct vs. incorrect gate timing. We also use
// the "read_valid" signal from stage 3 calibration to help us determine
// when to check for a valid sequence for stage 4 calibration (i.e. use
// CAL4_DATA_VALID in addition to CAL4_DATA_MATCH/CAL4_DATA_MATCH_STGD)
// Note that since the gate signal from the CLK0 domain is synchronized
// to the falling edge of DQS, that the effect of the gate will only be
// seen starting with a rising edge data (although it is possible
// the GATE IDDR output could go metastable and cause a unexpected result
// on the first rising and falling edges after the gate is enabled).
// Also note that the actual DQS glitch can come more than 0.5*tCK after
// the last falling edge of DQS and the constraint for this path is can
// be > 0.5*tCK; however, this means when calibrating, the output of the
// GATE IDDR may miss the setup time requirement of the rising edge flop
// and only meet it for the falling edge flop. Therefore the rising
// edge data immediately following the assertion of the gate can either
// be a 1 or 0 (can rely on either)
// As the timing on the gate is varied, we expect to see (sequence of
// captured read data shown below):
// - 1 0 0 1 1 0 0 1 (gate is really early, starts and ends before
// read burst even starts)
// - x 0 0 1 1 0 0 1 (gate pulse starts before the burst, and ends
// - x y 0 1 1 0 0 1 sometime during the burst; x,y = 0, or 1, but
// - x y x 1 1 0 0 1 all bits that show an x are the same value,
// - x y x y 1 0 0 1 and y are the same value)
// - x y x y x 0 0 1
// - x y x y x y 0 1 (gate starts just before start of burst)
// - 1 0 x 0 x 0 x 0 (gate starts after 1st falling word. The "x"
// represents possiblity that gate may not disable
// clock for 2nd rising word in time)
// - 1 0 0 1 x 1 x 1 (gate starts after 2nd falling word)
// - 1 0 0 1 1 0 x 0 (gate starts after 3rd falling word - GOOD!!)
// - 1 0 0 1 1 0 0 1 (gate starts after burst is already done)
//*****************************************************************
 
assign cal4_data_valid = calib_rden_valid | calib_rden_valid_stgd;
assign cal4_data_good = (calib_rden_valid &
cal4_data_match) |
(calib_rden_valid_stgd &
cal4_data_match_stgd);
 
always @(posedge clkdiv) begin
// if data is aligned out of fabric ISERDES:
cal4_data_match <= ((rdd_rise_q2_r == 1) &&
(rdd_fall_q2_r == 0) &&
(rdd_rise_q1_r == 0) &&
(rdd_fall_q1_r == 1) &&
(rdd_rise_q2 == 1) &&
(rdd_fall_q2 == 0) &&
// MIG 2.1: Last rising edge data value not
// guaranteed to be certain value at higher
// frequencies
// (rdd_rise_q1 == 0) &&
(rdd_fall_q1 == 0));
// if data is staggered out of fabric ISERDES:
cal4_data_match_stgd <= ((rdd_rise_q1_r1 == 1) &&
(rdd_fall_q1_r1 == 0) &&
(rdd_rise_q2_r == 0) &&
(rdd_fall_q2_r == 1) &&
(rdd_rise_q1_r == 1) &&
(rdd_fall_q1_r == 0) &&
// MIG 2.1: Last rising edge data value not
// guaranteed to be certain value at higher
// frequencies
// (rdd_rise_q2 == 0) &&
(rdd_fall_q2 == 0));
end
 
//*****************************************************************
// DQS gate enable generation:
// This signal gets synchronized to DQS domain, and drives IDDR
// register that in turn asserts/deasserts CE to all 4 or 8 DQ
// IDDR's in that DQS group.
// 1. During normal (post-cal) operation, this is only for 2 clock
// cycles following the end of a burst. Check for falling edge
// of RDEN. But must also make sure NOT assert for a read-idle-
// read (two non-consecutive reads, separated by exactly one
// idle cycle) - in this case, don't assert the gate because:
// (1) we don't have enough time to deassert the gate before the
// first rising edge of DQS for second burst (b/c of fact
// that DQS gate is generated in the fabric only off rising
// edge of CLK0 - if we somehow had an ODDR in fabric, we
// could pull this off, (2) assumption is that the DQS glitch
// will not rise enough to cause a glitch because the
// post-amble of the first burst is followed immediately by
// the pre-amble of the next burst
// 2. During stage 4 calibration, assert for 3 clock cycles
// (assert gate enable one clock cycle early), since we gate out
// the last two words (in addition to the crap on the DQ bus after
// the DQS read postamble).
// NOTE: PHY_INIT_RDEN and CTRL_RDEN have slightly different timing w/r
// to when they are asserted w/r to the start of the read burst
// (PHY_INIT_RDEN is one cycle earlier than CTRL_RDEN).
//*****************************************************************
 
// register for timing purposes for fast clock path - currently only
// calib_done_r[2] used
always @(posedge clk)
calib_done_r <= calib_done;
 
always @(*) begin
calib_ctrl_rden = ctrl_rden;
calib_init_rden = calib_done_r[2] & phy_init_rden;
end
 
assign calib_ctrl_rden_negedge = ~calib_ctrl_rden & calib_ctrl_rden_r;
// check for read-idle-read before asserting DQS pulse at end of read
assign calib_ctrl_gate_pulse = calib_ctrl_rden_negedge_r &
~calib_ctrl_rden;
always @(posedge clk) begin
calib_ctrl_rden_r <= calib_ctrl_rden;
calib_ctrl_rden_negedge_r <= calib_ctrl_rden_negedge;
calib_ctrl_gate_pulse_r <= calib_ctrl_gate_pulse;
end
 
assign calib_init_gate_pulse = ~calib_init_rden & calib_init_rden_r;
always @(posedge clk) begin
calib_init_rden_r <= calib_init_rden;
calib_init_gate_pulse_r <= calib_init_gate_pulse;
calib_init_gate_pulse_r1 <= calib_init_gate_pulse_r;
end
 
// Gate is asserted: (1) during cal, for 3 cycles, starting 1 cycle
// after falling edge of CTRL_RDEN, (2) during normal ops, for 2
// cycles, starting 2 cycles after falling edge of CTRL_RDEN
assign gate_srl_in = ~((calib_ctrl_gate_pulse |
calib_ctrl_gate_pulse_r) |
(calib_init_gate_pulse |
calib_init_gate_pulse_r |
calib_init_gate_pulse_r1));
 
//*****************************************************************
// generate DQS enable signal for each DQS group
// There are differences between DQS gate signal for calibration vs. during
// normal operation:
// * calibration gates the second to last clock cycle of the burst,
// rather than after the last word (e.g. for a 8-word, 4-cycle burst,
// cycle 4 is gated for calibration; during normal operation, cycle
// 5 (i.e. cycle after the last word) is gated)
// enable for DQS is deasserted for two clock cycles, except when
// we have the preamble for the next read immediately following
// the postamble of the current read - assume DQS does not glitch
// during this time, that it stays low. Also if we did have to gate
// the DQS for this case, then we don't have enough time to deassert
// the gate in time for the first rising edge of DQS for the second
// read
//*****************************************************************
 
// Flops for targetting of multi-cycle path in UCF
genvar gate_ff_i;
generate
for (gate_ff_i = 0; gate_ff_i < 5*DQS_WIDTH;
gate_ff_i = gate_ff_i+1) begin: gen_gate_dly
FDRSE u_ff_gate_dly
(
.Q (gate_dly_r[gate_ff_i]),
.C (clkdiv),
.CE (1'b1),
.D (gate_dly[gate_ff_i]),
.R (1'b0),
.S (1'b0)
) /* synthesis syn_preserve = 1 */
/* synthesis syn_replicate = 0 */;
end
endgenerate
 
genvar gate_i;
generate
for (gate_i = 0; gate_i < DQS_WIDTH; gate_i = gate_i + 1) begin: gen_gate
SRLC32E u_gate_srl
(
.Q (gate_srl_out[gate_i]),
.Q31 (),
.A ({gate_dly_r[(gate_i*5)+4],
gate_dly_r[(gate_i*5)+3],
gate_dly_r[(gate_i*5)+2],
gate_dly_r[(gate_i*5)+1],
gate_dly_r[(gate_i*5)]}),
.CE (1'b1),
.CLK (clk),
.D (gate_srl_in)
);
 
// For GATE_BASE_DELAY > 0, have one extra cycle to register outputs
// from controller before generating DQS gate pulse. In PAR, the
// location of the controller logic can be far from the DQS gate
// logic (DQS gate logic located near the DQS I/O's), contributing
// to large net delays. Registering the controller outputs for
// CL >= 4 (above 200MHz) adds a stage of pipelining to reduce net
// delays
if (GATE_BASE_DELAY > 0) begin: gen_gate_base_dly_gt3
// add flop between SRL32 and EN_DQS flop (which is located near the
// DDR2 IOB's)
FDRSE u_gate_srl_ff
(
.Q (gate_srl_out_r[gate_i]),
.C (clk),
.CE (1'b1),
.D (gate_srl_out[gate_i]),
.R (1'b0),
.S (1'b0)
) /* synthesis syn_preserve = 1 */;
end else begin: gen_gate_base_dly_le3
assign gate_srl_out_r[gate_i] = gate_srl_out[gate_i];
end
 
FDRSE u_en_dqs_ff
(
.Q (en_dqs[gate_i]),
.C (clk),
.CE (1'b1),
.D (gate_srl_out_r[gate_i]),
.R (1'b0),
.S (1'b0)
) /* synthesis syn_preserve = 1 */
/* synthesis syn_replicate = 0 */;
end
endgenerate
 
//*****************************************************************
// Find valid window: keep track of how long we've been in the same data
// window. If it's been long enough, then declare that we've found a stable
// valid window - in particular, that we're past any region of instability
// associated with the edge of the window. Use only when finding left edge
//*****************************************************************
 
always @(posedge clkdiv)
// reset before we start to look for window
if (cal4_state == CAL4_INIT) begin
cal4_window_cnt <= 4'b0000;
cal4_stable_window <= 1'b0;
end else if ((cal4_state == CAL4_FIND_EDGE) && cal4_seek_left) begin
// if we're looking for left edge, and incrementing IDELAY, count
// consecutive taps over which we're in the window
if (cal4_data_valid) begin
if (cal4_data_good)
cal4_window_cnt <= cal4_window_cnt + 1;
else
cal4_window_cnt <= 4'b0000;
end
 
if (cal4_window_cnt == MIN_WIN_SIZE-1)
cal4_stable_window <= 1'b1;
end
 
//*****************************************************************
// keep track of edge tap counts found, and whether we've
// incremented to the maximum number of taps allowed
//*****************************************************************
 
always @(posedge clkdiv)
if ((cal4_state == CAL4_INIT) || cal4_dlyrst_gate) begin
cal4_idel_max_tap <= 1'b0;
cal4_idel_bit_tap <= 1'b0;
cal4_idel_tap_cnt <= 6'b000000;
end else if (cal4_dlyce_gate) begin
if (cal4_dlyinc_gate) begin
cal4_idel_tap_cnt <= cal4_idel_tap_cnt + 1;
cal4_idel_bit_tap <= (cal4_idel_tap_cnt == CAL4_IDEL_BIT_VAL-2);
cal4_idel_max_tap <= (cal4_idel_tap_cnt == 6'b111110);
end else begin
cal4_idel_tap_cnt <= cal4_idel_tap_cnt - 1;
cal4_idel_bit_tap <= 1'b0;
cal4_idel_max_tap <= 1'b0;
end
end
 
always @(posedge clkdiv)
if ((cal4_state != CAL4_RDEN_PIPE_CLR_WAIT) &&
(cal3_state != CAL3_RDEN_PIPE_CLR_WAIT))
calib_rden_pipe_cnt <= CALIB_RDEN_PIPE_LEN-1;
else
calib_rden_pipe_cnt <= calib_rden_pipe_cnt - 1;
 
//*****************************************************************
// Stage 4 cal state machine
//*****************************************************************
 
always @(posedge clkdiv)
if (rstdiv) begin
calib_done[3] <= 1'b0;
calib_done_tmp[3] <= 1'b0;
calib_err[3] <= 1'b0;
count_gate <= 'b0;
gate_dly <= 'b0;
next_count_gate <= 'b0;
cal4_idel_adj_cnt <= 6'bxxxxxx;
cal4_dlyce_gate <= 1'b0;
cal4_dlyinc_gate <= 1'b0;
cal4_dlyrst_gate <= 1'b0; // reset handled elsewhere in code
cal4_gate_srl_a <= 5'bxxxxx;
cal4_rden_srl_a <= 5'bxxxxx;
cal4_ref_req <= 1'b0;
cal4_seek_left <= 1'bx;
cal4_state <= CAL4_IDLE;
end else begin
cal4_ref_req <= 1'b0;
cal4_dlyce_gate <= 1'b0;
cal4_dlyinc_gate <= 1'b0;
cal4_dlyrst_gate <= 1'b0;
 
case (cal4_state)
CAL4_IDLE: begin
count_gate <= 'b0;
next_count_gate <= 'b0;
if (calib_start[3]) begin
gate_dly <= 'b0;
calib_done[3] <= 1'b0;
cal4_state <= CAL4_INIT;
end
end
 
CAL4_INIT: begin
// load: (1) initial value of gate delay SRL, (2) appropriate
// value of RDEN SRL (so that we get correct "data valid" timing)
cal4_gate_srl_a <= GATE_BASE_INIT;
cal4_rden_srl_a <= {calib_rden_dly[(count_gate*5)+4],
calib_rden_dly[(count_gate*5)+3],
calib_rden_dly[(count_gate*5)+2],
calib_rden_dly[(count_gate*5)+1],
calib_rden_dly[(count_gate*5)]};
// let SRL pipe clear after loading initial shift value
cal4_state <= CAL4_RDEN_PIPE_CLR_WAIT;
end
 
// sort of an initial state - start checking to see whether we're
// already in the window or not
CAL4_FIND_WINDOW:
// decide right away if we start in the proper window - this
// determines if we are then looking for the left (trailing) or
// right (leading) edge of the data valid window
if (cal4_data_valid) begin
// if we find a match - then we're already in window, now look
// for left edge. Otherwise, look for right edge of window
cal4_seek_left <= cal4_data_good;
cal4_state <= CAL4_FIND_EDGE;
end
 
CAL4_FIND_EDGE:
// don't do anything until the exact clock cycle when to check that
// readback data is valid or not
if (cal4_data_valid) begin
// we're currently in the window, look for left edge of window
if (cal4_seek_left) begin
// make sure we've passed the right edge before trying to detect
// the left edge (i.e. avoid any edge "instability") - else, we
// may detect an "false" edge too soon. By design, if we start in
// the data valid window, always expect at least
// MIN(BIT_TIME_TAPS,32) (-/+ jitter, see below) taps of valid
// window before we hit the left edge (this is because when stage
// 4 calibration first begins (i.e., gate_dly = 00, and IDELAY =
// 00), we're guaranteed to NOT be in the window, and we always
// start searching for MIN(BIT_TIME_TAPS,32) for the right edge
// of window. If we don't find it, increment gate_dly, and if we
// now start in the window, we have at least approximately
// CLK_PERIOD-MIN(BIT_TIME_TAPS,32) = MIN(BIT_TIME_TAPS,32) taps.
// It's approximately because jitter, noise, etc. can bring this
// value down slightly. Because of this (although VERY UNLIKELY),
// we have to protect against not decrementing IDELAY below 0
// during adjustment phase).
if (cal4_stable_window && !cal4_data_good) begin
// found left edge of window, dec by MIN(BIT_TIME_TAPS,32)
cal4_idel_adj_cnt <= CAL4_IDEL_BIT_VAL;
cal4_idel_adj_inc <= 1'b0;
cal4_state <= CAL4_ADJ_IDEL;
end else begin
// Otherwise, keep looking for left edge:
if (cal4_idel_max_tap) begin
// ran out of taps looking for left edge (max=63) - happens
// for low frequency case, decrement by 32
cal4_idel_adj_cnt <= 6'b100000;
cal4_idel_adj_inc <= 1'b0;
cal4_state <= CAL4_ADJ_IDEL;
end else begin
cal4_dlyce_gate <= 1'b1;
cal4_dlyinc_gate <= 1'b1;
cal4_state <= CAL4_IDEL_WAIT;
end
end
end else begin
// looking for right edge of window:
// look for the first match - this means we've found the right
// (leading) edge of the data valid window, increment by
// MIN(BIT_TIME_TAPS,32)
if (cal4_data_good) begin
cal4_idel_adj_cnt <= CAL4_IDEL_BIT_VAL;
cal4_idel_adj_inc <= 1'b1;
cal4_state <= CAL4_ADJ_IDEL;
end else begin
// Otherwise, keep looking:
// only look for MIN(BIT_TIME_TAPS,32) taps for right edge,
// if we haven't found it, then inc gate delay, try again
if (cal4_idel_bit_tap) begin
// if we're already maxed out on gate delay, then error out
// (simulation only - calib_err isn't currently connected)
if (cal4_gate_srl_a == 5'b11111) begin
calib_err[3] <= 1'b1;
cal4_state <= CAL4_IDLE;
end else begin
// otherwise, increment gate delay count, and start
// over again
cal4_gate_srl_a <= cal4_gate_srl_a + 1;
cal4_dlyrst_gate <= 1'b1;
cal4_state <= CAL4_RDEN_PIPE_CLR_WAIT;
end
end else begin
// keep looking for right edge
cal4_dlyce_gate <= 1'b1;
cal4_dlyinc_gate <= 1'b1;
cal4_state <= CAL4_IDEL_WAIT;
end
end
end
end
 
// wait for GATE IDELAY to settle, after reset or increment
CAL4_IDEL_WAIT: begin
// For simulation, load SRL addresses for all DQS with same value
if (SIM_ONLY != 0) begin
for (i = 0; i < DQS_WIDTH; i = i + 1) begin: loop_sim_gate_dly
gate_dly[(i*5)+4] <= cal4_gate_srl_a[4];
gate_dly[(i*5)+3] <= cal4_gate_srl_a[3];
gate_dly[(i*5)+2] <= cal4_gate_srl_a[2];
gate_dly[(i*5)+1] <= cal4_gate_srl_a[1];
gate_dly[(i*5)] <= cal4_gate_srl_a[0];
end
end else begin
gate_dly[(count_gate*5)+4] <= cal4_gate_srl_a[4];
gate_dly[(count_gate*5)+3] <= cal4_gate_srl_a[3];
gate_dly[(count_gate*5)+2] <= cal4_gate_srl_a[2];
gate_dly[(count_gate*5)+1] <= cal4_gate_srl_a[1];
gate_dly[(count_gate*5)] <= cal4_gate_srl_a[0];
end
// check to see if we've found edge of window
if (!idel_set_wait)
cal4_state <= CAL4_FIND_EDGE;
end
 
// give additional time for RDEN_R pipe to clear from effects of
// previous pipeline (and IDELAY reset)
CAL4_RDEN_PIPE_CLR_WAIT: begin
// MIG 2.2: Bug fix - make sure to update GATE_DLY count, since
// possible for FIND_EDGE->RDEN_PIPE_CLR_WAIT->FIND_WINDOW
// transition (i.e. need to make sure the gate count updated in
// FIND_EDGE gets reflected in GATE_DLY by the time we reach
// state FIND_WINDOW) - previously GATE_DLY only being updated
// during state CAL4_IDEL_WAIT
if (SIM_ONLY != 0) begin
for (i = 0; i < DQS_WIDTH; i = i + 1) begin: loop_sim_gate_dly_pipe
gate_dly[(i*5)+4] <= cal4_gate_srl_a[4];
gate_dly[(i*5)+3] <= cal4_gate_srl_a[3];
gate_dly[(i*5)+2] <= cal4_gate_srl_a[2];
gate_dly[(i*5)+1] <= cal4_gate_srl_a[1];
gate_dly[(i*5)] <= cal4_gate_srl_a[0];
end
end else begin
gate_dly[(count_gate*5)+4] <= cal4_gate_srl_a[4];
gate_dly[(count_gate*5)+3] <= cal4_gate_srl_a[3];
gate_dly[(count_gate*5)+2] <= cal4_gate_srl_a[2];
gate_dly[(count_gate*5)+1] <= cal4_gate_srl_a[1];
gate_dly[(count_gate*5)] <= cal4_gate_srl_a[0];
end
// look for new window
if (calib_rden_pipe_cnt == 5'b00000)
cal4_state <= CAL4_FIND_WINDOW;
end
 
// increment/decrement DQS/DQ IDELAY for final adjustment
CAL4_ADJ_IDEL:
// add underflow protection for corner case when left edge found
// using fewer than MIN(BIT_TIME_TAPS,32) taps
if ((cal4_idel_adj_cnt == 6'b000000) ||
(cal4_dlyce_gate && !cal4_dlyinc_gate &&
(cal4_idel_tap_cnt == 6'b000001))) begin
cal4_state <= CAL4_DONE;
// stop when all gates calibrated, or gate[0] cal'ed (for sim)
if ((count_gate == DQS_WIDTH-1) || (SIM_ONLY != 0))
calib_done_tmp[3] <= 1'b1;
else
// need for VHDL simulation to prevent out-of-index error
next_count_gate <= count_gate + 1;
end else begin
cal4_idel_adj_cnt <= cal4_idel_adj_cnt - 1;
cal4_dlyce_gate <= 1'b1;
// whether inc or dec depends on whether left or right edge found
cal4_dlyinc_gate <= cal4_idel_adj_inc;
end
 
// wait for IDELAY output to settle after decrement. Check current
// COUNT_GATE value and decide if we're done
CAL4_DONE:
if (!idel_set_wait) begin
count_gate <= next_count_gate;
if (calib_done_tmp[3]) begin
calib_done[3] <= 1'b1;
cal4_state <= CAL4_IDLE;
end else begin
// request auto-refresh after every DQS group calibrated to
// avoid tRAS violation
cal4_ref_req <= 1'b1;
if (calib_ref_done)
cal4_state <= CAL4_INIT;
end
end
endcase
end
 
endmodule
/verilog/xilinx_ddr2/ddr2_idelay_ctrl.v
0,0 → 1,87
//*****************************************************************************
// DISCLAIMER OF LIABILITY
//
// This file contains proprietary and confidential information of
// Xilinx, Inc. ("Xilinx"), that is distributed under a license
// from Xilinx, and may be used, copied and/or disclosed only
// pursuant to the terms of a valid license agreement with Xilinx.
//
// XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION
// ("MATERIALS") "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
// EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING WITHOUT
// LIMITATION, ANY WARRANTY WITH RESPECT TO NONINFRINGEMENT,
// MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE. Xilinx
// does not warrant that functions included in the Materials will
// meet the requirements of Licensee, or that the operation of the
// Materials will be uninterrupted or error-free, or that defects
// in the Materials will be corrected. Furthermore, Xilinx does
// not warrant or make any representations regarding use, or the
// results of the use, of the Materials in terms of correctness,
// accuracy, reliability or otherwise.
//
// Xilinx products are not designed or intended to be fail-safe,
// or for use in any application requiring fail-safe performance,
// such as life-support or safety devices or systems, Class III
// medical devices, nuclear facilities, applications related to
// the deployment of airbags, or any other applications that could
// lead to death, personal injury or severe property or
// environmental damage (individually and collectively, "critical
// applications"). Customer assumes the sole risk and liability
// of any use of Xilinx products in critical applications,
// subject only to applicable laws and regulations governing
// limitations on product liability.
//
// Copyright 2006, 2007, 2008 Xilinx, Inc.
// All rights reserved.
//
// This disclaimer and copyright notice must be retained as part
// of this file at all times.
//*****************************************************************************
// ____ ____
// / /\/ /
// /___/ \ / Vendor: Xilinx
// \ \ \/ Version: 3.0
// \ \ Application: MIG
// / / Filename: ddr2_idelay_ctrl.v
// /___/ /\ Date Last Modified: $Date: 2008/12/23 14:26:00 $
// \ \ / \ Date Created: Wed Aug 16 2006
// \___\/\___\
//
//Device: Virtex-5
//Design Name: DDR2
//Purpose:
// This module instantiates the IDELAYCTRL primitive of the Virtex-5 device
// which continuously calibrates the IDELAY elements in the region in case of
// varying operating conditions. It takes a 200MHz clock as an input
//Reference:
//Revision History:
// Rev 1.1 - Parameter IODELAY_GRP added and constraint IODELAY_GROUP added
// on IOELAYCTRL primitive. Generate logic on IDELAYCTRL removed
// since tools will replicate idelactrl primitives.PK. 11/27/08
//*****************************************************************************
 
`timescale 1ns/1ps
 
module ddr2_idelay_ctrl #
(
// Following parameters are for 72-bit RDIMM design (for ML561 Reference
// board design). Actual values may be different. Actual parameters values
// are passed from design top module ddr2_mig module. Please refer to
// the ddr2_mig module for actual values.
parameter IODELAY_GRP = "IODELAY_MIG"
)
 
(
input clk200,
input rst200,
output idelay_ctrl_rdy
);
 
(* IODELAY_GROUP = IODELAY_GRP *) IDELAYCTRL u_idelayctrl
(
.RDY(idelay_ctrl_rdy),
.REFCLK(clk200),
.RST(rst200)
);
 
endmodule
/verilog/xilinx_ddr2/ddr2_usr_top.v
0,0 → 1,184
//*****************************************************************************
// DISCLAIMER OF LIABILITY
//
// This file contains proprietary and confidential information of
// Xilinx, Inc. ("Xilinx"), that is distributed under a license
// from Xilinx, and may be used, copied and/or disclosed only
// pursuant to the terms of a valid license agreement with Xilinx.
//
// XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION
// ("MATERIALS") "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
// EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING WITHOUT
// LIMITATION, ANY WARRANTY WITH RESPECT TO NONINFRINGEMENT,
// MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE. Xilinx
// does not warrant that functions included in the Materials will
// meet the requirements of Licensee, or that the operation of the
// Materials will be uninterrupted or error-free, or that defects
// in the Materials will be corrected. Furthermore, Xilinx does
// not warrant or make any representations regarding use, or the
// results of the use, of the Materials in terms of correctness,
// accuracy, reliability or otherwise.
//
// Xilinx products are not designed or intended to be fail-safe,
// or for use in any application requiring fail-safe performance,
// such as life-support or safety devices or systems, Class III
// medical devices, nuclear facilities, applications related to
// the deployment of airbags, or any other applications that could
// lead to death, personal injury or severe property or
// environmental damage (individually and collectively, "critical
// applications"). Customer assumes the sole risk and liability
// of any use of Xilinx products in critical applications,
// subject only to applicable laws and regulations governing
// limitations on product liability.
//
// Copyright 2006, 2007 Xilinx, Inc.
// All rights reserved.
//
// This disclaimer and copyright notice must be retained as part
// of this file at all times.
//*****************************************************************************
// ____ ____
// / /\/ /
// /___/ \ / Vendor: Xilinx
// \ \ \/ Version: 3.0
// \ \ Application: MIG
// / / Filename: ddr2_usr_top.v
// /___/ /\ Date Last Modified: $Date: 2008/12/23 14:26:01 $
// \ \ / \ Date Created: Mon Aug 28 2006
// \___\/\___\
//
//Device: Virtex-5
//Design Name: DDR2
//Purpose:
// This module interfaces with the user. The user should provide the data
// and various commands.
//Reference:
//Revision History:
//*****************************************************************************
 
`timescale 1ns/1ps
 
module ddr2_usr_top #
(
// Following parameters are for 72-bit RDIMM design (for ML561 Reference
// board design). Actual values may be different. Actual parameters values
// are passed from design top module ddr2_mig module. Please refer to
// the ddr2_mig module for actual values.
parameter BANK_WIDTH = 2,
parameter CS_BITS = 0,
parameter COL_WIDTH = 10,
parameter DQ_WIDTH = 72,
parameter DQ_PER_DQS = 8,
parameter APPDATA_WIDTH = 144,
parameter ECC_ENABLE = 0,
parameter DQS_WIDTH = 9,
parameter ROW_WIDTH = 14
)
(
input clk0,
input usr_clk, //jb
input clk90,
input rst0,
input [DQ_WIDTH-1:0] rd_data_in_rise,
input [DQ_WIDTH-1:0] rd_data_in_fall,
input [DQS_WIDTH-1:0] phy_calib_rden,
input [DQS_WIDTH-1:0] phy_calib_rden_sel,
output rd_data_valid,
output [APPDATA_WIDTH-1:0] rd_data_fifo_out,
input [2:0] app_af_cmd,
input [30:0] app_af_addr,
input app_af_wren,
input ctrl_af_rden,
output [2:0] af_cmd,
output [30:0] af_addr,
output af_empty,
output app_af_afull,
output [1:0] rd_ecc_error,
input app_wdf_wren,
input [APPDATA_WIDTH-1:0] app_wdf_data,
input [(APPDATA_WIDTH/8)-1:0] app_wdf_mask_data,
input wdf_rden,
output app_wdf_afull,
output [(2*DQ_WIDTH)-1:0] wdf_data,
output [((2*DQ_WIDTH)/8)-1:0] wdf_mask_data
);
 
wire [(APPDATA_WIDTH/2)-1:0] i_rd_data_fifo_out_fall;
wire [(APPDATA_WIDTH/2)-1:0] i_rd_data_fifo_out_rise;
 
//***************************************************************************
 
assign rd_data_fifo_out = {i_rd_data_fifo_out_fall,
i_rd_data_fifo_out_rise};
 
// read data de-skew and ECC calculation
ddr2_usr_rd #
(
.DQ_PER_DQS (DQ_PER_DQS),
.ECC_ENABLE (ECC_ENABLE),
.APPDATA_WIDTH (APPDATA_WIDTH),
.DQS_WIDTH (DQS_WIDTH)
)
u_usr_rd
(
.clk0 (clk0),
.rst0 (rst0),
.rd_data_in_rise (rd_data_in_rise),
.rd_data_in_fall (rd_data_in_fall),
.rd_ecc_error (rd_ecc_error),
.ctrl_rden (phy_calib_rden),
.ctrl_rden_sel (phy_calib_rden_sel),
.rd_data_valid (rd_data_valid),
.rd_data_out_rise (i_rd_data_fifo_out_rise),
.rd_data_out_fall (i_rd_data_fifo_out_fall)
);
 
// Command/Addres FIFO
ddr2_usr_addr_fifo #
(
.BANK_WIDTH (BANK_WIDTH),
.COL_WIDTH (COL_WIDTH),
.CS_BITS (CS_BITS),
.ROW_WIDTH (ROW_WIDTH)
)
u_usr_addr_fifo
(
.clk0 (clk0),
.usr_clk (usr_clk), //jb
.rst0 (rst0),
.app_af_cmd (app_af_cmd),
.app_af_addr (app_af_addr),
.app_af_wren (app_af_wren),
.ctrl_af_rden (ctrl_af_rden),
.af_cmd (af_cmd),
.af_addr (af_addr),
.af_empty (af_empty),
.app_af_afull (app_af_afull)
);
 
ddr2_usr_wr #
(
.BANK_WIDTH (BANK_WIDTH),
.COL_WIDTH (COL_WIDTH),
.CS_BITS (CS_BITS),
.DQ_WIDTH (DQ_WIDTH),
.APPDATA_WIDTH (APPDATA_WIDTH),
.ECC_ENABLE (ECC_ENABLE),
.ROW_WIDTH (ROW_WIDTH)
)
u_usr_wr
(
.clk0 (clk0),
.usr_clk (usr_clk), // jb
.clk90 (clk90),
.rst0 (rst0),
.app_wdf_wren (app_wdf_wren),
.app_wdf_data (app_wdf_data),
.app_wdf_mask_data (app_wdf_mask_data),
.wdf_rden (wdf_rden),
.app_wdf_afull (app_wdf_afull),
.wdf_data (wdf_data),
.wdf_mask_data (wdf_mask_data)
);
 
endmodule
/verilog/xilinx_ddr2/ddr2_usr_rd.v
0,0 → 1,299
//*****************************************************************************
// DISCLAIMER OF LIABILITY
//
// This file contains proprietary and confidential information of
// Xilinx, Inc. ("Xilinx"), that is distributed under a license
// from Xilinx, and may be used, copied and/or disclosed only
// pursuant to the terms of a valid license agreement with Xilinx.
//
// XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION
// ("MATERIALS") "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
// EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING WITHOUT
// LIMITATION, ANY WARRANTY WITH RESPECT TO NONINFRINGEMENT,
// MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE. Xilinx
// does not warrant that functions included in the Materials will
// meet the requirements of Licensee, or that the operation of the
// Materials will be uninterrupted or error-free, or that defects
// in the Materials will be corrected. Furthermore, Xilinx does
// not warrant or make any representations regarding use, or the
// results of the use, of the Materials in terms of correctness,
// accuracy, reliability or otherwise.
//
// Xilinx products are not designed or intended to be fail-safe,
// or for use in any application requiring fail-safe performance,
// such as life-support or safety devices or systems, Class III
// medical devices, nuclear facilities, applications related to
// the deployment of airbags, or any other applications that could
// lead to death, personal injury or severe property or
// environmental damage (individually and collectively, "critical
// applications"). Customer assumes the sole risk and liability
// of any use of Xilinx products in critical applications,
// subject only to applicable laws and regulations governing
// limitations on product liability.
//
// Copyright 2006, 2007, 2008 Xilinx, Inc.
// All rights reserved.
//
// This disclaimer and copyright notice must be retained as part
// of this file at all times.
//*****************************************************************************
// ____ ____
// / /\/ /
// /___/ \ / Vendor: Xilinx
// \ \ \/ Version: 3.0
// \ \ Application: MIG
// / / Filename: ddr2_usr_rd.v
// /___/ /\ Date Last Modified: $Date: 2008/12/23 14:26:01 $
// \ \ / \ Date Created: Tue Aug 29 2006
// \___\/\___\
//
//Device: Virtex-5
//Design Name: DDR2
//Purpose:
// The delay between the read data with respect to the command issued is
// calculted in terms of no. of clocks. This data is then stored into the
// FIFOs and then read back and given as the ouput for comparison.
//Reference:
//Revision History:
//*****************************************************************************
 
`timescale 1ns/1ps
 
module ddr2_usr_rd #
(
// Following parameters are for 72-bit RDIMM design (for ML561 Reference
// board design). Actual values may be different. Actual parameters values
// are passed from design top module ddr2_mig module. Please refer to
// the ddr2_mig module for actual values.
parameter DQ_PER_DQS = 8,
parameter DQS_WIDTH = 9,
parameter APPDATA_WIDTH = 144,
parameter ECC_WIDTH = 72,
parameter ECC_ENABLE = 0
)
(
input clk0,
input rst0,
input [(DQS_WIDTH*DQ_PER_DQS)-1:0] rd_data_in_rise,
input [(DQS_WIDTH*DQ_PER_DQS)-1:0] rd_data_in_fall,
input [DQS_WIDTH-1:0] ctrl_rden,
input [DQS_WIDTH-1:0] ctrl_rden_sel,
output reg [1:0] rd_ecc_error,
output rd_data_valid,
output reg [(APPDATA_WIDTH/2)-1:0] rd_data_out_rise,
output reg [(APPDATA_WIDTH/2)-1:0] rd_data_out_fall
);
 
// determine number of FIFO72's to use based on data width
localparam RDF_FIFO_NUM = ((APPDATA_WIDTH/2)+63)/64;
 
reg [DQS_WIDTH-1:0] ctrl_rden_r;
wire [(DQS_WIDTH*DQ_PER_DQS)-1:0] fall_data;
reg [(DQS_WIDTH*DQ_PER_DQS)-1:0] rd_data_in_fall_r;
reg [(DQS_WIDTH*DQ_PER_DQS)-1:0] rd_data_in_rise_r;
wire rden;
reg [DQS_WIDTH-1:0] rden_sel_r
/* synthesis syn_preserve=1 */;
wire [DQS_WIDTH-1:0] rden_sel_mux;
wire [(DQS_WIDTH*DQ_PER_DQS)-1:0] rise_data;
 
// ECC specific signals
wire [((RDF_FIFO_NUM -1) *2)+1:0] db_ecc_error;
reg [(DQS_WIDTH*DQ_PER_DQS)-1:0] fall_data_r;
reg fifo_rden_r0;
reg fifo_rden_r1;
reg fifo_rden_r2;
reg fifo_rden_r3;
reg fifo_rden_r4;
reg fifo_rden_r5;
reg fifo_rden_r6;
wire [(APPDATA_WIDTH/2)-1:0] rd_data_out_fall_temp;
wire [(APPDATA_WIDTH/2)-1:0] rd_data_out_rise_temp;
reg rst_r;
reg [(DQS_WIDTH*DQ_PER_DQS)-1:0] rise_data_r;
wire [((RDF_FIFO_NUM -1) *2)+1:0] sb_ecc_error;
 
 
//***************************************************************************
 
always @(posedge clk0) begin
rden_sel_r <= ctrl_rden_sel;
ctrl_rden_r <= ctrl_rden;
rd_data_in_rise_r <= rd_data_in_rise;
rd_data_in_fall_r <= rd_data_in_fall;
end
 
// Instantiate primitive to allow this flop to be attached to multicycle
// path constraint in UCF. Multicycle path allowed for data from read FIFO.
// This is the same signal as RDEN_SEL_R, but is only used to select data
// (does not affect control signals)
genvar rd_i;
generate
for (rd_i = 0; rd_i < DQS_WIDTH; rd_i = rd_i+1) begin: gen_rden_sel_mux
FDRSE u_ff_rden_sel_mux
(
.Q (rden_sel_mux[rd_i]),
.C (clk0),
.CE (1'b1),
.D (ctrl_rden_sel[rd_i]),
.R (1'b0),
.S (1'b0)
) /* synthesis syn_preserve=1 */;
end
endgenerate
 
// determine correct read data valid signal timing
assign rden = (rden_sel_r[0]) ? ctrl_rden[0] : ctrl_rden_r[0];
 
// assign data based on the skew
genvar data_i;
generate
for(data_i = 0; data_i < DQS_WIDTH; data_i = data_i+1) begin: gen_data
assign rise_data[(data_i*DQ_PER_DQS)+(DQ_PER_DQS-1):
(data_i*DQ_PER_DQS)]
= (rden_sel_mux[data_i]) ?
rd_data_in_rise[(data_i*DQ_PER_DQS)+(DQ_PER_DQS-1) :
(data_i*DQ_PER_DQS)] :
rd_data_in_rise_r[(data_i*DQ_PER_DQS)+(DQ_PER_DQS-1):
(data_i*DQ_PER_DQS)];
assign fall_data[(data_i*DQ_PER_DQS)+(DQ_PER_DQS-1):
(data_i*DQ_PER_DQS)]
= (rden_sel_mux[data_i]) ?
rd_data_in_fall[(data_i*DQ_PER_DQS)+(DQ_PER_DQS-1):
(data_i*DQ_PER_DQS)] :
rd_data_in_fall_r[(data_i*DQ_PER_DQS)+(DQ_PER_DQS-1):
(data_i*DQ_PER_DQS)];
end
endgenerate
 
// Generate RST for FIFO reset AND for read/write enable:
// ECC FIFO always being read from and written to
always @(posedge clk0)
rst_r <= rst0;
 
genvar rdf_i;
generate
if (ECC_ENABLE) begin
always @(posedge clk0) begin
rd_ecc_error[0] <= (|sb_ecc_error) & fifo_rden_r5;
rd_ecc_error[1] <= (|db_ecc_error) & fifo_rden_r5;
rd_data_out_rise <= rd_data_out_rise_temp;
rd_data_out_fall <= rd_data_out_fall_temp;
rise_data_r <= rise_data;
fall_data_r <= fall_data;
end
 
// can use any of the read valids, they're all delayed by same amount
assign rd_data_valid = fifo_rden_r6;
 
// delay read valid to take into account max delay difference btw
// the read enable coming from the different DQS groups
always @(posedge clk0) begin
if (rst0) begin
fifo_rden_r0 <= 1'b0;
fifo_rden_r1 <= 1'b0;
fifo_rden_r2 <= 1'b0;
fifo_rden_r3 <= 1'b0;
fifo_rden_r4 <= 1'b0;
fifo_rden_r5 <= 1'b0;
fifo_rden_r6 <= 1'b0;
end else begin
fifo_rden_r0 <= rden;
fifo_rden_r1 <= fifo_rden_r0;
fifo_rden_r2 <= fifo_rden_r1;
fifo_rden_r3 <= fifo_rden_r2;
fifo_rden_r4 <= fifo_rden_r3;
fifo_rden_r5 <= fifo_rden_r4;
fifo_rden_r6 <= fifo_rden_r5;
end
end
 
for (rdf_i = 0; rdf_i < RDF_FIFO_NUM; rdf_i = rdf_i + 1) begin: gen_rdf
 
FIFO36_72 # // rise fifo
(
.ALMOST_EMPTY_OFFSET (9'h007),
.ALMOST_FULL_OFFSET (9'h00F),
.DO_REG (1), // extra CC output delay
.EN_ECC_WRITE ("FALSE"),
.EN_ECC_READ ("TRUE"),
.EN_SYN ("FALSE"),
.FIRST_WORD_FALL_THROUGH ("FALSE")
)
u_rdf
(
.ALMOSTEMPTY (),
.ALMOSTFULL (),
.DBITERR (db_ecc_error[rdf_i + rdf_i]),
.DO (rd_data_out_rise_temp[(64*(rdf_i+1))-1:
(64 *rdf_i)]),
.DOP (),
.ECCPARITY (),
.EMPTY (),
.FULL (),
.RDCOUNT (),
.RDERR (),
.SBITERR (sb_ecc_error[rdf_i + rdf_i]),
.WRCOUNT (),
.WRERR (),
.DI (rise_data_r[((64*(rdf_i+1)) + (rdf_i*8))-1:
(64 *rdf_i)+(rdf_i*8)]),
.DIP (rise_data_r[(72*(rdf_i+1))-1:
(64*(rdf_i+1))+ (8*rdf_i)]),
.RDCLK (clk0),
.RDEN (~rst_r),
.RST (rst_r),
.WRCLK (clk0),
.WREN (~rst_r)
);
 
FIFO36_72 # // fall_fifo
(
.ALMOST_EMPTY_OFFSET (9'h007),
.ALMOST_FULL_OFFSET (9'h00F),
.DO_REG (1), // extra CC output delay
.EN_ECC_WRITE ("FALSE"),
.EN_ECC_READ ("TRUE"),
.EN_SYN ("FALSE"),
.FIRST_WORD_FALL_THROUGH ("FALSE")
)
u_rdf1
(
.ALMOSTEMPTY (),
.ALMOSTFULL (),
.DBITERR (db_ecc_error[(rdf_i+1) + rdf_i]),
.DO (rd_data_out_fall_temp[(64*(rdf_i+1))-1:
(64 *rdf_i)]),
.DOP (),
.ECCPARITY (),
.EMPTY (),
.FULL (),
.RDCOUNT (),
.RDERR (),
.SBITERR (sb_ecc_error[(rdf_i+1) + rdf_i]),
.WRCOUNT (),
.WRERR (),
.DI (fall_data_r[((64*(rdf_i+1)) + (rdf_i*8))-1:
(64*rdf_i)+(rdf_i*8)]),
.DIP (fall_data_r[(72*(rdf_i+1))-1:
(64*(rdf_i+1))+ (8*rdf_i)]),
.RDCLK (clk0),
.RDEN (~rst_r),
.RST (rst_r), // or can use rst0
.WRCLK (clk0),
.WREN (~rst_r)
);
end
end // if (ECC_ENABLE)
else begin
assign rd_data_valid = fifo_rden_r0;
always @(posedge clk0) begin
rd_data_out_rise <= rise_data;
rd_data_out_fall <= fall_data;
fifo_rden_r0 <= rden;
end
end
endgenerate
 
endmodule
/verilog/orpsoc_top/orpsoc_top.v
0,0 → 1,1562
//////////////////////////////////////////////////////////////////////
/// ////
/// ORPSoC top for ML501 board ////
/// ////
/// Instantiates modules, depending on ORPSoC defines file ////
/// ////
/// Julius Baxter, julius@opencores.org ////
/// ////
//////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2009, 2010 Authors and OPENCORES.ORG ////
//// ////
//// This source file may be used and distributed without ////
//// restriction provided that this copyright statement is not ////
//// removed from the file and that any derivative work contains ////
//// the original copyright notice and the associated disclaimer. ////
//// ////
//// This source file is free software; you can redistribute it ////
//// and/or modify it under the terms of the GNU Lesser General ////
//// Public License as published by the Free Software Foundation; ////
//// either version 2.1 of the License, or (at your option) any ////
//// later version. ////
//// ////
//// This source is distributed in the hope that it will be ////
//// useful, but WITHOUT ANY WARRANTY; without even the implied ////
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ////
//// PURPOSE. See the GNU Lesser General Public License for more ////
//// details. ////
//// ////
//// You should have received a copy of the GNU Lesser General ////
//// Public License along with this source; if not, download it ////
//// from http://www.opencores.org/lgpl.shtml ////
//// ////
//////////////////////////////////////////////////////////////////////
 
`include "orpsoc-defines.v"
`include "synthesis-defines.v"
module orpsoc_top
(
`ifdef JTAG_DEBUG
tdo_pad_o, tms_pad_i, tck_pad_i, tdi_pad_i,
`endif
`ifdef XILINX_DDR2
ddr2_a, ddr2_ba, ddr2_ras_n, ddr2_cas_n, ddr2_we_n,
ddr2_cs_n, ddr2_odt, ddr2_cke, ddr2_dm,
ddr2_dq, ddr2_dqs, ddr2_dqs_n, ddr2_ck, ddr2_ck_n,
`endif
`ifdef XILINX_SSRAM
sram_clk, sram_clk_fb, sram_flash_addr, sram_flash_data,
sram_cen, sram_flash_oe_n, sram_flash_we_n, sram_bw,
sram_adv_ld_n, sram_mode,
`endif
`ifdef UART0
uart0_srx_pad_i, uart0_stx_pad_o,
uart0_srx_expheader_pad_i, uart0_stx_expheader_pad_o,
`endif
`ifdef SPI0
spi0_sck_o, spi0_mosi_o, spi0_miso_i, spi0_ss_o,
`endif
`ifdef I2C0
i2c0_sda_io, i2c0_scl_io,
`endif
`ifdef I2C1
i2c1_sda_io, i2c1_scl_io,
`endif
`ifdef GPIO0
gpio0_io,
`endif
`ifdef ETH0
eth0_tx_clk, eth0_tx_data, eth0_tx_en, eth0_tx_er,
eth0_rx_clk, eth0_rx_data, eth0_dv, eth0_rx_er,
eth0_col, eth0_crs,
eth0_mdc_pad_o, eth0_md_pad_io,
`ifdef ETH0_PHY_RST
eth0_rst_n_o,
`endif
`endif
sys_clk_in_p,sys_clk_in_n,
 
rst_n_pad_i
 
);
 
`include "orpsoc-params.v"
 
input sys_clk_in_p,sys_clk_in_n;
input rst_n_pad_i;
`ifdef JTAG_DEBUG
output tdo_pad_o;
input tms_pad_i;
input tck_pad_i;
input tdi_pad_i;
`endif
`ifdef XILINX_DDR2
output [12:0] ddr2_a;
output [1:0] ddr2_ba;
output ddr2_ras_n;
output ddr2_cas_n;
output ddr2_we_n;
output [1:0] ddr2_cs_n;
output [1:0] ddr2_odt;
output [1:0] ddr2_cke;
output [7:0] ddr2_dm;
inout [63:0] ddr2_dq;
inout [7:0] ddr2_dqs;
inout [7:0] ddr2_dqs_n;
output [1:0] ddr2_ck;
output [1:0] ddr2_ck_n;
`endif
`ifdef XILINX_SSRAM
// ZBT SSRAM
output sram_clk,
input sram_clk_fb,
output [21:1] sram_flash_addr,
inout [31:0] sram_flash_data,
output sram_cen,
output sram_flash_oe_n,
output sram_flash_we_n,
output [3:0] sram_bw,
output sram_adv_ld_n,
output sram_mode,
`endif
`ifdef UART0
input uart0_srx_pad_i;
output uart0_stx_pad_o;
// Duplicates of the UART signals, this time to the USB debug cable
input uart0_srx_expheader_pad_i;
output uart0_stx_expheader_pad_o;
`endif
`ifdef SPI0
output spi0_sck_o;
output spi0_mosi_o;
output [spi0_ss_width-1:0] spi0_ss_o;
input spi0_miso_i;
`endif
`ifdef I2C0
inout i2c0_sda_io, i2c0_scl_io;
`endif
`ifdef I2C1
inout i2c1_sda_io, i2c1_scl_io;
`endif
`ifdef GPIO0
inout [gpio0_io_width-1:0] gpio0_io;
`endif
`ifdef ETH0
input eth0_tx_clk;
output [3:0] eth0_tx_data;
output eth0_tx_en;
output eth0_tx_er;
input eth0_rx_clk;
input [3:0] eth0_rx_data;
input eth0_dv;
input eth0_rx_er;
input eth0_col;
input eth0_crs;
output eth0_mdc_pad_o;
inout eth0_md_pad_io;
`ifdef ETH0_PHY_RST
output eth0_rst_n_o;
`endif
`endif // `ifdef ETH0
////////////////////////////////////////////////////////////////////////
//
// Clock and reset generation module
//
////////////////////////////////////////////////////////////////////////
 
//
// Wires
//
wire wb_clk, wb_rst;
wire ddr2_if_clk, ddr2_if_rst;
wire clk200;
wire dbg_tck;
 
clkgen clkgen0
(
.sys_clk_in_p (sys_clk_in_p),
.sys_clk_in_n (sys_clk_in_n),
 
.wb_clk_o (wb_clk),
.wb_rst_o (wb_rst),
 
`ifdef JTAG_DEBUG
.tck_pad_i (tck_pad_i),
.dbg_tck_o (dbg_tck),
`endif
`ifdef XILINX_DDR2
.ddr2_if_clk_o (ddr2_if_clk),
.ddr2_if_rst_o (ddr2_if_rst),
.clk200_o (clk200),
`endif
 
// Asynchronous active low reset
.rst_n_pad_i (rst_n_pad_i)
);
 
////////////////////////////////////////////////////////////////////////
//
// Arbiter
//
////////////////////////////////////////////////////////////////////////
// Wire naming convention:
// First: wishbone master or slave (wbm/wbs)
// Second: Which bus it's on instruction or data (i/d)
// Third: Between which module and the arbiter the wires are
// Fourth: Signal name
// Fifth: Direction relative to module (not bus/arbiter!)
// ie. wbm_d_or12_adr_o is address OUT from the or1200
 
// OR1200 instruction bus wires
wire [wb_aw-1:0] wbm_i_or12_adr_o;
wire [wb_dw-1:0] wbm_i_or12_dat_o;
wire [3:0] wbm_i_or12_sel_o;
wire wbm_i_or12_we_o;
wire wbm_i_or12_cyc_o;
wire wbm_i_or12_stb_o;
wire [2:0] wbm_i_or12_cti_o;
wire [1:0] wbm_i_or12_bte_o;
wire [wb_dw-1:0] wbm_i_or12_dat_i;
wire wbm_i_or12_ack_i;
wire wbm_i_or12_err_i;
wire wbm_i_or12_rty_i;
 
// OR1200 data bus wires
wire [wb_aw-1:0] wbm_d_or12_adr_o;
wire [wb_dw-1:0] wbm_d_or12_dat_o;
wire [3:0] wbm_d_or12_sel_o;
wire wbm_d_or12_we_o;
wire wbm_d_or12_cyc_o;
wire wbm_d_or12_stb_o;
wire [2:0] wbm_d_or12_cti_o;
wire [1:0] wbm_d_or12_bte_o;
wire [wb_dw-1:0] wbm_d_or12_dat_i;
wire wbm_d_or12_ack_i;
wire wbm_d_or12_err_i;
wire wbm_d_or12_rty_i;
 
// Debug interface bus wires
wire [wb_aw-1:0] wbm_d_dbg_adr_o;
wire [wb_dw-1:0] wbm_d_dbg_dat_o;
wire [3:0] wbm_d_dbg_sel_o;
wire wbm_d_dbg_we_o;
wire wbm_d_dbg_cyc_o;
wire wbm_d_dbg_stb_o;
wire [2:0] wbm_d_dbg_cti_o;
wire [1:0] wbm_d_dbg_bte_o;
wire [wb_dw-1:0] wbm_d_dbg_dat_i;
wire wbm_d_dbg_ack_i;
wire wbm_d_dbg_err_i;
wire wbm_d_dbg_rty_i;
 
// Byte bus bridge master signals
wire [wb_aw-1:0] wbm_b_d_adr_o;
wire [wb_dw-1:0] wbm_b_d_dat_o;
wire [3:0] wbm_b_d_sel_o;
wire wbm_b_d_we_o;
wire wbm_b_d_cyc_o;
wire wbm_b_d_stb_o;
wire [2:0] wbm_b_d_cti_o;
wire [1:0] wbm_b_d_bte_o;
wire [wb_dw-1:0] wbm_b_d_dat_i;
wire wbm_b_d_ack_i;
wire wbm_b_d_err_i;
wire wbm_b_d_rty_i;
 
// Instruction bus slave wires //
// rom0 instruction bus wires
wire [31:0] wbs_i_rom0_adr_i;
wire [wbs_i_rom0_data_width-1:0] wbs_i_rom0_dat_i;
wire [3:0] wbs_i_rom0_sel_i;
wire wbs_i_rom0_we_i;
wire wbs_i_rom0_cyc_i;
wire wbs_i_rom0_stb_i;
wire [2:0] wbs_i_rom0_cti_i;
wire [1:0] wbs_i_rom0_bte_i;
wire [wbs_i_rom0_data_width-1:0] wbs_i_rom0_dat_o;
wire wbs_i_rom0_ack_o;
wire wbs_i_rom0_err_o;
wire wbs_i_rom0_rty_o;
 
// mc0 instruction bus wires
wire [31:0] wbs_i_mc0_adr_i;
wire [wbs_i_mc0_data_width-1:0] wbs_i_mc0_dat_i;
wire [3:0] wbs_i_mc0_sel_i;
wire wbs_i_mc0_we_i;
wire wbs_i_mc0_cyc_i;
wire wbs_i_mc0_stb_i;
wire [2:0] wbs_i_mc0_cti_i;
wire [1:0] wbs_i_mc0_bte_i;
wire [wbs_i_mc0_data_width-1:0] wbs_i_mc0_dat_o;
wire wbs_i_mc0_ack_o;
wire wbs_i_mc0_err_o;
wire wbs_i_mc0_rty_o;
// Data bus slave wires //
// mc0 data bus wires
wire [31:0] wbs_d_mc0_adr_i;
wire [wbs_d_mc0_data_width-1:0] wbs_d_mc0_dat_i;
wire [3:0] wbs_d_mc0_sel_i;
wire wbs_d_mc0_we_i;
wire wbs_d_mc0_cyc_i;
wire wbs_d_mc0_stb_i;
wire [2:0] wbs_d_mc0_cti_i;
wire [1:0] wbs_d_mc0_bte_i;
wire [wbs_d_mc0_data_width-1:0] wbs_d_mc0_dat_o;
wire wbs_d_mc0_ack_o;
wire wbs_d_mc0_err_o;
wire wbs_d_mc0_rty_o;
// i2c0 wires
wire [31:0] wbs_d_i2c0_adr_i;
wire [wbs_d_i2c0_data_width-1:0] wbs_d_i2c0_dat_i;
wire [3:0] wbs_d_i2c0_sel_i;
wire wbs_d_i2c0_we_i;
wire wbs_d_i2c0_cyc_i;
wire wbs_d_i2c0_stb_i;
wire [2:0] wbs_d_i2c0_cti_i;
wire [1:0] wbs_d_i2c0_bte_i;
wire [wbs_d_i2c0_data_width-1:0] wbs_d_i2c0_dat_o;
wire wbs_d_i2c0_ack_o;
wire wbs_d_i2c0_err_o;
wire wbs_d_i2c0_rty_o;
 
// i2c1 wires
wire [31:0] wbs_d_i2c1_adr_i;
wire [wbs_d_i2c1_data_width-1:0] wbs_d_i2c1_dat_i;
wire [3:0] wbs_d_i2c1_sel_i;
wire wbs_d_i2c1_we_i;
wire wbs_d_i2c1_cyc_i;
wire wbs_d_i2c1_stb_i;
wire [2:0] wbs_d_i2c1_cti_i;
wire [1:0] wbs_d_i2c1_bte_i;
wire [wbs_d_i2c1_data_width-1:0] wbs_d_i2c1_dat_o;
wire wbs_d_i2c1_ack_o;
wire wbs_d_i2c1_err_o;
wire wbs_d_i2c1_rty_o;
// spi0 wires
wire [31:0] wbs_d_spi0_adr_i;
wire [wbs_d_spi0_data_width-1:0] wbs_d_spi0_dat_i;
wire [3:0] wbs_d_spi0_sel_i;
wire wbs_d_spi0_we_i;
wire wbs_d_spi0_cyc_i;
wire wbs_d_spi0_stb_i;
wire [2:0] wbs_d_spi0_cti_i;
wire [1:0] wbs_d_spi0_bte_i;
wire [wbs_d_spi0_data_width-1:0] wbs_d_spi0_dat_o;
wire wbs_d_spi0_ack_o;
wire wbs_d_spi0_err_o;
wire wbs_d_spi0_rty_o;
 
// uart0 wires
wire [31:0] wbs_d_uart0_adr_i;
wire [wbs_d_uart0_data_width-1:0] wbs_d_uart0_dat_i;
wire [3:0] wbs_d_uart0_sel_i;
wire wbs_d_uart0_we_i;
wire wbs_d_uart0_cyc_i;
wire wbs_d_uart0_stb_i;
wire [2:0] wbs_d_uart0_cti_i;
wire [1:0] wbs_d_uart0_bte_i;
wire [wbs_d_uart0_data_width-1:0] wbs_d_uart0_dat_o;
wire wbs_d_uart0_ack_o;
wire wbs_d_uart0_err_o;
wire wbs_d_uart0_rty_o;
// gpio0 wires
wire [31:0] wbs_d_gpio0_adr_i;
wire [wbs_d_gpio0_data_width-1:0] wbs_d_gpio0_dat_i;
wire [3:0] wbs_d_gpio0_sel_i;
wire wbs_d_gpio0_we_i;
wire wbs_d_gpio0_cyc_i;
wire wbs_d_gpio0_stb_i;
wire [2:0] wbs_d_gpio0_cti_i;
wire [1:0] wbs_d_gpio0_bte_i;
wire [wbs_d_gpio0_data_width-1:0] wbs_d_gpio0_dat_o;
wire wbs_d_gpio0_ack_o;
wire wbs_d_gpio0_err_o;
wire wbs_d_gpio0_rty_o;
 
// eth0 slave wires
wire [31:0] wbs_d_eth0_adr_i;
wire [wbs_d_eth0_data_width-1:0] wbs_d_eth0_dat_i;
wire [3:0] wbs_d_eth0_sel_i;
wire wbs_d_eth0_we_i;
wire wbs_d_eth0_cyc_i;
wire wbs_d_eth0_stb_i;
wire [2:0] wbs_d_eth0_cti_i;
wire [1:0] wbs_d_eth0_bte_i;
wire [wbs_d_eth0_data_width-1:0] wbs_d_eth0_dat_o;
wire wbs_d_eth0_ack_o;
wire wbs_d_eth0_err_o;
wire wbs_d_eth0_rty_o;
 
// eth0 master wires
wire [wbm_eth0_addr_width-1:0] wbm_eth0_adr_o;
wire [wbm_eth0_data_width-1:0] wbm_eth0_dat_o;
wire [3:0] wbm_eth0_sel_o;
wire wbm_eth0_we_o;
wire wbm_eth0_cyc_o;
wire wbm_eth0_stb_o;
wire [2:0] wbm_eth0_cti_o;
wire [1:0] wbm_eth0_bte_o;
wire [wbm_eth0_data_width-1:0] wbm_eth0_dat_i;
wire wbm_eth0_ack_i;
wire wbm_eth0_err_i;
wire wbm_eth0_rty_i;
 
 
 
//
// Wishbone instruction bus arbiter
//
arbiter_ibus arbiter_ibus0
(
// Instruction Bus Master
// Inputs to arbiter from master
.wbm_adr_o (wbm_i_or12_adr_o),
.wbm_dat_o (wbm_i_or12_dat_o),
.wbm_sel_o (wbm_i_or12_sel_o),
.wbm_we_o (wbm_i_or12_we_o),
.wbm_cyc_o (wbm_i_or12_cyc_o),
.wbm_stb_o (wbm_i_or12_stb_o),
.wbm_cti_o (wbm_i_or12_cti_o),
.wbm_bte_o (wbm_i_or12_bte_o),
// Outputs to master from arbiter
.wbm_dat_i (wbm_i_or12_dat_i),
.wbm_ack_i (wbm_i_or12_ack_i),
.wbm_err_i (wbm_i_or12_err_i),
.wbm_rty_i (wbm_i_or12_rty_i),
// Slave 0
// Inputs to slave from arbiter
.wbs0_adr_i (wbs_i_rom0_adr_i),
.wbs0_dat_i (wbs_i_rom0_dat_i),
.wbs0_sel_i (wbs_i_rom0_sel_i),
.wbs0_we_i (wbs_i_rom0_we_i),
.wbs0_cyc_i (wbs_i_rom0_cyc_i),
.wbs0_stb_i (wbs_i_rom0_stb_i),
.wbs0_cti_i (wbs_i_rom0_cti_i),
.wbs0_bte_i (wbs_i_rom0_bte_i),
// Outputs from slave to arbiter
.wbs0_dat_o (wbs_i_rom0_dat_o),
.wbs0_ack_o (wbs_i_rom0_ack_o),
.wbs0_err_o (wbs_i_rom0_err_o),
.wbs0_rty_o (wbs_i_rom0_rty_o),
 
// Slave 1
// Inputs to slave from arbiter
.wbs1_adr_i (wbs_i_mc0_adr_i),
.wbs1_dat_i (wbs_i_mc0_dat_i),
.wbs1_sel_i (wbs_i_mc0_sel_i),
.wbs1_we_i (wbs_i_mc0_we_i),
.wbs1_cyc_i (wbs_i_mc0_cyc_i),
.wbs1_stb_i (wbs_i_mc0_stb_i),
.wbs1_cti_i (wbs_i_mc0_cti_i),
.wbs1_bte_i (wbs_i_mc0_bte_i),
// Outputs from slave to arbiter
.wbs1_dat_o (wbs_i_mc0_dat_o),
.wbs1_ack_o (wbs_i_mc0_ack_o),
.wbs1_err_o (wbs_i_mc0_err_o),
.wbs1_rty_o (wbs_i_mc0_rty_o),
 
// Clock, reset inputs
.wb_clk (wb_clk),
.wb_rst (wb_rst));
 
defparam arbiter_ibus0.wb_addr_match_width = ibus_arb_addr_match_width;
 
defparam arbiter_ibus0.slave0_adr = ibus_arb_slave0_adr; // FLASH ROM
defparam arbiter_ibus0.slave1_adr = ibus_arb_slave1_adr; // Main memory
 
//
// Wishbone data bus arbiter
//
arbiter_dbus arbiter_dbus0
(
// Master 0
// Inputs to arbiter from master
.wbm0_adr_o (wbm_d_or12_adr_o),
.wbm0_dat_o (wbm_d_or12_dat_o),
.wbm0_sel_o (wbm_d_or12_sel_o),
.wbm0_we_o (wbm_d_or12_we_o),
.wbm0_cyc_o (wbm_d_or12_cyc_o),
.wbm0_stb_o (wbm_d_or12_stb_o),
.wbm0_cti_o (wbm_d_or12_cti_o),
.wbm0_bte_o (wbm_d_or12_bte_o),
// Outputs to master from arbiter
.wbm0_dat_i (wbm_d_or12_dat_i),
.wbm0_ack_i (wbm_d_or12_ack_i),
.wbm0_err_i (wbm_d_or12_err_i),
.wbm0_rty_i (wbm_d_or12_rty_i),
 
// Master 0
// Inputs to arbiter from master
.wbm1_adr_o (wbm_d_dbg_adr_o),
.wbm1_dat_o (wbm_d_dbg_dat_o),
.wbm1_we_o (wbm_d_dbg_we_o),
.wbm1_cyc_o (wbm_d_dbg_cyc_o),
.wbm1_sel_o (wbm_d_dbg_sel_o),
.wbm1_stb_o (wbm_d_dbg_stb_o),
.wbm1_cti_o (wbm_d_dbg_cti_o),
.wbm1_bte_o (wbm_d_dbg_bte_o),
// Outputs to master from arbiter
.wbm1_dat_i (wbm_d_dbg_dat_i),
.wbm1_ack_i (wbm_d_dbg_ack_i),
.wbm1_err_i (wbm_d_dbg_err_i),
.wbm1_rty_i (wbm_d_dbg_rty_i),
 
// Slaves
.wbs0_adr_i (wbs_d_mc0_adr_i),
.wbs0_dat_i (wbs_d_mc0_dat_i),
.wbs0_sel_i (wbs_d_mc0_sel_i),
.wbs0_we_i (wbs_d_mc0_we_i),
.wbs0_cyc_i (wbs_d_mc0_cyc_i),
.wbs0_stb_i (wbs_d_mc0_stb_i),
.wbs0_cti_i (wbs_d_mc0_cti_i),
.wbs0_bte_i (wbs_d_mc0_bte_i),
.wbs0_dat_o (wbs_d_mc0_dat_o),
.wbs0_ack_o (wbs_d_mc0_ack_o),
.wbs0_err_o (wbs_d_mc0_err_o),
.wbs0_rty_o (wbs_d_mc0_rty_o),
 
.wbs1_adr_i (wbs_d_eth0_adr_i),
.wbs1_dat_i (wbs_d_eth0_dat_i),
.wbs1_sel_i (wbs_d_eth0_sel_i),
.wbs1_we_i (wbs_d_eth0_we_i),
.wbs1_cyc_i (wbs_d_eth0_cyc_i),
.wbs1_stb_i (wbs_d_eth0_stb_i),
.wbs1_cti_i (wbs_d_eth0_cti_i),
.wbs1_bte_i (wbs_d_eth0_bte_i),
.wbs1_dat_o (wbs_d_eth0_dat_o),
.wbs1_ack_o (wbs_d_eth0_ack_o),
.wbs1_err_o (wbs_d_eth0_err_o),
.wbs1_rty_o (wbs_d_eth0_rty_o),
.wbs2_adr_i (wbm_b_d_adr_o),
.wbs2_dat_i (wbm_b_d_dat_o),
.wbs2_sel_i (wbm_b_d_sel_o),
.wbs2_we_i (wbm_b_d_we_o),
.wbs2_cyc_i (wbm_b_d_cyc_o),
.wbs2_stb_i (wbm_b_d_stb_o),
.wbs2_cti_i (wbm_b_d_cti_o),
.wbs2_bte_i (wbm_b_d_bte_o),
.wbs2_dat_o (wbm_b_d_dat_i),
.wbs2_ack_o (wbm_b_d_ack_i),
.wbs2_err_o (wbm_b_d_err_i),
.wbs2_rty_o (wbm_b_d_rty_i),
 
// Clock, reset inputs
.wb_clk (wb_clk),
.wb_rst (wb_rst));
 
// These settings are from top level params file
defparam arbiter_dbus0.wb_addr_match_width = dbus_arb_wb_addr_match_width;
defparam arbiter_dbus0.wb_num_slaves = dbus_arb_wb_num_slaves;
defparam arbiter_dbus0.slave0_adr = dbus_arb_slave0_adr;
defparam arbiter_dbus0.slave1_adr = dbus_arb_slave1_adr;
 
//
// Wishbone byte-wide bus arbiter
//
arbiter_bytebus arbiter_bytebus0
(
 
// Master 0
// Inputs to arbiter from master
.wbm0_adr_o (wbm_b_d_adr_o),
.wbm0_dat_o (wbm_b_d_dat_o),
.wbm0_sel_o (wbm_b_d_sel_o),
.wbm0_we_o (wbm_b_d_we_o),
.wbm0_cyc_o (wbm_b_d_cyc_o),
.wbm0_stb_o (wbm_b_d_stb_o),
.wbm0_cti_o (wbm_b_d_cti_o),
.wbm0_bte_o (wbm_b_d_bte_o),
// Outputs to master from arbiter
.wbm0_dat_i (wbm_b_d_dat_i),
.wbm0_ack_i (wbm_b_d_ack_i),
.wbm0_err_i (wbm_b_d_err_i),
.wbm0_rty_i (wbm_b_d_rty_i),
 
// Byte bus slaves
.wbs0_adr_i (wbs_d_uart0_adr_i),
.wbs0_dat_i (wbs_d_uart0_dat_i),
.wbs0_we_i (wbs_d_uart0_we_i),
.wbs0_cyc_i (wbs_d_uart0_cyc_i),
.wbs0_stb_i (wbs_d_uart0_stb_i),
.wbs0_cti_i (wbs_d_uart0_cti_i),
.wbs0_bte_i (wbs_d_uart0_bte_i),
.wbs0_dat_o (wbs_d_uart0_dat_o),
.wbs0_ack_o (wbs_d_uart0_ack_o),
.wbs0_err_o (wbs_d_uart0_err_o),
.wbs0_rty_o (wbs_d_uart0_rty_o),
 
.wbs1_adr_i (wbs_d_gpio0_adr_i),
.wbs1_dat_i (wbs_d_gpio0_dat_i),
.wbs1_we_i (wbs_d_gpio0_we_i),
.wbs1_cyc_i (wbs_d_gpio0_cyc_i),
.wbs1_stb_i (wbs_d_gpio0_stb_i),
.wbs1_cti_i (wbs_d_gpio0_cti_i),
.wbs1_bte_i (wbs_d_gpio0_bte_i),
.wbs1_dat_o (wbs_d_gpio0_dat_o),
.wbs1_ack_o (wbs_d_gpio0_ack_o),
.wbs1_err_o (wbs_d_gpio0_err_o),
.wbs1_rty_o (wbs_d_gpio0_rty_o),
 
.wbs2_adr_i (wbs_d_i2c0_adr_i),
.wbs2_dat_i (wbs_d_i2c0_dat_i),
.wbs2_we_i (wbs_d_i2c0_we_i),
.wbs2_cyc_i (wbs_d_i2c0_cyc_i),
.wbs2_stb_i (wbs_d_i2c0_stb_i),
.wbs2_cti_i (wbs_d_i2c0_cti_i),
.wbs2_bte_i (wbs_d_i2c0_bte_i),
.wbs2_dat_o (wbs_d_i2c0_dat_o),
.wbs2_ack_o (wbs_d_i2c0_ack_o),
.wbs2_err_o (wbs_d_i2c0_err_o),
.wbs2_rty_o (wbs_d_i2c0_rty_o),
 
.wbs3_adr_i (wbs_d_i2c1_adr_i),
.wbs3_dat_i (wbs_d_i2c1_dat_i),
.wbs3_we_i (wbs_d_i2c1_we_i),
.wbs3_cyc_i (wbs_d_i2c1_cyc_i),
.wbs3_stb_i (wbs_d_i2c1_stb_i),
.wbs3_cti_i (wbs_d_i2c1_cti_i),
.wbs3_bte_i (wbs_d_i2c1_bte_i),
.wbs3_dat_o (wbs_d_i2c1_dat_o),
.wbs3_ack_o (wbs_d_i2c1_ack_o),
.wbs3_err_o (wbs_d_i2c1_err_o),
.wbs3_rty_o (wbs_d_i2c1_rty_o),
 
.wbs4_adr_i (wbs_d_spi0_adr_i),
.wbs4_dat_i (wbs_d_spi0_dat_i),
.wbs4_we_i (wbs_d_spi0_we_i),
.wbs4_cyc_i (wbs_d_spi0_cyc_i),
.wbs4_stb_i (wbs_d_spi0_stb_i),
.wbs4_cti_i (wbs_d_spi0_cti_i),
.wbs4_bte_i (wbs_d_spi0_bte_i),
.wbs4_dat_o (wbs_d_spi0_dat_o),
.wbs4_ack_o (wbs_d_spi0_ack_o),
.wbs4_err_o (wbs_d_spi0_err_o),
.wbs4_rty_o (wbs_d_spi0_rty_o),
 
// Clock, reset inputs
.wb_clk (wb_clk),
.wb_rst (wb_rst));
 
defparam arbiter_bytebus0.wb_addr_match_width = bbus_arb_wb_addr_match_width;
defparam arbiter_bytebus0.wb_num_slaves = bbus_arb_wb_num_slaves;
 
defparam arbiter_bytebus0.slave0_adr = bbus_arb_slave0_adr;
defparam arbiter_bytebus0.slave1_adr = bbus_arb_slave1_adr;
defparam arbiter_bytebus0.slave2_adr = bbus_arb_slave2_adr;
defparam arbiter_bytebus0.slave3_adr = bbus_arb_slave3_adr;
defparam arbiter_bytebus0.slave4_adr = bbus_arb_slave4_adr;
 
 
`ifdef JTAG_DEBUG
////////////////////////////////////////////////////////////////////////
//
// JTAG TAP
//
////////////////////////////////////////////////////////////////////////
 
//
// Wires
//
wire dbg_if_select;
wire dbg_if_tdo;
wire jtag_tap_tdo;
wire jtag_tap_shift_dr, jtag_tap_pause_dr,
jtag_tap_upate_dr, jtag_tap_capture_dr;
//
// Instantiation
//
 
jtag_tap jtag_tap0
(
// Ports to pads
.tdo_pad_o (tdo_pad_o),
.tms_pad_i (tms_pad_i),
.tck_pad_i (dbg_tck),
.trst_pad_i (async_rst),
.tdi_pad_i (tdi_pad_i),
.tdo_padoe_o (tdo_padoe_o),
.tdo_o (jtag_tap_tdo),
 
.shift_dr_o (jtag_tap_shift_dr),
.pause_dr_o (jtag_tap_pause_dr),
.update_dr_o (jtag_tap_update_dr),
.capture_dr_o (jtag_tap_capture_dr),
.extest_select_o (),
.sample_preload_select_o (),
.mbist_select_o (),
.debug_select_o (dbg_if_select),
 
.bs_chain_tdi_i (1'b0),
.mbist_tdi_i (1'b0),
.debug_tdi_i (dbg_if_tdo)
);
////////////////////////////////////////////////////////////////////////
`endif // `ifdef JTAG_DEBUG
 
////////////////////////////////////////////////////////////////////////
//
// OpenRISC processor
//
////////////////////////////////////////////////////////////////////////
 
//
// Wires
//
wire [30:0] or1200_pic_ints;
 
wire [31:0] or1200_dbg_dat_i;
wire [31:0] or1200_dbg_adr_i;
wire or1200_dbg_we_i;
wire or1200_dbg_stb_i;
wire or1200_dbg_ack_o;
wire [31:0] or1200_dbg_dat_o;
wire or1200_dbg_stall_i;
wire or1200_dbg_ewt_i;
wire [3:0] or1200_dbg_lss_o;
wire [1:0] or1200_dbg_is_o;
wire [10:0] or1200_dbg_wp_o;
wire or1200_dbg_bp_o;
wire or1200_dbg_rst;
wire or1200_clk, or1200_rst;
wire sig_tick;
//
// Assigns
//
assign or1200_clk = wb_clk;
assign or1200_rst = wb_rst | or1200_dbg_rst;
 
//
// Instantiation
//
or1200_top or1200_top0
(
// Instruction bus, clocks, reset
.iwb_clk_i (wb_clk),
.iwb_rst_i (wb_rst),
.iwb_ack_i (wbm_i_or12_ack_i),
.iwb_err_i (wbm_i_or12_err_i),
.iwb_rty_i (wbm_i_or12_rty_i),
.iwb_dat_i (wbm_i_or12_dat_i),
.iwb_cyc_o (wbm_i_or12_cyc_o),
.iwb_adr_o (wbm_i_or12_adr_o),
.iwb_stb_o (wbm_i_or12_stb_o),
.iwb_we_o (wbm_i_or12_we_o),
.iwb_sel_o (wbm_i_or12_sel_o),
.iwb_dat_o (wbm_i_or12_dat_o),
.iwb_cti_o (wbm_i_or12_cti_o),
.iwb_bte_o (wbm_i_or12_bte_o),
// Data bus, clocks, reset
.dwb_clk_i (wb_clk),
.dwb_rst_i (wb_rst),
.dwb_ack_i (wbm_d_or12_ack_i),
.dwb_err_i (wbm_d_or12_err_i),
.dwb_rty_i (wbm_d_or12_rty_i),
.dwb_dat_i (wbm_d_or12_dat_i),
 
.dwb_cyc_o (wbm_d_or12_cyc_o),
.dwb_adr_o (wbm_d_or12_adr_o),
.dwb_stb_o (wbm_d_or12_stb_o),
.dwb_we_o (wbm_d_or12_we_o),
.dwb_sel_o (wbm_d_or12_sel_o),
.dwb_dat_o (wbm_d_or12_dat_o),
.dwb_cti_o (wbm_d_or12_cti_o),
.dwb_bte_o (wbm_d_or12_bte_o),
// Debug interface ports
.dbg_stall_i (or1200_dbg_stall_i),
//.dbg_ewt_i (or1200_dbg_ewt_i),
.dbg_ewt_i (1'b0),
.dbg_lss_o (or1200_dbg_lss_o),
.dbg_is_o (or1200_dbg_is_o),
.dbg_wp_o (or1200_dbg_wp_o),
.dbg_bp_o (or1200_dbg_bp_o),
 
.dbg_adr_i (or1200_dbg_adr_i),
.dbg_we_i (or1200_dbg_we_i ),
.dbg_stb_i (or1200_dbg_stb_i),
.dbg_dat_i (or1200_dbg_dat_i),
.dbg_dat_o (or1200_dbg_dat_o),
.dbg_ack_o (or1200_dbg_ack_o),
.pm_clksd_o (),
.pm_dc_gate_o (),
.pm_ic_gate_o (),
.pm_dmmu_gate_o (),
.pm_immu_gate_o (),
.pm_tt_gate_o (),
.pm_cpu_gate_o (),
.pm_wakeup_o (),
.pm_lvolt_o (),
 
// Core clocks, resets
.clk_i (or1200_clk),
.rst_i (or1200_rst),
.clmode_i (2'b00),
// Interrupts
.pic_ints_i (or1200_pic_ints),
.sig_tick(sig_tick),
/*
.mbist_so_o (),
.mbist_si_i (0),
.mbist_ctrl_i (0),
*/
 
.pm_cpustall_i (1'b0)
 
);
////////////////////////////////////////////////////////////////////////
 
 
`ifdef JTAG_DEBUG
////////////////////////////////////////////////////////////////////////
//
// OR1200 Debug Interface
//
////////////////////////////////////////////////////////////////////////
dbg_if dbg_if0
(
// OR1200 interface
.cpu0_clk_i (or1200_clk),
.cpu0_rst_o (or1200_dbg_rst),
.cpu0_addr_o (or1200_dbg_adr_i),
.cpu0_data_o (or1200_dbg_dat_i),
.cpu0_stb_o (or1200_dbg_stb_i),
.cpu0_we_o (or1200_dbg_we_i),
.cpu0_data_i (or1200_dbg_dat_o),
.cpu0_ack_i (or1200_dbg_ack_o),
 
 
.cpu0_stall_o (or1200_dbg_stall_i),
.cpu0_bp_i (or1200_dbg_bp_o),
// TAP interface
.tck_i (dbg_tck),
.tdi_i (jtag_tap_tdo),
.tdo_o (dbg_if_tdo),
.rst_i (wb_rst),
.shift_dr_i (jtag_tap_shift_dr),
.pause_dr_i (jtag_tap_pause_dr),
.update_dr_i (jtag_tap_update_dr),
.debug_select_i (dbg_if_select),
 
// Wishbone debug master
.wb_clk_i (wb_clk),
.wb_dat_i (wbm_d_dbg_dat_i),
.wb_ack_i (wbm_d_dbg_ack_i),
.wb_err_i (wbm_d_dbg_err_i),
.wb_adr_o (wbm_d_dbg_adr_o),
.wb_dat_o (wbm_d_dbg_dat_o),
.wb_cyc_o (wbm_d_dbg_cyc_o),
.wb_stb_o (wbm_d_dbg_stb_o),
.wb_sel_o (wbm_d_dbg_sel_o),
.wb_we_o (wbm_d_dbg_we_o ),
.wb_cti_o (wbm_d_dbg_cti_o),
.wb_cab_o (/* UNUSED */),
.wb_bte_o (wbm_d_dbg_bte_o)
);
////////////////////////////////////////////////////////////////////////
`else // !`ifdef JTAG_DEBUG
 
assign wbm_d_dbg_adr_o = 0;
assign wbm_d_dbg_dat_o = 0;
assign wbm_d_dbg_cyc_o = 0;
assign wbm_d_dbg_stb_o = 0;
assign wbm_d_dbg_sel_o = 0;
assign wbm_d_dbg_we_o = 0;
assign wbm_d_dbg_cti_o = 0;
assign wbm_d_dbg_bte_o = 0;
 
assign or1200_dbg_adr_i = 0;
assign or1200_dbg_dat_i = 0;
assign or1200_dbg_stb_i = 0;
assign or1200_dbg_we_i = 0;
assign or1200_dbg_stall_i = 0;
////////////////////////////////////////////////////////////////////////
`endif // !`ifdef JTAG_DEBUG
`ifdef XILINX_DDR2
////////////////////////////////////////////////////////////////////////
//
// Xilinx MIG DDR2 controller, Wishbone interface
//
////////////////////////////////////////////////////////////////////////
xilinx_ddr2 xilinx_ddr2_0
(
.wbm0_adr_i (wbm_eth0_adr_o),
.wbm0_bte_i (wbm_eth0_bte_o),
.wbm0_cti_i (wbm_eth0_cti_o),
.wbm0_cyc_i (wbm_eth0_cyc_o),
.wbm0_dat_i (wbm_eth0_dat_o),
.wbm0_sel_i (wbm_eth0_sel_o),
.wbm0_stb_i (wbm_eth0_stb_o),
.wbm0_we_i (wbm_eth0_we_o),
.wbm0_ack_o (wbm_eth0_ack_i),
.wbm0_err_o (wbm_eth0_err_i),
.wbm0_rty_o (wbm_eth0_rty_i),
.wbm0_dat_o (wbm_eth0_dat_i),
.wbm1_adr_i (wbs_d_mc0_adr_i),
.wbm1_bte_i (wbs_d_mc0_bte_i),
.wbm1_cti_i (wbs_d_mc0_cti_i),
.wbm1_cyc_i (wbs_d_mc0_cyc_i),
.wbm1_dat_i (wbs_d_mc0_dat_i),
.wbm1_sel_i (wbs_d_mc0_sel_i),
.wbm1_stb_i (wbs_d_mc0_stb_i),
.wbm1_we_i (wbs_d_mc0_we_i),
.wbm1_ack_o (wbs_d_mc0_ack_o),
.wbm1_err_o (wbs_d_mc0_err_o),
.wbm1_rty_o (wbs_d_mc0_rty_o),
.wbm1_dat_o (wbs_d_mc0_dat_o),
.wbm2_adr_i (wbs_i_mc0_adr_i),
.wbm2_bte_i (wbs_i_mc0_bte_i),
.wbm2_cti_i (wbs_i_mc0_cti_i),
.wbm2_cyc_i (wbs_i_mc0_cyc_i),
.wbm2_dat_i (wbs_i_mc0_dat_i),
.wbm2_sel_i (wbs_i_mc0_sel_i),
.wbm2_stb_i (wbs_i_mc0_stb_i),
.wbm2_we_i (wbs_i_mc0_we_i),
.wbm2_ack_o (wbs_i_mc0_ack_o),
.wbm2_err_o (wbs_i_mc0_err_o),
.wbm2_rty_o (wbs_i_mc0_rty_o),
.wbm2_dat_o (wbs_i_mc0_dat_o),
.wb_clk (wb_clk),
.wb_rst (wb_rst),
.ddr2_a (ddr2_a[12:0]),
.ddr2_ba (ddr2_ba[1:0]),
.ddr2_ras_n (ddr2_ras_n),
.ddr2_cas_n (ddr2_cas_n),
.ddr2_we_n (ddr2_we_n),
.ddr2_cs_n (ddr2_cs_n),
.ddr2_odt (ddr2_odt),
.ddr2_cke (ddr2_cke),
.ddr2_dm (ddr2_dm[7:0]),
.ddr2_ck (ddr2_ck[1:0]),
.ddr2_ck_n (ddr2_ck_n[1:0]),
.ddr2_dq (ddr2_dq[63:0]),
.ddr2_dqs (ddr2_dqs[7:0]),
.ddr2_dqs_n (ddr2_dqs_n[7:0]),
.ddr2_if_clk (ddr2_if_clk),
.clk200 (clk200),
.ddr2_if_rst (ddr2_if_rst)
);
`endif
 
 
////////////////////////////////////////////////////////////////////////
//
// ROM
//
////////////////////////////////////////////////////////////////////////
rom rom0
(
.wb_dat_o (wbs_i_rom0_dat_o),
.wb_ack_o (wbs_i_rom0_ack_o),
.wb_adr_i (wbs_i_rom0_adr_i[(wbs_i_rom0_addr_width+2)-1:2]),
.wb_stb_i (wbs_i_rom0_stb_i),
.wb_cyc_i (wbs_i_rom0_cyc_i),
.wb_cti_i (wbs_i_rom0_cti_i),
.wb_bte_i (wbs_i_rom0_bte_i),
.wb_clk (wb_clk),
.wb_rst (wb_rst));
 
defparam rom0.addr_width = wbs_i_rom0_addr_width;
 
assign wbs_i_rom0_err_o = 0;
assign wbs_i_rom0_rty_o = 0;
////////////////////////////////////////////////////////////////////////
 
`ifdef RAM_WB
////////////////////////////////////////////////////////////////////////
//
// Generic RAM
//
////////////////////////////////////////////////////////////////////////
 
ram_wb ram_wb0
(
// Wishbone slave interface 0
.wbm0_dat_i (wbs_i_mc0_dat_i),
.wbm0_adr_i (wbs_i_mc0_adr_i),
.wbm0_sel_i (wbs_i_mc0_sel_i),
.wbm0_cti_i (wbs_i_mc0_cti_i),
.wbm0_bte_i (wbs_i_mc0_bte_i),
.wbm0_we_i (wbs_i_mc0_we_i ),
.wbm0_cyc_i (wbs_i_mc0_cyc_i),
.wbm0_stb_i (wbs_i_mc0_stb_i),
.wbm0_dat_o (wbs_i_mc0_dat_o),
.wbm0_ack_o (wbs_i_mc0_ack_o),
.wbm0_err_o (),
.wbm0_rty_o (),
// Wishbone slave interface 1
.wbm1_dat_i (wbs_d_mc0_dat_i),
.wbm1_adr_i (wbs_d_mc0_adr_i),
.wbm1_sel_i (wbs_d_mc0_sel_i),
.wbm1_cti_i (wbs_d_mc0_cti_i),
.wbm1_bte_i (wbs_d_mc0_bte_i),
.wbm1_we_i (wbs_d_mc0_we_i ),
.wbm1_cyc_i (wbs_d_mc0_cyc_i),
.wbm1_stb_i (wbs_d_mc0_stb_i),
.wbm1_dat_o (wbs_d_mc0_dat_o),
.wbm1_ack_o (wbs_d_mc0_ack_o),
.wbm1_err_o (),
.wbm1_rty_o (),
// Clock, reset
.wb_clk_i (wb_clk),
.wb_rst_i (wb_rst));
 
assign wbs_i_mc0_err_o = 0;
assign wbs_i_mc0_rty_o = 0;
 
assign wbs_d_mc0_err_o = 0;
assign wbs_d_mc0_rty_o = 0;
defparam ram_wb0.aw = wb_aw;
defparam ram_wb0.dw = wb_dw;
defparam ram_wb0.mem_span = internal_sram_mem_span;
defparam ram_wb0.adr_width_for_span = internal_sram_adr_width_for_span;
////////////////////////////////////////////////////////////////////////
`endif // `ifdef RAM_WB
 
 
`ifdef ETH0
 
//
// Wires
//
wire eth0_irq;
wire [3:0] eth0_mtxd;
wire eth0_mtxen;
wire eth0_mtxerr;
wire eth0_mtx_clk;
wire eth0_mrx_clk;
wire [3:0] eth0_mrxd;
wire eth0_mrxdv;
wire eth0_mrxerr;
wire eth0_mcoll;
wire eth0_mcrs;
wire eth0_speed;
wire eth0_duplex;
wire eth0_link;
// Management interface wires
wire eth0_md_i;
wire eth0_md_o;
wire eth0_md_oe;
 
 
//
// assigns
 
// Hook up MII wires
assign eth0_mtx_clk = eth0_tx_clk;
assign eth0_tx_data = eth0_mtxd[3:0];
assign eth0_tx_en = eth0_mtxen;
assign eth0_tx_er = eth0_mtxerr;
assign eth0_mrxd[3:0] = eth0_rx_data;
assign eth0_mrxdv = eth0_dv;
assign eth0_mrxerr = eth0_rx_er;
assign eth0_mrx_clk = eth0_rx_clk;
assign eth0_mcoll = eth0_col;
assign eth0_mcrs = eth0_crs;
 
`ifdef XILINX
// Xilinx primitive for MDIO tristate
IOBUF iobuf_phy_smi_data
(
// Outputs
.O (eth0_md_i),
// Inouts
.IO (eth0_md_pad_io),
// Inputs
.I (eth0_md_o),
.T (!eth0_md_oe));
`else // !`ifdef XILINX
// Generic technology tristate control for management interface
assign eth0_md_pad_io = eth0_md_oe ? eth0_md_o : 1'bz;
assign eth0_md_i = eth0_md_pad_io;
`endif // !`ifdef XILINX
 
`ifdef ETH0_PHY_RST
assign eth0_rst_n_o = !wb_rst;
`endif
ethmac ethmac0
(
// Wishbone Slave interface
.wb_clk_i (wb_clk),
.wb_rst_i (wb_rst),
.wb_dat_i (wbs_d_eth0_dat_i[31:0]),
.wb_adr_i (wbs_d_eth0_adr_i[wbs_d_eth0_addr_width-1:2]),
.wb_sel_i (wbs_d_eth0_sel_i[3:0]),
.wb_we_i (wbs_d_eth0_we_i),
.wb_cyc_i (wbs_d_eth0_cyc_i),
.wb_stb_i (wbs_d_eth0_stb_i),
.wb_dat_o (wbs_d_eth0_dat_o[31:0]),
.wb_err_o (wbs_d_eth0_err_o),
.wb_ack_o (wbs_d_eth0_ack_o),
// Wishbone Master Interface
.m_wb_adr_o (wbm_eth0_adr_o[31:0]),
.m_wb_sel_o (wbm_eth0_sel_o[3:0]),
.m_wb_we_o (wbm_eth0_we_o),
.m_wb_dat_o (wbm_eth0_dat_o[31:0]),
.m_wb_cyc_o (wbm_eth0_cyc_o),
.m_wb_stb_o (wbm_eth0_stb_o),
.m_wb_cti_o (wbm_eth0_cti_o[2:0]),
.m_wb_bte_o (wbm_eth0_bte_o[1:0]),
.m_wb_dat_i (wbm_eth0_dat_i[31:0]),
.m_wb_ack_i (wbm_eth0_ack_i),
.m_wb_err_i (wbm_eth0_err_i),
 
// Ethernet MII interface
// Transmit
.mtxd_pad_o (eth0_mtxd[3:0]),
.mtxen_pad_o (eth0_mtxen),
.mtxerr_pad_o (eth0_mtxerr),
.mtx_clk_pad_i (eth0_mtx_clk),
// Receive
.mrx_clk_pad_i (eth0_mrx_clk),
.mrxd_pad_i (eth0_mrxd[3:0]),
.mrxdv_pad_i (eth0_mrxdv),
.mrxerr_pad_i (eth0_mrxerr),
.mcoll_pad_i (eth0_mcoll),
.mcrs_pad_i (eth0_mcrs),
// Management interface
.md_pad_i (eth0_md_i),
.mdc_pad_o (eth0_mdc_pad_o),
.md_pad_o (eth0_md_o),
.md_padoe_o (eth0_md_oe),
 
// Processor interrupt
.int_o (eth0_irq)
/*
.mbist_so_o (),
.mbist_si_i (),
.mbist_ctrl_i ()
*/
);
 
assign wbs_d_eth0_rty_o = 0;
 
`else
assign wbs_d_eth0_dat_o = 0;
assign wbs_d_eth0_err_o = 0;
assign wbs_d_eth0_ack_o = 0;
assign wbs_d_eth0_rty_o = 0;
assign wbm_eth0_adr_o = 0;
assign wbm_eth0_sel_o = 0;
assign wbm_eth0_we_o = 0;
assign wbm_eth0_dat_o = 0;
assign wbm_eth0_cyc_o = 0;
assign wbm_eth0_stb_o = 0;
assign wbm_eth0_cti_o = 0;
assign wbm_eth0_bte_o = 0;
`endif
`ifdef UART0
////////////////////////////////////////////////////////////////////////
//
// UART0
//
////////////////////////////////////////////////////////////////////////
 
//
// Wires
//
wire uart0_srx;
wire uart0_stx;
wire uart0_irq;
 
//
// Assigns
//
assign wbs_d_uart0_err_o = 0;
assign wbs_d_uart0_rty_o = 0;
 
// Two UART lines coming to single one (ensure they go high when unconnected)
assign uart_srx = uart0_srx_pad_i & uart0_srx_expheader_pad_i;
assign uart0_stx_pad_o = uart0_stx;
assign uart0_stx_expheader_pad_o = uart0_stx;
uart16550 uart16550_0
(
// Wishbone slave interface
.wb_clk_i (wb_clk),
.wb_rst_i (wb_rst),
.wb_adr_i (wbs_d_uart0_adr_i[uart0_addr_width-1:0]),
.wb_dat_i (wbs_d_uart0_dat_i),
.wb_we_i (wbs_d_uart0_we_i),
.wb_stb_i (wbs_d_uart0_stb_i),
.wb_cyc_i (wbs_d_uart0_cyc_i),
//.wb_sel_i (),
.wb_dat_o (wbs_d_uart0_dat_o),
.wb_ack_o (wbs_d_uart0_ack_o),
 
.int_o (uart0_irq),
.stx_pad_o (uart0_stx),
.rts_pad_o (),
.dtr_pad_o (),
// .baud_o (),
// Inputs
.srx_pad_i (uart0_srx),
.cts_pad_i (1'b0),
.dsr_pad_i (1'b0),
.ri_pad_i (1'b0),
.dcd_pad_i (1'b0));
 
////////////////////////////////////////////////////////////////////////
`else // !`ifdef UART0
//
// Assigns
//
assign wbs_d_uart0_err_o = 0;
assign wbs_d_uart0_rty_o = 0;
assign wbs_d_uart0_ack_o = 0;
assign wbs_d_uart0_dat_o = 0;
////////////////////////////////////////////////////////////////////////
`endif // !`ifdef UART0
`ifdef SPI0
////////////////////////////////////////////////////////////////////////
//
// SPI0 controller
//
////////////////////////////////////////////////////////////////////////
 
//
// Wires
//
wire spi0_irq;
 
//
// Assigns
//
assign wbs_d_spi0_err_o = 0;
assign wbs_d_spi0_rty_o = 0;
//assign spi0_hold_n_o = 1;
//assign spi0_w_n_o = 1;
simple_spi spi0
(
// Wishbone slave interface
.clk_i (wb_clk),
.rst_i (wb_rst),
.cyc_i (wbs_d_spi0_cyc_i),
.stb_i (wbs_d_spi0_stb_i),
.adr_i (wbs_d_spi0_adr_i[spi0_wb_adr_width-1:0]),
.we_i (wbs_d_spi0_we_i),
.dat_i (wbs_d_spi0_dat_i),
.dat_o (wbs_d_spi0_dat_o),
.ack_o (wbs_d_spi0_ack_o),
// SPI IRQ
.inta_o (spi0_irq),
// External SPI interface
.sck_o (spi0_sck_o),
.ss_o (spi0_ss_o),
.mosi_o (spi0_mosi_o),
.miso_i (spi0_miso_i)
);
 
defparam spi0.slave_select_width = spi0_ss_width;
////////////////////////////////////////////////////////////////////////
`else // !`ifdef SPI0
 
//
// Assigns
//
assign wbs_d_spi0_dat_o = 0;
assign wbs_d_spi0_ack_o = 0;
assign wbs_d_spi0_err_o = 0;
assign wbs_d_spi0_rty_o = 0;
////////////////////////////////////////////////////////////////////////
`endif // !`ifdef SPI0
 
 
`ifdef I2C0
////////////////////////////////////////////////////////////////////////
//
// i2c controller 0
//
////////////////////////////////////////////////////////////////////////
 
//
// Wires
//
wire i2c0_irq;
wire scl0_pad_o;
wire scl0_padoen_o;
wire sda0_pad_o;
wire sda0_padoen_o;
i2c_master_slave
#
(
.DEFAULT_SLAVE_ADDR(HV0_SADR)
)
i2c_master_slave0
(
.wb_clk_i (wb_clk),
.wb_rst_i (wb_rst),
.arst_i (wb_rst),
.wb_adr_i (wbs_d_i2c0_adr_i[i2c_0_wb_adr_width-1:0]),
.wb_dat_i (wbs_d_i2c0_dat_i),
.wb_we_i (wbs_d_i2c0_we_i ),
.wb_cyc_i (wbs_d_i2c0_cyc_i),
.wb_stb_i (wbs_d_i2c0_stb_i),
.wb_dat_o (wbs_d_i2c0_dat_o),
.wb_ack_o (wbs_d_i2c0_ack_o),
.scl_pad_i (i2c0_scl_io ),
.scl_pad_o (scl0_pad_o ),
.scl_padoen_o (scl0_padoen_o ),
.sda_pad_i (i2c0_sda_io ),
.sda_pad_o (sda0_pad_o ),
.sda_padoen_o (sda0_padoen_o ),
// Interrupt
.wb_inta_o (i2c0_irq)
);
 
assign wbs_d_i2c0_err_o = 0;
assign wbs_d_i2c0_rty_o = 0;
 
// i2c phy lines
assign i2c0_scl_io = scl0_padoen_o ? 1'bz : scl0_pad_o;
assign i2c0_sda_io = sda0_padoen_o ? 1'bz : sda0_pad_o;
 
 
////////////////////////////////////////////////////////////////////////
`else // !`ifdef I2C0
 
assign wbs_d_i2c0_dat_o = 0;
assign wbs_d_i2c0_ack_o = 0;
assign wbs_d_i2c0_err_o = 0;
assign wbs_d_i2c0_rty_o = 0;
 
////////////////////////////////////////////////////////////////////////
`endif // !`ifdef I2C0
 
`ifdef I2C1
////////////////////////////////////////////////////////////////////////
//
// i2c controller 1
//
////////////////////////////////////////////////////////////////////////
 
//
// Wires
//
wire i2c1_irq;
wire scl1_pad_o;
wire scl1_padoen_o;
wire sda1_pad_o;
wire sda1_padoen_o;
 
i2c_master_slave
#
(
.DEFAULT_SLAVE_ADDR(HV1_SADR)
)
i2c_master_slave1
(
.wb_clk_i (wb_clk),
.wb_rst_i (wb_rst),
.arst_i (wb_rst),
.wb_adr_i (wbs_d_i2c1_adr_i[i2c_1_wb_adr_width-1:0]),
.wb_dat_i (wbs_d_i2c1_dat_i),
.wb_we_i (wbs_d_i2c1_we_i ),
.wb_cyc_i (wbs_d_i2c1_cyc_i),
.wb_stb_i (wbs_d_i2c1_stb_i),
.wb_dat_o (wbs_d_i2c1_dat_o),
.wb_ack_o (wbs_d_i2c1_ack_o),
.scl_pad_i (i2c1_scl_io ),
.scl_pad_o (scl1_pad_o ),
.scl_padoen_o (scl1_padoen_o ),
.sda_pad_i (i2c1_sda_io ),
.sda_pad_o (sda1_pad_o ),
.sda_padoen_o (sda1_padoen_o ),
// Interrupt
.wb_inta_o (i2c1_irq)
);
 
assign wbs_d_i2c1_err_o = 0;
assign wbs_d_i2c1_rty_o = 0;
 
// i2c phy lines
assign i2c1_scl_io = scl1_padoen_o ? 1'bz : scl1_pad_o;
assign i2c1_sda_io = sda1_padoen_o ? 1'bz : sda1_pad_o;
 
////////////////////////////////////////////////////////////////////////
`else // !`ifdef I2C1
 
assign wbs_d_i2c1_dat_o = 0;
assign wbs_d_i2c1_ack_o = 0;
assign wbs_d_i2c1_err_o = 0;
assign wbs_d_i2c1_rty_o = 0;
 
////////////////////////////////////////////////////////////////////////
`endif // !`ifdef I2C1
 
`ifdef GPIO0
////////////////////////////////////////////////////////////////////////
//
// GPIO 0
//
////////////////////////////////////////////////////////////////////////
 
gpio gpio0
(
// GPIO bus
.gpio_io (gpio0_io[gpio0_io_width-1:0]),
// Wishbone slave interface
.wb_adr_i (wbs_d_gpio0_adr_i[gpio0_wb_adr_width-1:0]),
.wb_dat_i (wbs_d_gpio0_dat_i),
.wb_we_i (wbs_d_gpio0_we_i),
.wb_cyc_i (wbs_d_gpio0_cyc_i),
.wb_stb_i (wbs_d_gpio0_stb_i),
.wb_cti_i (wbs_d_gpio0_cti_i),
.wb_bte_i (wbs_d_gpio0_bte_i),
.wb_dat_o (wbs_d_gpio0_dat_o),
.wb_ack_o (wbs_d_gpio0_ack_o),
.wb_err_o (wbs_d_gpio0_err_o),
.wb_rty_o (wbs_d_gpio0_rty_o),
.wb_clk (wb_clk),
.wb_rst (wb_rst)
);
 
defparam gpio0.gpio_io_width = gpio0_io_width;
defparam gpio0.gpio_dir_reset_val = gpio0_dir_reset_val;
defparam gpio0.gpio_o_reset_val = gpio0_o_reset_val;
 
////////////////////////////////////////////////////////////////////////
`else // !`ifdef GPIO0
assign wbs_d_gpio0_dat_o = 0;
assign wbs_d_gpio0_ack_o = 0;
assign wbs_d_gpio0_err_o = 0;
assign wbs_d_gpio0_rty_o = 0;
////////////////////////////////////////////////////////////////////////
`endif // !`ifdef GPIO0
////////////////////////////////////////////////////////////////////////
//
// OR1200 Interrupt assignment
//
////////////////////////////////////////////////////////////////////////
assign or1200_pic_ints[0] = 0; // Non-maskable inside OR1200
assign or1200_pic_ints[1] = 0; // Non-maskable inside OR1200
`ifdef UART0
assign or1200_pic_ints[2] = uart0_irq;
`else
assign or1200_pic_ints[2] = 0;
`endif
assign or1200_pic_ints[3] = 0;
`ifdef ETH0
assign or1200_pic_ints[4] = eth0_irq;
`else
assign or1200_pic_ints[4] = 0;
`endif
assign or1200_pic_ints[5] = 0;
`ifdef SPI0
assign or1200_pic_ints[6] = spi0_irq;
`else
assign or1200_pic_ints[6] = 0;
`endif
assign or1200_pic_ints[7] = 0;
assign or1200_pic_ints[8] = 0;
assign or1200_pic_ints[9] = 0;
`ifdef I2C0
assign or1200_pic_ints[10] = i2c0_irq;
`else
assign or1200_pic_ints[10] = 0;
`endif
`ifdef I2C1
assign or1200_pic_ints[11] = i2c1_irq;
`else
assign or1200_pic_ints[11] = 0;
`endif
assign or1200_pic_ints[12] = 0;
assign or1200_pic_ints[13] = 0;
assign or1200_pic_ints[14] = 0;
assign or1200_pic_ints[15] = 0;
assign or1200_pic_ints[16] = 0;
assign or1200_pic_ints[17] = 0;
assign or1200_pic_ints[18] = 0;
assign or1200_pic_ints[19] = 0;
assign or1200_pic_ints[20] = 0;
assign or1200_pic_ints[21] = 0;
assign or1200_pic_ints[22] = 0;
assign or1200_pic_ints[23] = 0;
assign or1200_pic_ints[24] = 0;
assign or1200_pic_ints[25] = 0;
assign or1200_pic_ints[26] = 0;
assign or1200_pic_ints[27] = 0;
assign or1200_pic_ints[28] = 0;
assign or1200_pic_ints[29] = 0;
assign or1200_pic_ints[30] = 0;
endmodule // orpsoc_top
 
 
/verilog/arbiter/arbiter_bytebus.v
0,0 → 1,1192
//////////////////////////////////////////////////////////////////////
/// ////
/// Wishbone arbiter, byte-wide data path, no bursting ////
/// ////
/// Simple arbiter, single master, multiple slave, for byte-wide ////
/// peripherals ////
/// ////
/// Julius Baxter, julius@opencores.org ////
/// ////
//////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2009, 2010 Authors and OPENCORES.ORG ////
//// ////
//// This source file may be used and distributed without ////
//// restriction provided that this copyright statement is not ////
//// removed from the file and that any derivative work contains ////
//// the original copyright notice and the associated disclaimer. ////
//// ////
//// This source file is free software; you can redistribute it ////
//// and/or modify it under the terms of the GNU Lesser General ////
//// Public License as published by the Free Software Foundation; ////
//// either version 2.1 of the License, or (at your option) any ////
//// later version. ////
//// ////
//// This source is distributed in the hope that it will be ////
//// useful, but WITHOUT ANY WARRANTY; without even the implied ////
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ////
//// PURPOSE. See the GNU Lesser General Public License for more ////
//// details. ////
//// ////
//// You should have received a copy of the GNU Lesser General ////
//// Public License along with this source; if not, download it ////
//// from http://www.opencores.org/lgpl.shtml ////
//// ////
//////////////////////////////////////////////////////////////////////
 
//
// Things to update when changing slave config:
//
// 1. Port list
// 2. Port specification
// 3. Slave addr select parameter
// 4. Slave addr selects
// 5. Slave input mux logic
// 6. The four different master out mux logics (dat_o mux, and ack, rty & err)
//
`include "orpsoc-defines.v"
module arbiter_bytebus
(
 
// Master in
wbm0_adr_o,
wbm0_dat_o,
wbm0_sel_o,
wbm0_we_o,
wbm0_cyc_o,
wbm0_stb_o,
wbm0_cti_o,
wbm0_bte_o,
wbm0_dat_i,
wbm0_ack_i,
wbm0_err_i,
wbm0_rty_i,
 
// Slave one
// Wishbone Slave interface
wbs0_adr_i,
wbs0_dat_i,
wbs0_we_i,
wbs0_cyc_i,
wbs0_stb_i,
wbs0_cti_i,
wbs0_bte_i,
wbs0_dat_o,
wbs0_ack_o,
wbs0_err_o,
wbs0_rty_o,
 
// Slave two
// Wishbone Slave interface
wbs1_adr_i,
wbs1_dat_i,
wbs1_we_i,
wbs1_cyc_i,
wbs1_stb_i,
wbs1_cti_i,
wbs1_bte_i,
wbs1_dat_o,
wbs1_ack_o,
wbs1_err_o,
wbs1_rty_o,
 
// Slave three
// Wishbone Slave interface
wbs2_adr_i,
wbs2_dat_i,
wbs2_we_i,
wbs2_cyc_i,
wbs2_stb_i,
wbs2_cti_i,
wbs2_bte_i,
wbs2_dat_o,
wbs2_ack_o,
wbs2_err_o,
wbs2_rty_o,
 
// Slave four
// Wishbone Slave interface
wbs3_adr_i,
wbs3_dat_i,
wbs3_we_i,
wbs3_cyc_i,
wbs3_stb_i,
wbs3_cti_i,
wbs3_bte_i,
wbs3_dat_o,
wbs3_ack_o,
wbs3_err_o,
wbs3_rty_o,
 
// Slave five
// Wishbone Slave interface
wbs4_adr_i,
wbs4_dat_i,
wbs4_we_i,
wbs4_cyc_i,
wbs4_stb_i,
wbs4_cti_i,
wbs4_bte_i,
wbs4_dat_o,
wbs4_ack_o,
wbs4_err_o,
wbs4_rty_o,
/*
// Slave six
// Wishbone Slave interface
wbs5_adr_i,
wbs5_dat_i,
wbs5_we_i,
wbs5_cyc_i,
wbs5_stb_i,
wbs5_cti_i,
wbs5_bte_i,
wbs5_dat_o,
wbs5_ack_o,
wbs5_err_o,
wbs5_rty_o,
 
// Slave seven
// Wishbone Slave interface
wbs6_adr_i,
wbs6_dat_i,
wbs6_we_i,
wbs6_cyc_i,
wbs6_stb_i,
wbs6_cti_i,
wbs6_bte_i,
wbs6_dat_o,
wbs6_ack_o,
wbs6_err_o,
wbs6_rty_o,
 
// Slave eight
// Wishbone Slave interface
wbs7_adr_i,
wbs7_dat_i,
wbs7_we_i,
wbs7_cyc_i,
wbs7_stb_i,
wbs7_cti_i,
wbs7_bte_i,
wbs7_dat_o,
wbs7_ack_o,
wbs7_err_o,
wbs7_rty_o,
 
// Slave nine
// Wishbone Slave interface
wbs8_adr_i,
wbs8_dat_i,
wbs8_we_i,
wbs8_cyc_i,
wbs8_stb_i,
wbs8_cti_i,
wbs8_bte_i,
wbs8_dat_o,
wbs8_ack_o,
wbs8_err_o,
wbs8_rty_o,
 
// Slave ten
// Wishbone Slave interface
wbs9_adr_i,
wbs9_dat_i,
wbs9_we_i,
wbs9_cyc_i,
wbs9_stb_i,
wbs9_cti_i,
wbs9_bte_i,
wbs9_dat_o,
wbs9_ack_o,
wbs9_err_o,
wbs9_rty_o,
 
// Slave eleven
// Wishbone Slave interface
wbs10_adr_i,
wbs10_dat_i,
wbs10_we_i,
wbs10_cyc_i,
wbs10_stb_i,
wbs10_cti_i,
wbs10_bte_i,
wbs10_dat_o,
wbs10_ack_o,
wbs10_err_o,
wbs10_rty_o,
 
// Slave twelve
// Wishbone Slave interface
wbs11_adr_i,
wbs11_dat_i,
wbs11_we_i,
wbs11_cyc_i,
wbs11_stb_i,
wbs11_cti_i,
wbs11_bte_i,
wbs11_dat_o,
wbs11_ack_o,
wbs11_err_o,
wbs11_rty_o,
 
// Slave thirteen
// Wishbone Slave interface
wbs12_adr_i,
wbs12_dat_i,
wbs12_we_i,
wbs12_cyc_i,
wbs12_stb_i,
wbs12_cti_i,
wbs12_bte_i,
wbs12_dat_o,
wbs12_ack_o,
wbs12_err_o,
wbs12_rty_o,
 
// Slave fourteen
// Wishbone Slave interface
wbs13_adr_i,
wbs13_dat_i,
wbs13_we_i,
wbs13_cyc_i,
wbs13_stb_i,
wbs13_cti_i,
wbs13_bte_i,
wbs13_dat_o,
wbs13_ack_o,
wbs13_err_o,
wbs13_rty_o,
 
// Slave fifteen
// Wishbone Slave interface
wbs14_adr_i,
wbs14_dat_i,
wbs14_we_i,
wbs14_cyc_i,
wbs14_stb_i,
wbs14_cti_i,
wbs14_bte_i,
wbs14_dat_o,
wbs14_ack_o,
wbs14_err_o,
wbs14_rty_o,
 
// Slave sixteen
// Wishbone Slave interface
wbs15_adr_i,
wbs15_dat_i,
wbs15_we_i,
wbs15_cyc_i,
wbs15_stb_i,
wbs15_cti_i,
wbs15_bte_i,
wbs15_dat_o,
wbs15_ack_o,
wbs15_err_o,
wbs15_rty_o,
 
// Slave seventeen
// Wishbone Slave interface
wbs16_adr_i,
wbs16_dat_i,
wbs16_we_i,
wbs16_cyc_i,
wbs16_stb_i,
wbs16_cti_i,
wbs16_bte_i,
wbs16_dat_o,
wbs16_ack_o,
wbs16_err_o,
wbs16_rty_o,
 
 
// Slave eighteen
// Wishbone Slave interface
wbs17_adr_i,
wbs17_dat_i,
wbs17_we_i,
wbs17_cyc_i,
wbs17_stb_i,
wbs17_cti_i,
wbs17_bte_i,
wbs17_dat_o,
wbs17_ack_o,
wbs17_err_o,
wbs17_rty_o,
// Slave nineteen
// Wishbone Slave interface
wbs18_adr_i,
wbs18_dat_i,
wbs18_we_i,
wbs18_cyc_i,
wbs18_stb_i,
wbs18_cti_i,
wbs18_bte_i,
wbs18_dat_o,
wbs18_ack_o,
wbs18_err_o,
wbs18_rty_o,
// Slave twenty
// Wishbone Slave interface
wbs19_adr_i,
wbs19_dat_i,
wbs19_we_i,
wbs19_cyc_i,
wbs19_stb_i,
wbs19_cti_i,
wbs19_bte_i,
wbs19_dat_o,
wbs19_ack_o,
wbs19_err_o,
wbs19_rty_o,
*/
wb_clk, wb_rst
);
 
parameter wb_dat_width = 32;
parameter wbs_dat_width = 8;
parameter wb_adr_width = 32;
 
parameter wb_addr_match_width = 8;
 
parameter wb_num_slaves = 20; // Currently can handle up to 20
 
// Slave addresses
parameter slave0_adr = 8'h00;
parameter slave1_adr = 8'h00;
parameter slave2_adr = 8'h00;
parameter slave3_adr = 8'h00;
parameter slave4_adr = 8'h00;
parameter slave5_adr = 8'h00;
parameter slave6_adr = 8'h00;
parameter slave7_adr = 8'h00;
parameter slave8_adr = 8'h00;
parameter slave9_adr = 8'h00;
parameter slave10_adr = 8'h00;
parameter slave11_adr = 8'h00;
parameter slave12_adr = 8'h00;
parameter slave13_adr = 8'h00;
parameter slave14_adr = 8'h00;
parameter slave15_adr = 8'h00;
parameter slave16_adr = 8'h00;
parameter slave17_adr = 8'h00;
parameter slave18_adr = 8'h00;
parameter slave19_adr = 8'h00;
 
`define WB_ARB_ADDR_MATCH_SEL wb_adr_width-1:wb_adr_width-wb_addr_match_width
input wb_clk;
input wb_rst;
// WB Master one
input [wb_adr_width-1:0] wbm0_adr_o;
input [wb_dat_width-1:0] wbm0_dat_o;
input [3:0] wbm0_sel_o;
input wbm0_we_o;
input wbm0_cyc_o;
input wbm0_stb_o;
input [2:0] wbm0_cti_o;
input [1:0] wbm0_bte_o;
output [wb_dat_width-1:0] wbm0_dat_i;
output wbm0_ack_i;
output wbm0_err_i;
output wbm0_rty_i;
// Slave one
// Wishbone Slave interface
output [wb_adr_width-1:0] wbs0_adr_i;
output [wbs_dat_width-1:0] wbs0_dat_i;
output wbs0_we_i;
output wbs0_cyc_i;
output wbs0_stb_i;
output [2:0] wbs0_cti_i;
output [1:0] wbs0_bte_i;
input [wbs_dat_width-1:0] wbs0_dat_o;
input wbs0_ack_o;
input wbs0_err_o;
input wbs0_rty_o;
 
// Wishbone Slave interface
output [wb_adr_width-1:0] wbs1_adr_i;
output [wbs_dat_width-1:0] wbs1_dat_i;
output wbs1_we_i;
output wbs1_cyc_i;
output wbs1_stb_i;
output [2:0] wbs1_cti_i;
output [1:0] wbs1_bte_i;
input [wbs_dat_width-1:0] wbs1_dat_o;
input wbs1_ack_o;
input wbs1_err_o;
input wbs1_rty_o;
 
// Wishbone Slave interface
output [wb_adr_width-1:0] wbs2_adr_i;
output [wbs_dat_width-1:0] wbs2_dat_i;
output wbs2_we_i;
output wbs2_cyc_i;
output wbs2_stb_i;
output [2:0] wbs2_cti_i;
output [1:0] wbs2_bte_i;
input [wbs_dat_width-1:0] wbs2_dat_o;
input wbs2_ack_o;
input wbs2_err_o;
input wbs2_rty_o;
 
// Wishbone Slave interface
output [wb_adr_width-1:0] wbs3_adr_i;
output [wbs_dat_width-1:0] wbs3_dat_i;
output wbs3_we_i;
output wbs3_cyc_i;
output wbs3_stb_i;
output [2:0] wbs3_cti_i;
output [1:0] wbs3_bte_i;
input [wbs_dat_width-1:0] wbs3_dat_o;
input wbs3_ack_o;
input wbs3_err_o;
input wbs3_rty_o;
 
// Wishbone Slave interface
output [wb_adr_width-1:0] wbs4_adr_i;
output [wbs_dat_width-1:0] wbs4_dat_i;
output wbs4_we_i;
output wbs4_cyc_i;
output wbs4_stb_i;
output [2:0] wbs4_cti_i;
output [1:0] wbs4_bte_i;
input [wbs_dat_width-1:0] wbs4_dat_o;
input wbs4_ack_o;
input wbs4_err_o;
input wbs4_rty_o;
/*
// Wishbone Slave interface
output [wb_adr_width-1:0] wbs5_adr_i;
output [wbs_dat_width-1:0] wbs5_dat_i;
output wbs5_we_i;
output wbs5_cyc_i;
output wbs5_stb_i;
output [2:0] wbs5_cti_i;
output [1:0] wbs5_bte_i;
input [wbs_dat_width-1:0] wbs5_dat_o;
input wbs5_ack_o;
input wbs5_err_o;
input wbs5_rty_o;
 
// Wishbone Slave interface
output [wb_adr_width-1:0] wbs6_adr_i;
output [wbs_dat_width-1:0] wbs6_dat_i;
output wbs6_we_i;
output wbs6_cyc_i;
output wbs6_stb_i;
output [2:0] wbs6_cti_i;
output [1:0] wbs6_bte_i;
input [wbs_dat_width-1:0] wbs6_dat_o;
input wbs6_ack_o;
input wbs6_err_o;
input wbs6_rty_o;
 
// Wishbone Slave interface
output [wb_adr_width-1:0] wbs7_adr_i;
output [wbs_dat_width-1:0] wbs7_dat_i;
output wbs7_we_i;
output wbs7_cyc_i;
output wbs7_stb_i;
output [2:0] wbs7_cti_i;
output [1:0] wbs7_bte_i;
input [wbs_dat_width-1:0] wbs7_dat_o;
input wbs7_ack_o;
input wbs7_err_o;
input wbs7_rty_o;
 
// Wishbone Slave interface
output [wb_adr_width-1:0] wbs8_adr_i;
output [wbs_dat_width-1:0] wbs8_dat_i;
output wbs8_we_i;
output wbs8_cyc_i;
output wbs8_stb_i;
output [2:0] wbs8_cti_i;
output [1:0] wbs8_bte_i;
input [wbs_dat_width-1:0] wbs8_dat_o;
input wbs8_ack_o;
input wbs8_err_o;
input wbs8_rty_o;
 
// Wishbone Slave interface
output [wb_adr_width-1:0] wbs9_adr_i;
output [wbs_dat_width-1:0] wbs9_dat_i;
output wbs9_we_i;
output wbs9_cyc_i;
output wbs9_stb_i;
output [2:0] wbs9_cti_i;
output [1:0] wbs9_bte_i;
input [wbs_dat_width-1:0] wbs9_dat_o;
input wbs9_ack_o;
input wbs9_err_o;
input wbs9_rty_o;
 
// Wishbone Slave interface
output [wb_adr_width-1:0] wbs10_adr_i;
output [wbs_dat_width-1:0] wbs10_dat_i;
output wbs10_we_i;
output wbs10_cyc_i;
output wbs10_stb_i;
output [2:0] wbs10_cti_i;
output [1:0] wbs10_bte_i;
input [wbs_dat_width-1:0] wbs10_dat_o;
input wbs10_ack_o;
input wbs10_err_o;
input wbs10_rty_o;
 
 
// Wishbone Slave interface
output [wb_adr_width-1:0] wbs11_adr_i;
output [wbs_dat_width-1:0] wbs11_dat_i;
output wbs11_we_i;
output wbs11_cyc_i;
output wbs11_stb_i;
output [2:0] wbs11_cti_i;
output [1:0] wbs11_bte_i;
input [wbs_dat_width-1:0] wbs11_dat_o;
input wbs11_ack_o;
input wbs11_err_o;
input wbs11_rty_o;
 
 
// Wishbone Slave interface
output [wb_adr_width-1:0] wbs12_adr_i;
output [wbs_dat_width-1:0] wbs12_dat_i;
output wbs12_we_i;
output wbs12_cyc_i;
output wbs12_stb_i;
output [2:0] wbs12_cti_i;
output [1:0] wbs12_bte_i;
input [wbs_dat_width-1:0] wbs12_dat_o;
input wbs12_ack_o;
input wbs12_err_o;
input wbs12_rty_o;
 
// Wishbone Slave interface
output [wb_adr_width-1:0] wbs13_adr_i;
output [wbs_dat_width-1:0] wbs13_dat_i;
output wbs13_we_i;
output wbs13_cyc_i;
output wbs13_stb_i;
output [2:0] wbs13_cti_i;
output [1:0] wbs13_bte_i;
input [wbs_dat_width-1:0] wbs13_dat_o;
input wbs13_ack_o;
input wbs13_err_o;
input wbs13_rty_o;
 
 
// Wishbone Slave interface
output [wb_adr_width-1:0] wbs14_adr_i;
output [wbs_dat_width-1:0] wbs14_dat_i;
output wbs14_we_i;
output wbs14_cyc_i;
output wbs14_stb_i;
output [2:0] wbs14_cti_i;
output [1:0] wbs14_bte_i;
input [wbs_dat_width-1:0] wbs14_dat_o;
input wbs14_ack_o;
input wbs14_err_o;
input wbs14_rty_o;
 
// Wishbone Slave interface
output [wb_adr_width-1:0] wbs15_adr_i;
output [wbs_dat_width-1:0] wbs15_dat_i;
output wbs15_we_i;
output wbs15_cyc_i;
output wbs15_stb_i;
output [2:0] wbs15_cti_i;
output [1:0] wbs15_bte_i;
input [wbs_dat_width-1:0] wbs15_dat_o;
input wbs15_ack_o;
input wbs15_err_o;
input wbs15_rty_o;
 
// Wishbone Slave interface
output [wb_adr_width-1:0] wbs16_adr_i;
output [wbs_dat_width-1:0] wbs16_dat_i;
output wbs16_we_i;
output wbs16_cyc_i;
output wbs16_stb_i;
output [2:0] wbs16_cti_i;
output [1:0] wbs16_bte_i;
input [wbs_dat_width-1:0] wbs16_dat_o;
input wbs16_ack_o;
input wbs16_err_o;
input wbs16_rty_o;
 
 
// Wishbone Slave interface
output [wb_adr_width-1:0] wbs17_adr_i;
output [wbs_dat_width-1:0] wbs17_dat_i;
output wbs17_we_i;
output wbs17_cyc_i;
output wbs17_stb_i;
output [2:0] wbs17_cti_i;
output [1:0] wbs17_bte_i;
input [wbs_dat_width-1:0] wbs17_dat_o;
input wbs17_ack_o;
input wbs17_err_o;
input wbs17_rty_o;
 
// Wishbone Slave interface
output [wb_adr_width-1:0] wbs18_adr_i;
output [wbs_dat_width-1:0] wbs18_dat_i;
output wbs18_we_i;
output wbs18_cyc_i;
output wbs18_stb_i;
output [2:0] wbs18_cti_i;
output [1:0] wbs18_bte_i;
input [wbs_dat_width-1:0] wbs18_dat_o;
input wbs18_ack_o;
input wbs18_err_o;
input wbs18_rty_o;
// Wishbone Slave interface
output [wb_adr_width-1:0] wbs19_adr_i;
output [wbs_dat_width-1:0] wbs19_dat_i;
output wbs19_we_i;
output wbs19_cyc_i;
output wbs19_stb_i;
output [2:0] wbs19_cti_i;
output [1:0] wbs19_bte_i;
input [wbs_dat_width-1:0] wbs19_dat_o;
input wbs19_ack_o;
input wbs19_err_o;
input wbs19_rty_o;
*/
 
reg watchdog_err;
// Master input mux output wires
wire [wb_adr_width-1:0] wbm_adr_o;
wire [wbs_dat_width-1:0] wbm_dat_o;
wire [3:0] wbm_sel_o;
wire wbm_we_o;
wire wbm_cyc_o;
wire wbm_stb_o;
wire [2:0] wbm_cti_o;
wire [1:0] wbm_bte_o;
wire [wbs_dat_width-1:0] wbm_dat_byte_i;
wire wbm_ack_i;
wire wbm_err_i;
wire wbm_rty_i;
 
// Master input mux (not really used, only one master on this bus)
assign wbm_adr_o = wbm0_adr_o;
 
// Select the right byte and put it on the data out line
// !BIG ENDIAN!
assign wbm_dat_o = wbm0_sel_o[3] ? wbm0_dat_o[31:24] :
wbm0_sel_o[2] ? wbm0_dat_o[23:16] :
wbm0_sel_o[1] ? wbm0_dat_o[15:8] :
wbm0_dat_o[7:0];
assign wbm_we_o = wbm0_we_o;
assign wbm_cyc_o = wbm0_stb_o;
assign wbm_stb_o = wbm0_stb_o;
 
// Will we really need these for byte-peripherals
assign wbm_cti_o = wbm0_cti_o;
assign wbm_bte_o = wbm0_bte_o;
 
// Signals back to the master
assign wbm0_dat_i = (wbm0_sel_o[3]) ? {wbm_dat_byte_i, 24'd0} :
(wbm0_sel_o[2]) ? {8'd0, wbm_dat_byte_i, 16'd0} :
(wbm0_sel_o[1]) ? {16'd0, wbm_dat_byte_i, 8'd0} :
{24'd0, wbm_dat_byte_i};
 
assign wbm0_ack_i = wbm_ack_i;
assign wbm0_err_i = wbm_err_i;
assign wbm0_rty_i = wbm_rty_i;
 
`ifdef ARBITER_BYTEBUS_WATCHDOG
reg [`ARBITER_BYTEBUS_WATCHDOG_TIMER_WIDTH:0] watchdog_timer;
reg wbm_stb_r; // Register strobe
wire wbm_stb_edge; // Detect its edge
 
always @(posedge wb_clk)
wbm_stb_r <= wbm_stb_o;
 
assign wbm_stb_edge = (wbm_stb_o & !wbm_stb_r);
// Counter logic
always @(posedge wb_clk)
if (wb_rst) watchdog_timer <= 0;
else if (wbm_ack_i) // When we see an ack, turn off timer
watchdog_timer <= 0;
else if (wbm_stb_edge) // New access means start timer again
watchdog_timer <= 1;
else if (|watchdog_timer) // Continue counting if counter > 0
watchdog_timer <= watchdog_timer + 1;
 
always @(posedge wb_clk)
watchdog_err <= (&watchdog_timer);
`else // !`ifdef ARBITER_BYTEBUS_WATCHDOG
always @(posedge wb_clk)
watchdog_err <= 0;
`endif // !`ifdef ARBITER_BYTEBUS_WATCHDOG
 
// Wishbone slave mux out wires
wire [wb_adr_width-1:0] wbs_adr_i;
wire [wbs_dat_width-1:0] wbs_dat_i;
wire wbs_we_i;
wire wbs_cyc_i;
wire wbs_stb_i;
wire [2:0] wbs_cti_i;
wire [1:0] wbs_bte_i;
wire [wbs_dat_width-1:0] wbs_dat_o;
wire wbs_ack_o;
wire wbs_err_o;
wire wbs_rty_o;
 
// Slave select wire
wire [wb_num_slaves-1:0] wb_slave_sel;
// Slave out mux in wires
wire [wbs_dat_width-1:0] wbs_dat_o_mux_i [0:wb_num_slaves-1];
wire wbs_ack_o_mux_i [0:wb_num_slaves-1];
wire wbs_err_o_mux_i [0:wb_num_slaves-1];
wire wbs_rty_o_mux_i [0:wb_num_slaves-1];
 
// Slave selects
assign wb_slave_sel[0] = wbm_adr_o[`WB_ARB_ADDR_MATCH_SEL] == slave0_adr;
assign wb_slave_sel[1] = wbm_adr_o[`WB_ARB_ADDR_MATCH_SEL] == slave1_adr;
assign wb_slave_sel[2] = wbm_adr_o[`WB_ARB_ADDR_MATCH_SEL] == slave2_adr;
assign wb_slave_sel[3] = wbm_adr_o[`WB_ARB_ADDR_MATCH_SEL] == slave3_adr;
assign wb_slave_sel[4] = wbm_adr_o[`WB_ARB_ADDR_MATCH_SEL] == slave4_adr;
/*
assign wb_slave_sel[5] = wbm_adr_o[`WB_ARB_ADDR_MATCH_SEL] == slave5_adr;
assign wb_slave_sel[6] = wbm_adr_o[`WB_ARB_ADDR_MATCH_SEL] == slave6_adr;
assign wb_slave_sel[7] = wbm_adr_o[`WB_ARB_ADDR_MATCH_SEL] == slave7_adr;
assign wb_slave_sel[8] = wbm_adr_o[`WB_ARB_ADDR_MATCH_SEL] == slave8_adr;
assign wb_slave_sel[9] = wbm_adr_o[`WB_ARB_ADDR_MATCH_SEL] == slave9_adr;
assign wb_slave_sel[10] = wbm_adr_o[`WB_ARB_ADDR_MATCH_SEL] == slave10_adr;
assign wb_slave_sel[11] = wbm_adr_o[`WB_ARB_ADDR_MATCH_SEL] == slave11_adr;
assign wb_slave_sel[12] = wbm_adr_o[`WB_ARB_ADDR_MATCH_SEL] == slave12_adr;
assign wb_slave_sel[13] = wbm_adr_o[`WB_ARB_ADDR_MATCH_SEL] == slave13_adr;
assign wb_slave_sel[14] = wbm_adr_o[`WB_ARB_ADDR_MATCH_SEL] == slave14_adr;
assign wb_slave_sel[15] = wbm_adr_o[`WB_ARB_ADDR_MATCH_SEL] == slave15_adr;
assign wb_slave_sel[16] = wbm_adr_o[`WB_ARB_ADDR_MATCH_SEL] == slave16_adr;
assign wb_slave_sel[16] = wbm_adr_o[`WB_ARB_ADDR_MATCH_SEL] == slave17_adr;
assign wb_slave_sel[16] = wbm_adr_o[`WB_ARB_ADDR_MATCH_SEL] == slave18_adr;
assign wb_slave_sel[16] = wbm_adr_o[`WB_ARB_ADDR_MATCH_SEL] == slave19_adr;
*/
 
 
// Assign master inputs to slaves and slave inputs for MUXing back to master
 
// Slave 0 inputs
assign wbs0_adr_i = wbm_adr_o;
assign wbs0_dat_i = wbm_dat_o;
assign wbs0_cyc_i = wbm_cyc_o & wb_slave_sel[0];
assign wbs0_stb_i = wbm_stb_o & wb_slave_sel[0];
assign wbs0_we_i = wbm_we_o;
assign wbs0_cti_i = wbm_cti_o;
assign wbs0_bte_i = wbm_bte_o;
assign wbs_dat_o_mux_i[0] = wbs0_dat_o;
assign wbs_ack_o_mux_i[0] = wbs0_ack_o & wb_slave_sel[0];
assign wbs_err_o_mux_i[0] = wbs0_err_o & wb_slave_sel[0];
assign wbs_rty_o_mux_i[0] = wbs0_rty_o & wb_slave_sel[0];
 
 
// Slave 1 inputs
assign wbs1_adr_i = wbm_adr_o;
assign wbs1_dat_i = wbm_dat_o;
assign wbs1_cyc_i = wbm_cyc_o & wb_slave_sel[1];
assign wbs1_stb_i = wbm_stb_o & wb_slave_sel[1];
assign wbs1_we_i = wbm_we_o;
assign wbs1_cti_i = wbm_cti_o;
assign wbs1_bte_i = wbm_bte_o;
assign wbs_dat_o_mux_i[1] = wbs1_dat_o;
assign wbs_ack_o_mux_i[1] = wbs1_ack_o & wb_slave_sel[1];
assign wbs_err_o_mux_i[1] = wbs1_err_o & wb_slave_sel[1];
assign wbs_rty_o_mux_i[1] = wbs1_rty_o & wb_slave_sel[1];
 
 
// Slave 2 inputs
assign wbs2_adr_i = wbm_adr_o;
assign wbs2_dat_i = wbm_dat_o;
assign wbs2_cyc_i = wbm_cyc_o & wb_slave_sel[2];
assign wbs2_stb_i = wbm_stb_o & wb_slave_sel[2];
assign wbs2_we_i = wbm_we_o;
assign wbs2_cti_i = wbm_cti_o;
assign wbs2_bte_i = wbm_bte_o;
assign wbs_dat_o_mux_i[2] = wbs2_dat_o;
assign wbs_ack_o_mux_i[2] = wbs2_ack_o & wb_slave_sel[2];
assign wbs_err_o_mux_i[2] = wbs2_err_o & wb_slave_sel[2];
assign wbs_rty_o_mux_i[2] = wbs2_rty_o & wb_slave_sel[2];
 
 
// Slave 3 inputs
assign wbs3_adr_i = wbm_adr_o;
assign wbs3_dat_i = wbm_dat_o;
assign wbs3_cyc_i = wbm_cyc_o & wb_slave_sel[3];
assign wbs3_stb_i = wbm_stb_o & wb_slave_sel[3];
assign wbs3_we_i = wbm_we_o;
assign wbs3_cti_i = wbm_cti_o;
assign wbs3_bte_i = wbm_bte_o;
assign wbs_dat_o_mux_i[3] = wbs3_dat_o;
assign wbs_ack_o_mux_i[3] = wbs3_ack_o & wb_slave_sel[3];
assign wbs_err_o_mux_i[3] = wbs3_err_o & wb_slave_sel[3];
assign wbs_rty_o_mux_i[3] = wbs3_rty_o & wb_slave_sel[3];
 
 
// Slave 4 inputs
assign wbs4_adr_i = wbm_adr_o;
assign wbs4_dat_i = wbm_dat_o;
assign wbs4_cyc_i = wbm_cyc_o & wb_slave_sel[4];
assign wbs4_stb_i = wbm_stb_o & wb_slave_sel[4];
assign wbs4_we_i = wbm_we_o;
assign wbs4_cti_i = wbm_cti_o;
assign wbs4_bte_i = wbm_bte_o;
assign wbs_dat_o_mux_i[4] = wbs4_dat_o;
assign wbs_ack_o_mux_i[4] = wbs4_ack_o & wb_slave_sel[4];
assign wbs_err_o_mux_i[4] = wbs4_err_o & wb_slave_sel[4];
assign wbs_rty_o_mux_i[4] = wbs4_rty_o & wb_slave_sel[4];
 
/*
// Slave 5 inputs
assign wbs5_adr_i = wbm_adr_o;
assign wbs5_dat_i = wbm_dat_o;
assign wbs5_cyc_i = wbm_cyc_o & wb_slave_sel[5];
assign wbs5_stb_i = wbm_stb_o & wb_slave_sel[5];
assign wbs5_we_i = wbm_we_o;
assign wbs5_cti_i = wbm_cti_o;
assign wbs5_bte_i = wbm_bte_o;
assign wbs_dat_o_mux_i[5] = wbs5_dat_o;
assign wbs_ack_o_mux_i[5] = wbs5_ack_o & wb_slave_sel[5];
assign wbs_err_o_mux_i[5] = wbs5_err_o & wb_slave_sel[5];
assign wbs_rty_o_mux_i[5] = wbs5_rty_o & wb_slave_sel[5];
 
 
// Slave 6 inputs
assign wbs6_adr_i = wbm_adr_o;
assign wbs6_dat_i = wbm_dat_o;
assign wbs6_cyc_i = wbm_cyc_o & wb_slave_sel[6];
assign wbs6_stb_i = wbm_stb_o & wb_slave_sel[6];
assign wbs6_we_i = wbm_we_o;
assign wbs6_cti_i = wbm_cti_o;
assign wbs6_bte_i = wbm_bte_o;
assign wbs_dat_o_mux_i[6] = wbs6_dat_o;
assign wbs_ack_o_mux_i[6] = wbs6_ack_o & wb_slave_sel[6];
assign wbs_err_o_mux_i[6] = wbs6_err_o & wb_slave_sel[6];
assign wbs_rty_o_mux_i[6] = wbs6_rty_o & wb_slave_sel[6];
 
 
// Slave 7 inputs
assign wbs7_adr_i = wbm_adr_o;
assign wbs7_dat_i = wbm_dat_o;
assign wbs7_cyc_i = wbm_cyc_o & wb_slave_sel[7];
assign wbs7_stb_i = wbm_stb_o & wb_slave_sel[7];
assign wbs7_we_i = wbm_we_o;
assign wbs7_cti_i = wbm_cti_o;
assign wbs7_bte_i = wbm_bte_o;
assign wbs_dat_o_mux_i[7] = wbs7_dat_o;
assign wbs_ack_o_mux_i[7] = wbs7_ack_o & wb_slave_sel[7];
assign wbs_err_o_mux_i[7] = wbs7_err_o & wb_slave_sel[7];
assign wbs_rty_o_mux_i[7] = wbs7_rty_o & wb_slave_sel[7];
 
 
// Slave 8 inputs
assign wbs8_adr_i = wbm_adr_o;
assign wbs8_dat_i = wbm_dat_o;
assign wbs8_cyc_i = wbm_cyc_o & wb_slave_sel[8];
assign wbs8_stb_i = wbm_stb_o & wb_slave_sel[8];
assign wbs8_we_i = wbm_we_o;
assign wbs8_cti_i = wbm_cti_o;
assign wbs8_bte_i = wbm_bte_o;
assign wbs_dat_o_mux_i[8] = wbs8_dat_o;
assign wbs_ack_o_mux_i[8] = wbs8_ack_o & wb_slave_sel[8];
assign wbs_err_o_mux_i[8] = wbs8_err_o & wb_slave_sel[8];
assign wbs_rty_o_mux_i[8] = wbs8_rty_o & wb_slave_sel[8];
 
 
// Slave 9 inputs
assign wbs9_adr_i = wbm_adr_o;
assign wbs9_dat_i = wbm_dat_o;
assign wbs9_cyc_i = wbm_cyc_o & wb_slave_sel[9];
assign wbs9_stb_i = wbm_stb_o & wb_slave_sel[9];
assign wbs9_we_i = wbm_we_o;
assign wbs9_cti_i = wbm_cti_o;
assign wbs9_bte_i = wbm_bte_o;
assign wbs_dat_o_mux_i[9] = wbs9_dat_o;
assign wbs_ack_o_mux_i[9] = wbs9_ack_o & wb_slave_sel[9];
assign wbs_err_o_mux_i[9] = wbs9_err_o & wb_slave_sel[9];
assign wbs_rty_o_mux_i[9] = wbs9_rty_o & wb_slave_sel[9];
 
 
// Slave 10 inputs
assign wbs10_adr_i = wbm_adr_o;
assign wbs10_dat_i = wbm_dat_o;
assign wbs10_cyc_i = wbm_cyc_o & wb_slave_sel[10];
assign wbs10_stb_i = wbm_stb_o & wb_slave_sel[10];
assign wbs10_we_i = wbm_we_o;
assign wbs10_cti_i = wbm_cti_o;
assign wbs10_bte_i = wbm_bte_o;
assign wbs_dat_o_mux_i[10] = wbs10_dat_o;
assign wbs_ack_o_mux_i[10] = wbs10_ack_o & wb_slave_sel[10];
assign wbs_err_o_mux_i[10] = wbs10_err_o & wb_slave_sel[10];
assign wbs_rty_o_mux_i[10] = wbs10_rty_o & wb_slave_sel[10];
 
// Slave 11 inputs
assign wbs11_adr_i = wbm_adr_o;
assign wbs11_dat_i = wbm_dat_o;
assign wbs11_cyc_i = wbm_cyc_o & wb_slave_sel[11];
assign wbs11_stb_i = wbm_stb_o & wb_slave_sel[11];
assign wbs11_we_i = wbm_we_o;
assign wbs11_cti_i = wbm_cti_o;
assign wbs11_bte_i = wbm_bte_o;
assign wbs_dat_o_mux_i[11] = wbs11_dat_o;
assign wbs_ack_o_mux_i[11] = wbs11_ack_o & wb_slave_sel[11];
assign wbs_err_o_mux_i[11] = wbs11_err_o & wb_slave_sel[11];
assign wbs_rty_o_mux_i[11] = wbs11_rty_o & wb_slave_sel[11];
 
// Slave 12 inputs
assign wbs12_adr_i = wbm_adr_o;
assign wbs12_dat_i = wbm_dat_o;
assign wbs12_cyc_i = wbm_cyc_o & wb_slave_sel[12];
assign wbs12_stb_i = wbm_stb_o & wb_slave_sel[12];
assign wbs12_we_i = wbm_we_o;
assign wbs12_cti_i = wbm_cti_o;
assign wbs12_bte_i = wbm_bte_o;
assign wbs_dat_o_mux_i[12] = wbs12_dat_o;
assign wbs_ack_o_mux_i[12] = wbs12_ack_o & wb_slave_sel[12];
assign wbs_err_o_mux_i[12] = wbs12_err_o & wb_slave_sel[12];
assign wbs_rty_o_mux_i[12] = wbs12_rty_o & wb_slave_sel[12];
 
 
// Slave 13 inputs
assign wbs13_adr_i = wbm_adr_o;
assign wbs13_dat_i = wbm_dat_o;
assign wbs13_cyc_i = wbm_cyc_o & wb_slave_sel[13];
assign wbs13_stb_i = wbm_stb_o & wb_slave_sel[13];
assign wbs13_we_i = wbm_we_o;
assign wbs13_cti_i = wbm_cti_o;
assign wbs13_bte_i = wbm_bte_o;
assign wbs_dat_o_mux_i[13] = wbs13_dat_o;
assign wbs_ack_o_mux_i[13] = wbs13_ack_o & wb_slave_sel[13];
assign wbs_err_o_mux_i[13] = wbs13_err_o & wb_slave_sel[13];
assign wbs_rty_o_mux_i[13] = wbs13_rty_o & wb_slave_sel[13];
 
 
// Slave 14 inputs
assign wbs14_adr_i = wbm_adr_o;
assign wbs14_dat_i = wbm_dat_o;
assign wbs14_cyc_i = wbm_cyc_o & wb_slave_sel[14];
assign wbs14_stb_i = wbm_stb_o & wb_slave_sel[14];
assign wbs14_we_i = wbm_we_o;
assign wbs14_cti_i = wbm_cti_o;
assign wbs14_bte_i = wbm_bte_o;
assign wbs_dat_o_mux_i[14] = wbs14_dat_o;
assign wbs_ack_o_mux_i[14] = wbs14_ack_o & wb_slave_sel[14];
assign wbs_err_o_mux_i[14] = wbs14_err_o & wb_slave_sel[14];
assign wbs_rty_o_mux_i[14] = wbs14_rty_o & wb_slave_sel[14];
 
 
// Slave 15 inputs
assign wbs15_adr_i = wbm_adr_o;
assign wbs15_dat_i = wbm_dat_o;
assign wbs15_cyc_i = wbm_cyc_o & wb_slave_sel[15];
assign wbs15_stb_i = wbm_stb_o & wb_slave_sel[15];
assign wbs15_we_i = wbm_we_o;
assign wbs15_cti_i = wbm_cti_o;
assign wbs15_bte_i = wbm_bte_o;
assign wbs_dat_o_mux_i[15] = wbs15_dat_o;
assign wbs_ack_o_mux_i[15] = wbs15_ack_o & wb_slave_sel[15];
assign wbs_err_o_mux_i[15] = wbs15_err_o & wb_slave_sel[15];
assign wbs_rty_o_mux_i[15] = wbs15_rty_o & wb_slave_sel[15];
 
 
// Slave 16 inputs
assign wbs16_adr_i = wbm_adr_o;
assign wbs16_dat_i = wbm_dat_o;
assign wbs16_cyc_i = wbm_cyc_o & wb_slave_sel[16];
assign wbs16_stb_i = wbm_stb_o & wb_slave_sel[16];
assign wbs16_we_i = wbm_we_o;
assign wbs16_cti_i = wbm_cti_o;
assign wbs16_bte_i = wbm_bte_o;
assign wbs_dat_o_mux_i[16] = wbs16_dat_o;
assign wbs_ack_o_mux_i[16] = wbs16_ack_o & wb_slave_sel[16];
assign wbs_err_o_mux_i[16] = wbs16_err_o & wb_slave_sel[16];
assign wbs_rty_o_mux_i[16] = wbs16_rty_o & wb_slave_sel[16];
 
 
// Slave 17 inputs
assign wbs17_adr_i = wbm_adr_o;
assign wbs17_dat_i = wbm_dat_o;
assign wbs17_cyc_i = wbm_cyc_o & wb_slave_sel[17];
assign wbs17_stb_i = wbm_stb_o & wb_slave_sel[17];
assign wbs17_we_i = wbm_we_o;
assign wbs17_cti_i = wbm_cti_o;
assign wbs17_bte_i = wbm_bte_o;
assign wbs_dat_o_mux_i[17] = wbs17_dat_o;
assign wbs_ack_o_mux_i[17] = wbs17_ack_o & wb_slave_sel[17];
assign wbs_err_o_mux_i[17] = wbs17_err_o & wb_slave_sel[17];
assign wbs_rty_o_mux_i[17] = wbs17_rty_o & wb_slave_sel[17];
// Slave 18 inputs
assign wbs18_adr_i = wbm_adr_o;
assign wbs18_dat_i = wbm_dat_o;
assign wbs18_cyc_i = wbm_cyc_o & wb_slave_sel[18];
assign wbs18_stb_i = wbm_stb_o & wb_slave_sel[18];
assign wbs18_we_i = wbm_we_o;
assign wbs18_cti_i = wbm_cti_o;
assign wbs18_bte_i = wbm_bte_o;
assign wbs_dat_o_mux_i[18] = wbs18_dat_o;
assign wbs_ack_o_mux_i[18] = wbs18_ack_o & wb_slave_sel[18];
assign wbs_err_o_mux_i[18] = wbs18_err_o & wb_slave_sel[18];
assign wbs_rty_o_mux_i[18] = wbs18_rty_o & wb_slave_sel[18];
// Slave 19 inputs
assign wbs19_adr_i = wbm_adr_o;
assign wbs19_dat_i = wbm_dat_o;
assign wbs19_cyc_i = wbm_cyc_o & wb_slave_sel[19];
assign wbs19_stb_i = wbm_stb_o & wb_slave_sel[19];
assign wbs19_we_i = wbm_we_o;
assign wbs19_cti_i = wbm_cti_o;
assign wbs19_bte_i = wbm_bte_o;
assign wbs_dat_o_mux_i[19] = wbs19_dat_o;
assign wbs_ack_o_mux_i[19] = wbs19_ack_o & wb_slave_sel[19];
assign wbs_err_o_mux_i[19] = wbs19_err_o & wb_slave_sel[19];
assign wbs_rty_o_mux_i[19] = wbs19_rty_o & wb_slave_sel[19];
 
*/
 
 
 
// Master out mux from slave in data
assign wbm_dat_byte_i = wb_slave_sel[0] ? wbs_dat_o_mux_i[0] :
wb_slave_sel[1] ? wbs_dat_o_mux_i[1] :
wb_slave_sel[2] ? wbs_dat_o_mux_i[2] :
wb_slave_sel[3] ? wbs_dat_o_mux_i[3] :
wb_slave_sel[4] ? wbs_dat_o_mux_i[4] :
/*
wb_slave_sel[5] ? wbs_dat_o_mux_i[5] :
wb_slave_sel[6] ? wbs_dat_o_mux_i[6] :
wb_slave_sel[7] ? wbs_dat_o_mux_i[7] :
wb_slave_sel[8] ? wbs_dat_o_mux_i[8] :
wb_slave_sel[9] ? wbs_dat_o_mux_i[9] :
wb_slave_sel[10] ? wbs_dat_o_mux_i[10] :
wb_slave_sel[11] ? wbs_dat_o_mux_i[11] :
wb_slave_sel[12] ? wbs_dat_o_mux_i[12] :
wb_slave_sel[13] ? wbs_dat_o_mux_i[13] :
wb_slave_sel[14] ? wbs_dat_o_mux_i[14] :
wb_slave_sel[15] ? wbs_dat_o_mux_i[15] :
wb_slave_sel[16] ? wbs_dat_o_mux_i[16] :
wb_slave_sel[17] ? wbs_dat_o_mux_i[17] :
wb_slave_sel[18] ? wbs_dat_o_mux_i[18] :
wb_slave_sel[19] ? wbs_dat_o_mux_i[19] :
*/
wbs_dat_o_mux_i[0];
// Master out acks, or together
assign wbm_ack_i = wbs_ack_o_mux_i[0] |
wbs_ack_o_mux_i[1] |
wbs_ack_o_mux_i[2] |
wbs_ack_o_mux_i[3] |
wbs_ack_o_mux_i[4] /* |
wbs_ack_o_mux_i[5] |
wbs_ack_o_mux_i[6] |
wbs_ack_o_mux_i[7] |
wbs_ack_o_mux_i[8] |
wbs_ack_o_mux_i[9] |
wbs_ack_o_mux_i[10] |
wbs_ack_o_mux_i[11] |
wbs_ack_o_mux_i[12] |
wbs_ack_o_mux_i[13] |
wbs_ack_o_mux_i[14] |
wbs_ack_o_mux_i[15] |
wbs_ack_o_mux_i[16] |
wbs_ack_o_mux_i[17] |
wbs_ack_o_mux_i[18] |
wbs_ack_o_mux_i[19]
*/
;
 
assign wbm_err_i = wbs_err_o_mux_i[0] |
wbs_err_o_mux_i[1] |
wbs_err_o_mux_i[2] |
wbs_err_o_mux_i[3] |
wbs_err_o_mux_i[4] |/*
wbs_err_o_mux_i[5] |
wbs_err_o_mux_i[6] |
wbs_err_o_mux_i[7] |
wbs_err_o_mux_i[8] |
wbs_err_o_mux_i[9] |
wbs_err_o_mux_i[10] |
wbs_err_o_mux_i[11] |
wbs_err_o_mux_i[12] |
wbs_err_o_mux_i[13] |
wbs_err_o_mux_i[14] |
wbs_err_o_mux_i[15] |
wbs_err_o_mux_i[16] |
wbs_err_o_mux_i[17] |
wbs_err_o_mux_i[18] |
wbs_err_o_mux_i[19] |
*/
watchdog_err ;
 
assign wbm_rty_i = wbs_rty_o_mux_i[0] |
wbs_rty_o_mux_i[1] |
wbs_rty_o_mux_i[2] |
wbs_rty_o_mux_i[3] |
wbs_rty_o_mux_i[4] /*|
wbs_rty_o_mux_i[5] |
wbs_rty_o_mux_i[6] |
wbs_rty_o_mux_i[7] |
wbs_rty_o_mux_i[8] |
wbs_rty_o_mux_i[9] |
wbs_rty_o_mux_i[10] |
wbs_rty_o_mux_i[11] |
wbs_rty_o_mux_i[12] |
wbs_rty_o_mux_i[13] |
wbs_rty_o_mux_i[14] |
wbs_rty_o_mux_i[15] |
wbs_rty_o_mux_i[16] |
wbs_rty_o_mux_i[17] |
wbs_rty_o_mux_i[18] |
wbs_rty_o_mux_i[19]
*/
;
 
endmodule // arbiter_bytebus
/verilog/arbiter/arbiter_dbus.v
0,0 → 1,1268
//////////////////////////////////////////////////////////////////////
/// ////
/// Wishbone arbiter, burst-compatible ////
/// ////
/// Simple arbiter, multi-master, multi-slave with default slave ////
/// for chaining with peripheral arbiter ////
/// ////
/// Julius Baxter, julius@opencores.org ////
/// ////
//////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2009, 2010 Authors and OPENCORES.ORG ////
//// ////
//// This source file may be used and distributed without ////
//// restriction provided that this copyright statement is not ////
//// removed from the file and that any derivative work contains ////
//// the original copyright notice and the associated disclaimer. ////
//// ////
//// This source file is free software; you can redistribute it ////
//// and/or modify it under the terms of the GNU Lesser General ////
//// Public License as published by the Free Software Foundation; ////
//// either version 2.1 of the License, or (at your option) any ////
//// later version. ////
//// ////
//// This source is distributed in the hope that it will be ////
//// useful, but WITHOUT ANY WARRANTY; without even the implied ////
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ////
//// PURPOSE. See the GNU Lesser General Public License for more ////
//// details. ////
//// ////
//// You should have received a copy of the GNU Lesser General ////
//// Public License along with this source; if not, download it ////
//// from http://www.opencores.org/lgpl.shtml ////
//// ////
//////////////////////////////////////////////////////////////////////
`include "orpsoc-defines.v"
// 2 Masters, a few slaves
module arbiter_dbus
(
// or1200 data master
// Wishbone Master interface
wbm0_adr_o,
wbm0_dat_o,
wbm0_sel_o,
wbm0_we_o,
wbm0_cyc_o,
wbm0_stb_o,
wbm0_cti_o,
wbm0_bte_o,
wbm0_dat_i,
wbm0_ack_i,
wbm0_err_i,
wbm0_rty_i,
 
// or1200 debug master
// Wishbone Master interface
wbm1_adr_o,
wbm1_dat_o,
wbm1_sel_o,
wbm1_we_o,
wbm1_cyc_o,
wbm1_stb_o,
wbm1_cti_o,
wbm1_bte_o,
wbm1_dat_i,
wbm1_ack_i,
wbm1_err_i,
wbm1_rty_i,
 
// Slave one
// Wishbone Slave interface
wbs0_adr_i,
wbs0_dat_i,
wbs0_sel_i,
wbs0_we_i,
wbs0_cyc_i,
wbs0_stb_i,
wbs0_cti_i,
wbs0_bte_i,
wbs0_dat_o,
wbs0_ack_o,
wbs0_err_o,
wbs0_rty_o,
 
// Slave two
// Wishbone Slave interface
wbs1_adr_i,
wbs1_dat_i,
wbs1_sel_i,
wbs1_we_i,
wbs1_cyc_i,
wbs1_stb_i,
wbs1_cti_i,
wbs1_bte_i,
wbs1_dat_o,
wbs1_ack_o,
wbs1_err_o,
wbs1_rty_o,
 
 
// Slave three
// Wishbone Slave interface
wbs2_adr_i,
wbs2_dat_i,
wbs2_sel_i,
wbs2_we_i,
wbs2_cyc_i,
wbs2_stb_i,
wbs2_cti_i,
wbs2_bte_i,
wbs2_dat_o,
wbs2_ack_o,
wbs2_err_o,
wbs2_rty_o,
/*
// Slave four
// Wishbone Slave interface
wbs3_adr_i,
wbs3_dat_i,
wbs3_sel_i,
wbs3_we_i,
wbs3_cyc_i,
wbs3_stb_i,
wbs3_cti_i,
wbs3_bte_i,
wbs3_dat_o,
wbs3_ack_o,
wbs3_err_o,
wbs3_rty_o,
 
// Slave five
// Wishbone Slave interface
wbs4_adr_i,
wbs4_dat_i,
wbs4_sel_i,
wbs4_we_i,
wbs4_cyc_i,
wbs4_stb_i,
wbs4_cti_i,
wbs4_bte_i,
wbs4_dat_o,
wbs4_ack_o,
wbs4_err_o,
wbs4_rty_o,
 
// Slave six
// Wishbone Slave interface
wbs5_adr_i,
wbs5_dat_i,
wbs5_sel_i,
wbs5_we_i,
wbs5_cyc_i,
wbs5_stb_i,
wbs5_cti_i,
wbs5_bte_i,
wbs5_dat_o,
wbs5_ack_o,
wbs5_err_o,
wbs5_rty_o,
 
// Slave seven
// Wishbone Slave interface
wbs6_adr_i,
wbs6_dat_i,
wbs6_sel_i,
wbs6_we_i,
wbs6_cyc_i,
wbs6_stb_i,
wbs6_cti_i,
wbs6_bte_i,
wbs6_dat_o,
wbs6_ack_o,
wbs6_err_o,
wbs6_rty_o,
 
// Slave eight
// Wishbone Slave interface
wbs7_adr_i,
wbs7_dat_i,
wbs7_sel_i,
wbs7_we_i,
wbs7_cyc_i,
wbs7_stb_i,
wbs7_cti_i,
wbs7_bte_i,
wbs7_dat_o,
wbs7_ack_o,
wbs7_err_o,
wbs7_rty_o,
 
// Slave nine
// Wishbone Slave interface
wbs8_adr_i,
wbs8_dat_i,
wbs8_sel_i,
wbs8_we_i,
wbs8_cyc_i,
wbs8_stb_i,
wbs8_cti_i,
wbs8_bte_i,
wbs8_dat_o,
wbs8_ack_o,
wbs8_err_o,
wbs8_rty_o,
 
// Slave ten
// Wishbone Slave interface
wbs9_adr_i,
wbs9_dat_i,
wbs9_sel_i,
wbs9_we_i,
wbs9_cyc_i,
wbs9_stb_i,
wbs9_cti_i,
wbs9_bte_i,
wbs9_dat_o,
wbs9_ack_o,
wbs9_err_o,
wbs9_rty_o,
 
// Slave eleven
// Wishbone Slave interface
wbs10_adr_i,
wbs10_dat_i,
wbs10_sel_i,
wbs10_we_i,
wbs10_cyc_i,
wbs10_stb_i,
wbs10_cti_i,
wbs10_bte_i,
wbs10_dat_o,
wbs10_ack_o,
wbs10_err_o,
wbs10_rty_o,
 
// Slave twelve
// Wishbone Slave interface
wbs11_adr_i,
wbs11_dat_i,
wbs11_sel_i,
wbs11_we_i,
wbs11_cyc_i,
wbs11_stb_i,
wbs11_cti_i,
wbs11_bte_i,
wbs11_dat_o,
wbs11_ack_o,
wbs11_err_o,
wbs11_rty_o,
 
// Slave thirteen
// Wishbone Slave interface
wbs12_adr_i,
wbs12_dat_i,
wbs12_sel_i,
wbs12_we_i,
wbs12_cyc_i,
wbs12_stb_i,
wbs12_cti_i,
wbs12_bte_i,
wbs12_dat_o,
wbs12_ack_o,
wbs12_err_o,
wbs12_rty_o,
 
// Slave fourteen
// Wishbone Slave interface
wbs13_adr_i,
wbs13_dat_i,
wbs13_sel_i,
wbs13_we_i,
wbs13_cyc_i,
wbs13_stb_i,
wbs13_cti_i,
wbs13_bte_i,
wbs13_dat_o,
wbs13_ack_o,
wbs13_err_o,
wbs13_rty_o,
 
// Slave fifteen
// Wishbone Slave interface
wbs14_adr_i,
wbs14_dat_i,
wbs14_sel_i,
wbs14_we_i,
wbs14_cyc_i,
wbs14_stb_i,
wbs14_cti_i,
wbs14_bte_i,
wbs14_dat_o,
wbs14_ack_o,
wbs14_err_o,
wbs14_rty_o,
 
// Slave sixteen
// Wishbone Slave interface
wbs15_adr_i,
wbs15_dat_i,
wbs15_sel_i,
wbs15_we_i,
wbs15_cyc_i,
wbs15_stb_i,
wbs15_cti_i,
wbs15_bte_i,
wbs15_dat_o,
wbs15_ack_o,
wbs15_err_o,
wbs15_rty_o,
 
// Slave seventeen
// Wishbone Slave interface
wbs16_adr_i,
wbs16_dat_i,
wbs16_sel_i,
wbs16_we_i,
wbs16_cyc_i,
wbs16_stb_i,
wbs16_cti_i,
wbs16_bte_i,
wbs16_dat_o,
wbs16_ack_o,
wbs16_err_o,
wbs16_rty_o,
*/
wb_clk,
wb_rst
);
 
parameter wb_dat_width = 32;
parameter wb_adr_width = 32;
 
parameter wb_addr_match_width = 8;
 
parameter wb_num_slaves = 2; // must also (un)comment things if changing
 
// Slave addresses - these should be defparam'd from top level
// Declare them as you need them
parameter slave0_adr = 0;
parameter slave1_adr = 0;
parameter slave2_adr = 0;
parameter slave3_adr = 0;
parameter slave4_adr = 0;
parameter slave5_adr = 0;
parameter slave6_adr = 0;
parameter slave7_adr = 0;
parameter slave8_adr = 0;
parameter slave9_adr = 0;
parameter slave10_adr = 0;
parameter slave11_adr = 0;
parameter slave12_adr = 0;
 
// Select for slave 0
`define WB_ARB_ADDR_MATCH_SEL_SLAVE0 wb_adr_width-1:wb_adr_width-4
`define WB_ARB_ADDR_MATCH_SEL wb_adr_width-1:wb_adr_width-wb_addr_match_width
 
input wb_clk;
input wb_rst;
// WB Master one
input [wb_adr_width-1:0] wbm0_adr_o;
input [wb_dat_width-1:0] wbm0_dat_o;
input [3:0] wbm0_sel_o;
input wbm0_we_o;
input wbm0_cyc_o;
input wbm0_stb_o;
input [2:0] wbm0_cti_o;
input [1:0] wbm0_bte_o;
output [wb_dat_width-1:0] wbm0_dat_i;
output wbm0_ack_i;
output wbm0_err_i;
output wbm0_rty_i;
input [wb_adr_width-1:0] wbm1_adr_o;
input [wb_dat_width-1:0] wbm1_dat_o;
input [3:0] wbm1_sel_o;
input wbm1_we_o;
input wbm1_cyc_o;
input wbm1_stb_o;
input [2:0] wbm1_cti_o;
input [1:0] wbm1_bte_o;
output [wb_dat_width-1:0] wbm1_dat_i;
output wbm1_ack_i;
output wbm1_err_i;
output wbm1_rty_i;
 
// Slave one
// Wishbone Slave interface
output [wb_adr_width-1:0] wbs0_adr_i;
output [wb_dat_width-1:0] wbs0_dat_i;
output [3:0] wbs0_sel_i;
output wbs0_we_i;
output wbs0_cyc_i;
output wbs0_stb_i;
output [2:0] wbs0_cti_i;
output [1:0] wbs0_bte_i;
input [wb_dat_width-1:0] wbs0_dat_o;
input wbs0_ack_o;
input wbs0_err_o;
input wbs0_rty_o;
 
// Wishbone Slave interface
output [wb_adr_width-1:0] wbs1_adr_i;
output [wb_dat_width-1:0] wbs1_dat_i;
output [3:0] wbs1_sel_i;
output wbs1_we_i;
output wbs1_cyc_i;
output wbs1_stb_i;
output [2:0] wbs1_cti_i;
output [1:0] wbs1_bte_i;
input [wb_dat_width-1:0] wbs1_dat_o;
input wbs1_ack_o;
input wbs1_err_o;
input wbs1_rty_o;
 
// Wishbone Slave interface
output [wb_adr_width-1:0] wbs2_adr_i;
output [wb_dat_width-1:0] wbs2_dat_i;
output [3:0] wbs2_sel_i;
output wbs2_we_i;
output wbs2_cyc_i;
output wbs2_stb_i;
output [2:0] wbs2_cti_i;
output [1:0] wbs2_bte_i;
input [wb_dat_width-1:0] wbs2_dat_o;
input wbs2_ack_o;
input wbs2_err_o;
input wbs2_rty_o;
/*
// Wishbone Slave interface
output [wb_adr_width-1:0] wbs3_adr_i;
output [wb_dat_width-1:0] wbs3_dat_i;
output [3:0] wbs3_sel_i;
output wbs3_we_i;
output wbs3_cyc_i;
output wbs3_stb_i;
output [2:0] wbs3_cti_i;
output [1:0] wbs3_bte_i;
input [wb_dat_width-1:0] wbs3_dat_o;
input wbs3_ack_o;
input wbs3_err_o;
input wbs3_rty_o;
 
// Wishbone Slave interface
output [wb_adr_width-1:0] wbs4_adr_i;
output [wb_dat_width-1:0] wbs4_dat_i;
output [3:0] wbs4_sel_i;
output wbs4_we_i;
output wbs4_cyc_i;
output wbs4_stb_i;
output [2:0] wbs4_cti_i;
output [1:0] wbs4_bte_i;
input [wb_dat_width-1:0] wbs4_dat_o;
input wbs4_ack_o;
input wbs4_err_o;
input wbs4_rty_o;
 
// Wishbone Slave interface
output [wb_adr_width-1:0] wbs5_adr_i;
output [wb_dat_width-1:0] wbs5_dat_i;
output [3:0] wbs5_sel_i;
output wbs5_we_i;
output wbs5_cyc_i;
output wbs5_stb_i;
output [2:0] wbs5_cti_i;
output [1:0] wbs5_bte_i;
input [wb_dat_width-1:0] wbs5_dat_o;
input wbs5_ack_o;
input wbs5_err_o;
input wbs5_rty_o;
 
// Wishbone Slave interface
output [wb_adr_width-1:0] wbs6_adr_i;
output [wb_dat_width-1:0] wbs6_dat_i;
output [3:0] wbs6_sel_i;
output wbs6_we_i;
output wbs6_cyc_i;
output wbs6_stb_i;
output [2:0] wbs6_cti_i;
output [1:0] wbs6_bte_i;
input [wb_dat_width-1:0] wbs6_dat_o;
input wbs6_ack_o;
input wbs6_err_o;
input wbs6_rty_o;
 
// Wishbone Slave interface
output [wb_adr_width-1:0] wbs7_adr_i;
output [wb_dat_width-1:0] wbs7_dat_i;
output [3:0] wbs7_sel_i;
output wbs7_we_i;
output wbs7_cyc_i;
output wbs7_stb_i;
output [2:0] wbs7_cti_i;
output [1:0] wbs7_bte_i;
input [wb_dat_width-1:0] wbs7_dat_o;
input wbs7_ack_o;
input wbs7_err_o;
input wbs7_rty_o;
 
// Wishbone Slave interface
output [wb_adr_width-1:0] wbs8_adr_i;
output [wb_dat_width-1:0] wbs8_dat_i;
output [3:0] wbs8_sel_i;
output wbs8_we_i;
output wbs8_cyc_i;
output wbs8_stb_i;
output [2:0] wbs8_cti_i;
output [1:0] wbs8_bte_i;
input [wb_dat_width-1:0] wbs8_dat_o;
input wbs8_ack_o;
input wbs8_err_o;
input wbs8_rty_o;
 
// Wishbone Slave interface
output [wb_adr_width-1:0] wbs9_adr_i;
output [wb_dat_width-1:0] wbs9_dat_i;
output [3:0] wbs9_sel_i;
output wbs9_we_i;
output wbs9_cyc_i;
output wbs9_stb_i;
output [2:0] wbs9_cti_i;
output [1:0] wbs9_bte_i;
input [wb_dat_width-1:0] wbs9_dat_o;
input wbs9_ack_o;
input wbs9_err_o;
input wbs9_rty_o;
 
// Wishbone Slave interface
output [wb_adr_width-1:0] wbs10_adr_i;
output [wb_dat_width-1:0] wbs10_dat_i;
output [3:0] wbs10_sel_i;
output wbs10_we_i;
output wbs10_cyc_i;
output wbs10_stb_i;
output [2:0] wbs10_cti_i;
output [1:0] wbs10_bte_i;
input [wb_dat_width-1:0] wbs10_dat_o;
input wbs10_ack_o;
input wbs10_err_o;
input wbs10_rty_o;
 
// Wishbone Slave interface
output [wb_adr_width-1:0] wbs11_adr_i;
output [wb_dat_width-1:0] wbs11_dat_i;
output [3:0] wbs11_sel_i;
output wbs11_we_i;
output wbs11_cyc_i;
output wbs11_stb_i;
output [2:0] wbs11_cti_i;
output [1:0] wbs11_bte_i;
input [wb_dat_width-1:0] wbs11_dat_o;
input wbs11_ack_o;
input wbs11_err_o;
input wbs11_rty_o;
 
// Wishbone Slave interface
output [wb_adr_width-1:0] wbs12_adr_i;
output [wb_dat_width-1:0] wbs12_dat_i;
output [3:0] wbs12_sel_i;
output wbs12_we_i;
output wbs12_cyc_i;
output wbs12_stb_i;
output [2:0] wbs12_cti_i;
output [1:0] wbs12_bte_i;
input [wb_dat_width-1:0] wbs12_dat_o;
input wbs12_ack_o;
input wbs12_err_o;
input wbs12_rty_o;
 
// Wishbone Slave interface
output [wb_adr_width-1:0] wbs13_adr_i;
output [wb_dat_width-1:0] wbs13_dat_i;
output [3:0] wbs13_sel_i;
output wbs13_we_i;
output wbs13_cyc_i;
output wbs13_stb_i;
output [2:0] wbs13_cti_i;
output [1:0] wbs13_bte_i;
input [wb_dat_width-1:0] wbs13_dat_o;
input wbs13_ack_o;
input wbs13_err_o;
input wbs13_rty_o;
 
// Wishbone Slave interface
output [wb_adr_width-1:0] wbs14_adr_i;
output [wb_dat_width-1:0] wbs14_dat_i;
output [3:0] wbs14_sel_i;
output wbs14_we_i;
output wbs14_cyc_i;
output wbs14_stb_i;
output [2:0] wbs14_cti_i;
output [1:0] wbs14_bte_i;
input [wb_dat_width-1:0] wbs14_dat_o;
input wbs14_ack_o;
input wbs14_err_o;
input wbs14_rty_o;
 
// Wishbone Slave interface
output [wb_adr_width-1:0] wbs15_adr_i;
output [wb_dat_width-1:0] wbs15_dat_i;
output [3:0] wbs15_sel_i;
output wbs15_we_i;
output wbs15_cyc_i;
output wbs15_stb_i;
output [2:0] wbs15_cti_i;
output [1:0] wbs15_bte_i;
input [wb_dat_width-1:0] wbs15_dat_o;
input wbs15_ack_o;
input wbs15_err_o;
input wbs15_rty_o;
 
// Wishbone Slave interface
output [wb_adr_width-1:0] wbs16_adr_i;
output [wb_dat_width-1:0] wbs16_dat_i;
output [3:0] wbs16_sel_i;
output wbs16_we_i;
output wbs16_cyc_i;
output wbs16_stb_i;
output [2:0] wbs16_cti_i;
output [1:0] wbs16_bte_i;
input [wb_dat_width-1:0] wbs16_dat_o;
input wbs16_ack_o;
input wbs16_err_o;
input wbs16_rty_o;
*/
 
reg watchdog_err;
`ifdef ARBITER_DBUS_REGISTERING
 
// Registering setup:
// Masters typically register their outputs, so do the master selection and
// muxing before registering in the arbiter. Keep the common parts outside
// for code brevity.
// Master ins -> |MUX> -> these wires
wire [wb_adr_width-1:0] wbm_adr_o_w;
wire [wb_dat_width-1:0] wbm_dat_o_w;
wire [3:0] wbm_sel_o_w;
wire wbm_we_o_w;
wire wbm_cyc_o_w;
wire wbm_stb_o_w;
wire [2:0] wbm_cti_o_w;
wire [1:0] wbm_bte_o_w;
// Slave ins -> |MUX> -> these wires
wire [wb_dat_width-1:0] wbm_dat_i;
wire wbm_ack_i;
wire wbm_err_i;
wire wbm_rty_i;
 
// Registers after masters input mux
reg [wb_adr_width-1:0] wbm_adr_o_r;
reg [wb_dat_width-1:0] wbm_dat_o_r;
reg [3:0] wbm_sel_o_r;
reg wbm_we_o_r;
reg wbm_cyc_o_r;
reg wbm_stb_o_r;
reg [2:0] wbm_cti_o_r;
reg [1:0] wbm_bte_o_r;
 
// Master input mux register wires
wire [wb_adr_width-1:0] wbm_adr_o;
wire [wb_dat_width-1:0] wbm_dat_o;
wire [3:0] wbm_sel_o;
wire wbm_we_o;
wire wbm_cyc_o;
wire wbm_stb_o;
wire [2:0] wbm_cti_o;
wire [1:0] wbm_bte_o;
 
// Registers after slaves input mux
reg [wb_dat_width-1:0] wbm_dat_i_r;
reg wbm_ack_i_r;
reg wbm_err_i_r;
reg wbm_rty_i_r;
 
// Master select (MUX controls)
wire [1:0] master_sel;
// priority to wbm1, the debug master
assign master_sel[0] = wbm0_cyc_o & !wbm1_cyc_o;
assign master_sel[1] = wbm1_cyc_o;
 
 
// Master input mux, priority to debug master
assign wbm_adr_o_w = master_sel[1] ? wbm1_adr_o :
wbm0_adr_o;
assign wbm_dat_o_w = master_sel[1] ? wbm1_dat_o :
wbm0_dat_o;
assign wbm_sel_o_w = master_sel[1] ? wbm1_sel_o :
wbm0_sel_o;
 
assign wbm_we_o_w = master_sel[1] ? wbm1_we_o :
wbm0_we_o;
assign wbm_cyc_o_w = master_sel[1] ? wbm1_cyc_o :
wbm0_cyc_o;
 
assign wbm_stb_o_w = master_sel[1] ? wbm1_stb_o :
wbm0_stb_o;
 
assign wbm_cti_o_w = master_sel[1] ? wbm1_cti_o :
wbm0_cti_o;
 
assign wbm_bte_o_w = master_sel[1] ? wbm1_bte_o :
wbm0_bte_o;
 
// Register muxed master signals
always @(posedge wb_clk)
begin
wbm_adr_o_r <= wbm_adr_o_w;
wbm_dat_o_r <= wbm_dat_o_w;
wbm_sel_o_r <= wbm_sel_o_w;
wbm_we_o_r <= wbm_we_o_w;
wbm_cyc_o_r <= wbm_cyc_o_w;
wbm_stb_o_r <= wbm_stb_o_w & !wbm_ack_i & !wbm_ack_i_r;
wbm_cti_o_r <= wbm_cti_o_w;
wbm_bte_o_r <= wbm_bte_o_w;
wbm_dat_i_r <= wbm_dat_i;
wbm_ack_i_r <= wbm_ack_i;
wbm_err_i_r <= wbm_err_i;
wbm_rty_i_r <= wbm_rty_i;
end // always @ (posedge wb_clk)
 
assign wbm_adr_o = wbm_adr_o_r;
assign wbm_dat_o = wbm_dat_o_r;
assign wbm_sel_o = wbm_sel_o_r;
assign wbm_we_o = wbm_we_o_r;
assign wbm_cyc_o = wbm_cyc_o_r;
assign wbm_stb_o = wbm_stb_o_r;
assign wbm_cti_o = wbm_cti_o_r;
assign wbm_bte_o = wbm_bte_o_r;
 
// Master input mux, priority to debug master
assign wbm0_dat_i = wbm_dat_i_r;
assign wbm0_ack_i = wbm_ack_i_r & master_sel[0];
assign wbm0_err_i = wbm_err_i_r & master_sel[0];
assign wbm0_rty_i = wbm_rty_i_r & master_sel[0];
assign wbm1_dat_i = wbm_dat_i_r;
assign wbm1_ack_i = wbm_ack_i_r & master_sel[1];
assign wbm1_err_i = wbm_err_i_r & master_sel[1];
assign wbm1_rty_i = wbm_rty_i_r & master_sel[1];
`else // !`ifdef ARBITER_DBUS_REGISTERING
 
// Master input mux output wires
wire [wb_adr_width-1:0] wbm_adr_o;
wire [wb_dat_width-1:0] wbm_dat_o;
wire [3:0] wbm_sel_o;
wire wbm_we_o;
wire wbm_cyc_o;
wire wbm_stb_o;
wire [2:0] wbm_cti_o;
wire [1:0] wbm_bte_o;
// Master select
wire [1:0] master_sel;
// priority to wbm1, the debug master
assign master_sel[0] = wbm0_cyc_o & !wbm1_cyc_o;
assign master_sel[1] = wbm1_cyc_o;
 
 
// Master input mux, priority to debug master
assign wbm_adr_o = master_sel[1] ? wbm1_adr_o :
wbm0_adr_o;
assign wbm_dat_o = master_sel[1] ? wbm1_dat_o :
wbm0_dat_o;
assign wbm_sel_o = master_sel[1] ? wbm1_sel_o :
wbm0_sel_o;
 
assign wbm_we_o = master_sel[1] ? wbm1_we_o :
wbm0_we_o;
assign wbm_cyc_o = master_sel[1] ? wbm1_cyc_o :
wbm0_cyc_o;
 
assign wbm_stb_o = master_sel[1] ? wbm1_stb_o :
wbm0_stb_o;
 
assign wbm_cti_o = master_sel[1] ? wbm1_cti_o :
wbm0_cti_o;
 
assign wbm_bte_o = master_sel[1] ? wbm1_bte_o :
wbm0_bte_o;
 
 
wire [wb_dat_width-1:0] wbm_dat_i;
wire wbm_ack_i;
wire wbm_err_i;
wire wbm_rty_i;
 
 
assign wbm0_dat_i = wbm_dat_i;
assign wbm0_ack_i = wbm_ack_i & master_sel[0];
assign wbm0_err_i = wbm_err_i & master_sel[0];
assign wbm0_rty_i = wbm_rty_i & master_sel[0];
assign wbm1_dat_i = wbm_dat_i;
assign wbm1_ack_i = wbm_ack_i & master_sel[1];
assign wbm1_err_i = wbm_err_i & master_sel[1];
assign wbm1_rty_i = wbm_rty_i & master_sel[1];
 
 
`endif // !`ifdef ARBITER_DBUS_REGISTERING
 
// Slave select wire
wire [wb_num_slaves-1:0] wb_slave_sel;
reg [wb_num_slaves-1:0] wb_slave_sel_r;
 
// Register wb_slave_sel_r to break combinatorial loop when selecting default
// slave
always @(posedge wb_clk)
wb_slave_sel_r <= wb_slave_sel;
// Slave out mux in wires
wire [wb_dat_width-1:0] wbs_dat_o_mux_i [0:wb_num_slaves-1];
wire wbs_ack_o_mux_i [0:wb_num_slaves-1];
wire wbs_err_o_mux_i [0:wb_num_slaves-1];
wire wbs_rty_o_mux_i [0:wb_num_slaves-1];
 
//
// Slave selects
//
assign wb_slave_sel[0] = wbm_adr_o[31:28] == slave0_adr | wbm_adr_o[31:28] == 4'hf; // Special case, point all reads to ROM address to here
assign wb_slave_sel[1] = wbm_adr_o[`WB_ARB_ADDR_MATCH_SEL] == slave1_adr;
// Auto select last slave when others are not selected
assign wb_slave_sel[2] = !(wb_slave_sel_r[0] | wb_slave_sel_r[1]);
 
/*
assign wb_slave_sel[2] = wbm_adr_o[`WB_ARB_ADDR_MATCH_SEL] == slave2_adr;
assign wb_slave_sel[3] = wbm_adr_o[`WB_ARB_ADDR_MATCH_SEL] == slave3_adr;
assign wb_slave_sel[4] = wbm_adr_o[`WB_ARB_ADDR_MATCH_SEL] == slave4_adr;
assign wb_slave_sel[5] = wbm_adr_o[`WB_ARB_ADDR_MATCH_SEL] == slave5_adr;
assign wb_slave_sel[6] = wbm_adr_o[`WB_ARB_ADDR_MATCH_SEL] == slave6_adr;
assign wb_slave_sel[7] = wbm_adr_o[`WB_ARB_ADDR_MATCH_SEL] == slave7_adr;
assign wb_slave_sel[8] = wbm_adr_o[`WB_ARB_ADDR_MATCH_SEL] == slave8_adr;
assign wb_slave_sel[9] = wbm_adr_o[`WB_ARB_ADDR_MATCH_SEL] == slave9_adr;
assign wb_slave_sel[10] = wbm_adr_o[`WB_ARB_ADDR_MATCH_SEL] == slave10_adr;
assign wb_slave_sel[11] = wbm_adr_o[`WB_ARB_ADDR_MATCH_SEL] == slave11_adr;
assign wb_slave_sel[12] = wbm_adr_o[`WB_ARB_ADDR_MATCH_SEL] == slave12_adr;
assign wb_slave_sel[13] = wbm_adr_o[`WB_ARB_ADDR_MATCH_SEL] == slave13_adr;
assign wb_slave_sel[14] = wbm_adr_o[`WB_ARB_ADDR_MATCH_SEL] == slave14_adr;
assign wb_slave_sel[15] = wbm_adr_o[`WB_ARB_ADDR_MATCH_SEL] == slave15_adr;
assign wb_slave_sel[16] = wbm_adr_o[`WB_ARB_ADDR_MATCH_SEL] == slave16_adr;
*/
 
`ifdef ARBITER_DBUS_WATCHDOG
reg [`ARBITER_DBUS_WATCHDOG_TIMER_WIDTH:0] watchdog_timer;
reg wbm_stb_r; // Register strobe
wire wbm_stb_edge; // Detect its edge
 
always @(posedge wb_clk)
wbm_stb_r <= wbm_stb_o;
 
assign wbm_stb_edge = (wbm_stb_o & !wbm_stb_r);
// Counter logic
always @(posedge wb_clk)
if (wb_rst) watchdog_timer <= 0;
else if (wbm_ack_i) // When we see an ack, turn off timer
watchdog_timer <= 0;
else if (wbm_stb_edge) // New access means start timer again
watchdog_timer <= 1;
else if (|watchdog_timer) // Continue counting if counter > 0
watchdog_timer <= watchdog_timer + 1;
 
always @(posedge wb_clk)
watchdog_err <= (&watchdog_timer);
 
`else // !`ifdef ARBITER_DBUS_WATCHDOG
always @(posedge wb_clk)
watchdog_err <= 0;
`endif // !`ifdef ARBITER_DBUS_WATCHDOG
 
// Slave 0 inputs
assign wbs0_adr_i = wbm_adr_o;
assign wbs0_dat_i = wbm_dat_o;
assign wbs0_sel_i = wbm_sel_o;
assign wbs0_cyc_i = wbm_cyc_o & wb_slave_sel_r[0];
assign wbs0_stb_i = wbm_stb_o & wb_slave_sel_r[0];
assign wbs0_we_i = wbm_we_o;
assign wbs0_cti_i = wbm_cti_o;
assign wbs0_bte_i = wbm_bte_o;
assign wbs_dat_o_mux_i[0] = wbs0_dat_o;
assign wbs_ack_o_mux_i[0] = wbs0_ack_o & wb_slave_sel_r[0];
assign wbs_err_o_mux_i[0] = wbs0_err_o & wb_slave_sel_r[0];
assign wbs_rty_o_mux_i[0] = wbs0_rty_o & wb_slave_sel_r[0];
 
 
// Slave 1 inputs
assign wbs1_adr_i = wbm_adr_o;
assign wbs1_dat_i = wbm_dat_o;
assign wbs1_sel_i = wbm_sel_o;
assign wbs1_cyc_i = wbm_cyc_o & wb_slave_sel_r[1];
assign wbs1_stb_i = wbm_stb_o & wb_slave_sel_r[1];
assign wbs1_we_i = wbm_we_o;
assign wbs1_cti_i = wbm_cti_o;
assign wbs1_bte_i = wbm_bte_o;
assign wbs_dat_o_mux_i[1] = wbs1_dat_o;
assign wbs_ack_o_mux_i[1] = wbs1_ack_o & wb_slave_sel_r[1];
assign wbs_err_o_mux_i[1] = wbs1_err_o & wb_slave_sel_r[1];
assign wbs_rty_o_mux_i[1] = wbs1_rty_o & wb_slave_sel_r[1];
 
 
// Slave 2 inputs
assign wbs2_adr_i = wbm_adr_o;
assign wbs2_dat_i = wbm_dat_o;
assign wbs2_sel_i = wbm_sel_o;
assign wbs2_cyc_i = wbm_cyc_o & wb_slave_sel_r[2];
assign wbs2_stb_i = wbm_stb_o & wb_slave_sel_r[2];
assign wbs2_we_i = wbm_we_o;
assign wbs2_cti_i = wbm_cti_o;
assign wbs2_bte_i = wbm_bte_o;
assign wbs_dat_o_mux_i[2] = wbs2_dat_o;
assign wbs_ack_o_mux_i[2] = wbs2_ack_o & wb_slave_sel_r[2];
assign wbs_err_o_mux_i[2] = wbs2_err_o & wb_slave_sel_r[2];
assign wbs_rty_o_mux_i[2] = wbs2_rty_o & wb_slave_sel_r[2];
/*
 
// Slave 3 inputs
assign wbs3_adr_i = wbm_adr_o;
assign wbs3_dat_i = wbm_dat_o;
assign wbs3_sel_i = wbm_sel_o;
assign wbs3_cyc_i = wbm_cyc_o & wb_slave_sel_r[3];
assign wbs3_stb_i = wbm_stb_o & wb_slave_sel_r[3];
assign wbs3_we_i = wbm_we_o;
assign wbs3_cti_i = wbm_cti_o;
assign wbs3_bte_i = wbm_bte_o;
assign wbs_dat_o_mux_i[3] = wbs3_dat_o;
assign wbs_ack_o_mux_i[3] = wbs3_ack_o & wb_slave_sel_r[3];
assign wbs_err_o_mux_i[3] = wbs3_err_o & wb_slave_sel_r[3];
assign wbs_rty_o_mux_i[3] = wbs3_rty_o & wb_slave_sel_r[3];
 
// Slave 4 inputs
assign wbs4_adr_i = wbm_adr_o;
assign wbs4_dat_i = wbm_dat_o;
assign wbs4_sel_i = wbm_sel_o;
assign wbs4_cyc_i = wbm_cyc_o & wb_slave_sel_r[4];
assign wbs4_stb_i = wbm_stb_o & wb_slave_sel_r[4];
assign wbs4_we_i = wbm_we_o;
assign wbs4_cti_i = wbm_cti_o;
assign wbs4_bte_i = wbm_bte_o;
assign wbs_dat_o_mux_i[4] = wbs4_dat_o;
assign wbs_ack_o_mux_i[4] = wbs4_ack_o & wb_slave_sel_r[4];
assign wbs_err_o_mux_i[4] = wbs4_err_o & wb_slave_sel_r[4];
assign wbs_rty_o_mux_i[4] = wbs4_rty_o & wb_slave_sel_r[4];
 
 
// Slave 5 inputs
assign wbs5_adr_i = wbm_adr_o;
assign wbs5_dat_i = wbm_dat_o;
assign wbs5_sel_i = wbm_sel_o;
assign wbs5_cyc_i = wbm_cyc_o & wb_slave_sel_r[5];
assign wbs5_stb_i = wbm_stb_o & wb_slave_sel_r[5];
assign wbs5_we_i = wbm_we_o;
assign wbs5_cti_i = wbm_cti_o;
assign wbs5_bte_i = wbm_bte_o;
assign wbs_dat_o_mux_i[5] = wbs5_dat_o;
assign wbs_ack_o_mux_i[5] = wbs5_ack_o & wb_slave_sel_r[5];
assign wbs_err_o_mux_i[5] = wbs5_err_o & wb_slave_sel_r[5];
assign wbs_rty_o_mux_i[5] = wbs5_rty_o & wb_slave_sel_r[5];
 
 
// Slave 6 inputs
assign wbs6_adr_i = wbm_adr_o;
assign wbs6_dat_i = wbm_dat_o;
assign wbs6_sel_i = wbm_sel_o;
assign wbs6_cyc_i = wbm_cyc_o & wb_slave_sel_r[6];
assign wbs6_stb_i = wbm_stb_o & wb_slave_sel_r[6];
assign wbs6_we_i = wbm_we_o;
assign wbs6_cti_i = wbm_cti_o;
assign wbs6_bte_i = wbm_bte_o;
assign wbs_dat_o_mux_i[6] = wbs6_dat_o;
assign wbs_ack_o_mux_i[6] = wbs6_ack_o & wb_slave_sel_r[6];
assign wbs_err_o_mux_i[6] = wbs6_err_o & wb_slave_sel_r[6];
assign wbs_rty_o_mux_i[6] = wbs6_rty_o & wb_slave_sel_r[6];
 
 
// Slave 7 inputs
assign wbs7_adr_i = wbm_adr_o;
assign wbs7_dat_i = wbm_dat_o;
assign wbs7_sel_i = wbm_sel_o;
assign wbs7_cyc_i = wbm_cyc_o & wb_slave_sel_r[7];
assign wbs7_stb_i = wbm_stb_o & wb_slave_sel_r[7];
assign wbs7_we_i = wbm_we_o;
assign wbs7_cti_i = wbm_cti_o;
assign wbs7_bte_i = wbm_bte_o;
assign wbs_dat_o_mux_i[7] = wbs7_dat_o;
assign wbs_ack_o_mux_i[7] = wbs7_ack_o & wb_slave_sel_r[7];
assign wbs_err_o_mux_i[7] = wbs7_err_o & wb_slave_sel_r[7];
assign wbs_rty_o_mux_i[7] = wbs7_rty_o & wb_slave_sel_r[7];
 
 
// Slave 8 inputs
assign wbs8_adr_i = wbm_adr_o;
assign wbs8_dat_i = wbm_dat_o;
assign wbs8_sel_i = wbm_sel_o;
assign wbs8_cyc_i = wbm_cyc_o & wb_slave_sel_r[8];
assign wbs8_stb_i = wbm_stb_o & wb_slave_sel_r[8];
assign wbs8_we_i = wbm_we_o;
assign wbs8_cti_i = wbm_cti_o;
assign wbs8_bte_i = wbm_bte_o;
assign wbs_dat_o_mux_i[8] = wbs8_dat_o;
assign wbs_ack_o_mux_i[8] = wbs8_ack_o & wb_slave_sel_r[8];
assign wbs_err_o_mux_i[8] = wbs8_err_o & wb_slave_sel_r[8];
assign wbs_rty_o_mux_i[8] = wbs8_rty_o & wb_slave_sel_r[8];
 
 
// Slave 9 inputs
assign wbs9_adr_i = wbm_adr_o;
assign wbs9_dat_i = wbm_dat_o;
assign wbs9_sel_i = wbm_sel_o;
assign wbs9_cyc_i = wbm_cyc_o & wb_slave_sel_r[9];
assign wbs9_stb_i = wbm_stb_o & wb_slave_sel_r[9];
assign wbs9_we_i = wbm_we_o;
assign wbs9_cti_i = wbm_cti_o;
assign wbs9_bte_i = wbm_bte_o;
assign wbs_dat_o_mux_i[9] = wbs9_dat_o;
assign wbs_ack_o_mux_i[9] = wbs9_ack_o & wb_slave_sel_r[9];
assign wbs_err_o_mux_i[9] = wbs9_err_o & wb_slave_sel_r[9];
assign wbs_rty_o_mux_i[9] = wbs9_rty_o & wb_slave_sel_r[9];
 
 
// Slave 10 inputs
assign wbs10_adr_i = wbm_adr_o;
assign wbs10_dat_i = wbm_dat_o;
assign wbs10_sel_i = wbm_sel_o;
assign wbs10_cyc_i = wbm_cyc_o & wb_slave_sel_r[10];
assign wbs10_stb_i = wbm_stb_o & wb_slave_sel_r[10];
assign wbs10_we_i = wbm_we_o;
assign wbs10_cti_i = wbm_cti_o;
assign wbs10_bte_i = wbm_bte_o;
assign wbs_dat_o_mux_i[10] = wbs10_dat_o;
assign wbs_ack_o_mux_i[10] = wbs10_ack_o & wb_slave_sel_r[10];
assign wbs_err_o_mux_i[10] = wbs10_err_o & wb_slave_sel_r[10];
assign wbs_rty_o_mux_i[10] = wbs10_rty_o & wb_slave_sel_r[10];
 
// Slave 11 inputs
assign wbs11_adr_i = wbm_adr_o;
assign wbs11_dat_i = wbm_dat_o;
assign wbs11_sel_i = wbm_sel_o;
assign wbs11_cyc_i = wbm_cyc_o & wb_slave_sel_r[11];
assign wbs11_stb_i = wbm_stb_o & wb_slave_sel_r[11];
assign wbs11_we_i = wbm_we_o;
assign wbs11_cti_i = wbm_cti_o;
assign wbs11_bte_i = wbm_bte_o;
assign wbs_dat_o_mux_i[11] = wbs11_dat_o;
assign wbs_ack_o_mux_i[11] = wbs11_ack_o & wb_slave_sel_r[11];
assign wbs_err_o_mux_i[11] = wbs11_err_o & wb_slave_sel_r[11];
assign wbs_rty_o_mux_i[11] = wbs11_rty_o & wb_slave_sel_r[11];
 
 
// Slave 12 inputs
assign wbs12_adr_i = wbm_adr_o;
assign wbs12_dat_i = wbm_dat_o;
assign wbs12_sel_i = wbm_sel_o;
assign wbs12_cyc_i = wbm_cyc_o & wb_slave_sel_r[12];
assign wbs12_stb_i = wbm_stb_o & wb_slave_sel_r[12];
assign wbs12_we_i = wbm_we_o;
assign wbs12_cti_i = wbm_cti_o;
assign wbs12_bte_i = wbm_bte_o;
assign wbs_dat_o_mux_i[12] = wbs12_dat_o;
assign wbs_ack_o_mux_i[12] = wbs12_ack_o & wb_slave_sel_r[12];
assign wbs_err_o_mux_i[12] = wbs12_err_o & wb_slave_sel_r[12];
assign wbs_rty_o_mux_i[12] = wbs12_rty_o & wb_slave_sel_r[12];
 
 
// Slave 13 inputs
assign wbs13_adr_i = wbm_adr_o;
assign wbs13_dat_i = wbm_dat_o;
assign wbs13_sel_i = wbm_sel_o;
assign wbs13_cyc_i = wbm_cyc_o & wb_slave_sel_r[13];
assign wbs13_stb_i = wbm_stb_o & wb_slave_sel_r[13];
assign wbs13_we_i = wbm_we_o;
assign wbs13_cti_i = wbm_cti_o;
assign wbs13_bte_i = wbm_bte_o;
assign wbs_dat_o_mux_i[13] = wbs13_dat_o;
assign wbs_ack_o_mux_i[13] = wbs13_ack_o & wb_slave_sel_r[13];
assign wbs_err_o_mux_i[13] = wbs13_err_o & wb_slave_sel_r[13];
assign wbs_rty_o_mux_i[13] = wbs13_rty_o & wb_slave_sel_r[13];
 
 
// Slave 14 inputs
assign wbs14_adr_i = wbm_adr_o;
assign wbs14_dat_i = wbm_dat_o;
assign wbs14_sel_i = wbm_sel_o;
assign wbs14_cyc_i = wbm_cyc_o & wb_slave_sel_r[14];
assign wbs14_stb_i = wbm_stb_o & wb_slave_sel_r[14];
assign wbs14_we_i = wbm_we_o;
assign wbs14_cti_i = wbm_cti_o;
assign wbs14_bte_i = wbm_bte_o;
assign wbs_dat_o_mux_i[14] = wbs14_dat_o;
assign wbs_ack_o_mux_i[14] = wbs14_ack_o & wb_slave_sel_r[14];
assign wbs_err_o_mux_i[14] = wbs14_err_o & wb_slave_sel_r[14];
assign wbs_rty_o_mux_i[14] = wbs14_rty_o & wb_slave_sel_r[14];
 
 
// Slave 15 inputs
assign wbs15_adr_i = wbm_adr_o;
assign wbs15_dat_i = wbm_dat_o;
assign wbs15_sel_i = wbm_sel_o;
assign wbs15_cyc_i = wbm_cyc_o & wb_slave_sel_r[15];
assign wbs15_stb_i = wbm_stb_o & wb_slave_sel_r[15];
assign wbs15_we_i = wbm_we_o;
assign wbs15_cti_i = wbm_cti_o;
assign wbs15_bte_i = wbm_bte_o;
assign wbs_dat_o_mux_i[15] = wbs15_dat_o;
assign wbs_ack_o_mux_i[15] = wbs15_ack_o & wb_slave_sel_r[15];
assign wbs_err_o_mux_i[15] = wbs15_err_o & wb_slave_sel_r[15];
assign wbs_rty_o_mux_i[15] = wbs15_rty_o & wb_slave_sel_r[15];
 
 
// Slave 16 inputs
assign wbs16_adr_i = wbm_adr_o;
assign wbs16_dat_i = wbm_dat_o;
assign wbs16_sel_i = wbm_sel_o;
assign wbs16_cyc_i = wbm_cyc_o & wb_slave_sel_r[16];
assign wbs16_stb_i = wbm_stb_o & wb_slave_sel_r[16];
assign wbs16_we_i = wbm_we_o;
assign wbs16_cti_i = wbm_cti_o;
assign wbs16_bte_i = wbm_bte_o;
assign wbs_dat_o_mux_i[16] = wbs16_dat_o;
assign wbs_ack_o_mux_i[16] = wbs16_ack_o & wb_slave_sel_r[16];
assign wbs_err_o_mux_i[16] = wbs16_err_o & wb_slave_sel_r[16];
assign wbs_rty_o_mux_i[16] = wbs16_rty_o & wb_slave_sel_r[16];
 
*/
 
 
 
// Master out mux from slave in data
assign wbm_dat_i = wb_slave_sel_r[0] ? wbs_dat_o_mux_i[0] :
wb_slave_sel_r[1] ? wbs_dat_o_mux_i[1] :
wb_slave_sel_r[2] ? wbs_dat_o_mux_i[2] :
/* wb_slave_sel_r[3] ? wbs_dat_o_mux_i[3] :
wb_slave_sel_r[4] ? wbs_dat_o_mux_i[4] :
wb_slave_sel_r[5] ? wbs_dat_o_mux_i[5] :
wb_slave_sel_r[6] ? wbs_dat_o_mux_i[6] :
wb_slave_sel_r[7] ? wbs_dat_o_mux_i[7] :
wb_slave_sel_r[8] ? wbs_dat_o_mux_i[8] :
wb_slave_sel_r[9] ? wbs_dat_o_mux_i[9] :
wb_slave_sel_r[10] ? wbs_dat_o_mux_i[10] :
wb_slave_sel_r[11] ? wbs_dat_o_mux_i[11] :
wb_slave_sel_r[12] ? wbs_dat_o_mux_i[12] :
wb_slave_sel_r[13] ? wbs_dat_o_mux_i[13] :
wb_slave_sel_r[14] ? wbs_dat_o_mux_i[14] :
wb_slave_sel_r[15] ? wbs_dat_o_mux_i[15] :
wb_slave_sel_r[16] ? wbs_dat_o_mux_i[16] :
*/
wbs_dat_o_mux_i[0];
// Master out acks, or together
assign wbm_ack_i = wbs_ack_o_mux_i[0] |
wbs_ack_o_mux_i[1] |
wbs_ack_o_mux_i[2] /*|
wbs_ack_o_mux_i[3] |
wbs_ack_o_mux_i[4] |
wbs_ack_o_mux_i[5] |
wbs_ack_o_mux_i[6] |
wbs_ack_o_mux_i[7] |
wbs_ack_o_mux_i[8] |
wbs_ack_o_mux_i[9] |
wbs_ack_o_mux_i[10] |
wbs_ack_o_mux_i[11] |
wbs_ack_o_mux_i[12] |
wbs_ack_o_mux_i[13] |
wbs_ack_o_mux_i[14] |
wbs_ack_o_mux_i[15] |
wbs_ack_o_mux_i[16] */
;
 
assign wbm_err_i = wbs_err_o_mux_i[0] |
wbs_err_o_mux_i[1] |
wbs_err_o_mux_i[2] |/*
wbs_err_o_mux_i[3] |
wbs_err_o_mux_i[4] |
wbs_err_o_mux_i[5] |
wbs_err_o_mux_i[6] |
wbs_err_o_mux_i[7] |
wbs_err_o_mux_i[8] |
wbs_err_o_mux_i[9] |
wbs_err_o_mux_i[10] |
wbs_err_o_mux_i[11] |
wbs_err_o_mux_i[12] |
wbs_err_o_mux_i[13] |
wbs_err_o_mux_i[14] |
wbs_err_o_mux_i[15] |
wbs_err_o_mux_i[16] |*/
watchdog_err ;
 
 
assign wbm_rty_i = wbs_rty_o_mux_i[0] |
wbs_rty_o_mux_i[1] |
wbs_rty_o_mux_i[2] /*|
wbs_rty_o_mux_i[3] |
wbs_rty_o_mux_i[4] |
wbs_rty_o_mux_i[5] |
wbs_rty_o_mux_i[6] |
wbs_rty_o_mux_i[7] |
wbs_rty_o_mux_i[8] |
wbs_rty_o_mux_i[9] |
wbs_rty_o_mux_i[10] |
wbs_rty_o_mux_i[11] |
wbs_rty_o_mux_i[12] |
wbs_rty_o_mux_i[13] |
wbs_rty_o_mux_i[14] |
wbs_rty_o_mux_i[15] |
wbs_rty_o_mux_i[16]*/;
 
endmodule // arbiter_dbus
 
/verilog/arbiter/arbiter_ibus.v
0,0 → 1,337
//////////////////////////////////////////////////////////////////////
/// ////
/// Wishbone arbiter, burst-compatible ////
/// ////
/// Simple arbiter, single master, dual slave, primarily for ////
/// processor instruction bus, providing access to one main ////
/// memory server and one ROM ////
/// ////
/// Julius Baxter, julius@opencores.org ////
/// ////
//////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2009, 2010 Authors and OPENCORES.ORG ////
//// ////
//// This source file may be used and distributed without ////
//// restriction provided that this copyright statement is not ////
//// removed from the file and that any derivative work contains ////
//// the original copyright notice and the associated disclaimer. ////
//// ////
//// This source file is free software; you can redistribute it ////
//// and/or modify it under the terms of the GNU Lesser General ////
//// Public License as published by the Free Software Foundation; ////
//// either version 2.1 of the License, or (at your option) any ////
//// later version. ////
//// ////
//// This source is distributed in the hope that it will be ////
//// useful, but WITHOUT ANY WARRANTY; without even the implied ////
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ////
//// PURPOSE. See the GNU Lesser General Public License for more ////
//// details. ////
//// ////
//// You should have received a copy of the GNU Lesser General ////
//// Public License along with this source; if not, download it ////
//// from http://www.opencores.org/lgpl.shtml ////
//// ////
//////////////////////////////////////////////////////////////////////
`include "orpsoc-defines.v"
// One master, 2 slaves.
module arbiter_ibus
(
// instruction bus in
// Wishbone Master interface
wbm_adr_o,
wbm_dat_o,
wbm_sel_o,
wbm_we_o,
wbm_cyc_o,
wbm_stb_o,
wbm_cti_o,
wbm_bte_o,
wbm_dat_i,
wbm_ack_i,
wbm_err_i,
wbm_rty_i,
 
 
// Slave one
// Wishbone Slave interface
wbs0_adr_i,
wbs0_dat_i,
wbs0_sel_i,
wbs0_we_i,
wbs0_cyc_i,
wbs0_stb_i,
wbs0_cti_i,
wbs0_bte_i,
wbs0_dat_o,
wbs0_ack_o,
wbs0_err_o,
wbs0_rty_o,
 
// Slave two
// Wishbone Slave interface
wbs1_adr_i,
wbs1_dat_i,
wbs1_sel_i,
wbs1_we_i,
wbs1_cyc_i,
wbs1_stb_i,
wbs1_cti_i,
wbs1_bte_i,
wbs1_dat_o,
wbs1_ack_o,
wbs1_err_o,
wbs1_rty_o,
 
wb_clk,
wb_rst
);
 
 
parameter wb_dat_width = 32;
parameter wb_adr_width = 32;
 
parameter wb_addr_match_width = 8;
 
parameter slave0_adr = 8'hf0; // FLASH ROM
parameter slave1_adr = 8'h00; // Main memory (SDRAM/FPGA SRAM)
 
`define WB_ARB_ADDR_MATCH_SEL wb_adr_width-1:wb_adr_width-wb_addr_match_width
input wb_clk;
input wb_rst;
 
// WB Master
input [wb_adr_width-1:0] wbm_adr_o;
input [wb_dat_width-1:0] wbm_dat_o;
input [3:0] wbm_sel_o;
input wbm_we_o;
input wbm_cyc_o;
input wbm_stb_o;
input [2:0] wbm_cti_o;
input [1:0] wbm_bte_o;
output [wb_dat_width-1:0] wbm_dat_i;
output wbm_ack_i;
output wbm_err_i;
output wbm_rty_i;
 
// WB Slave 0
output [wb_adr_width-1:0] wbs0_adr_i;
output [wb_dat_width-1:0] wbs0_dat_i;
output [3:0] wbs0_sel_i;
output wbs0_we_i;
output wbs0_cyc_i;
output wbs0_stb_i;
output [2:0] wbs0_cti_i;
output [1:0] wbs0_bte_i;
input [wb_dat_width-1:0] wbs0_dat_o;
input wbs0_ack_o;
input wbs0_err_o;
input wbs0_rty_o;
 
// WB Slave 1
output [wb_adr_width-1:0] wbs1_adr_i;
output [wb_dat_width-1:0] wbs1_dat_i;
output [3:0] wbs1_sel_i;
output wbs1_we_i;
output wbs1_cyc_i;
output wbs1_stb_i;
output [2:0] wbs1_cti_i;
output [1:0] wbs1_bte_i;
input [wb_dat_width-1:0] wbs1_dat_o;
input wbs1_ack_o;
input wbs1_err_o;
input wbs1_rty_o;
 
wire [1:0] slave_sel; // One bit per slave
 
reg watchdog_err;
`ifdef ARBITER_IBUS_WATCHDOG
reg [`ARBITER_IBUS_WATCHDOG_TIMER_WIDTH:0] watchdog_timer;
reg wbm_stb_r; // Register strobe
wire wbm_stb_edge; // Detect its edge
reg wbm_stb_edge_r, wbm_ack_i_r; // Reg these, better timing
 
always @(posedge wb_clk)
wbm_stb_r <= wbm_stb_o;
 
assign wbm_stb_edge = (wbm_stb_o & !wbm_stb_r);
 
always @(posedge wb_clk)
wbm_stb_edge_r <= wbm_stb_edge;
always @(posedge wb_clk)
wbm_ack_i_r <= wbm_ack_i;
// Counter logic
always @(posedge wb_clk)
if (wb_rst) watchdog_timer <= 0;
else if (wbm_ack_i_r) // When we see an ack, turn off timer
watchdog_timer <= 0;
else if (wbm_stb_edge_r) // New access means start timer again
watchdog_timer <= 1;
else if (|watchdog_timer) // Continue counting if counter > 0
watchdog_timer <= watchdog_timer + 1;
 
always @(posedge wb_clk)
watchdog_err <= (&watchdog_timer);
`else // !`ifdef ARBITER_IBUS_WATCHDOG
always @(posedge wb_clk)
watchdog_err <= 0;
 
`endif // !`ifdef ARBITER_IBUS_WATCHDOG
 
`ifdef ARBITER_IBUS_REGISTERING
// Master input registers
reg [wb_adr_width-1:0] wbm_adr_o_r;
reg [wb_dat_width-1:0] wbm_dat_o_r;
reg [3:0] wbm_sel_o_r;
reg wbm_we_o_r;
reg wbm_cyc_o_r;
reg wbm_stb_o_r;
reg [2:0] wbm_cti_o_r;
reg [1:0] wbm_bte_o_r;
// Slave output registers
reg [wb_dat_width-1:0] wbs0_dat_o_r;
reg wbs0_ack_o_r;
reg wbs0_err_o_r;
reg wbs0_rty_o_r;
reg [wb_dat_width-1:0] wbs1_dat_o_r;
reg wbs1_ack_o_r;
reg wbs1_err_o_r;
reg wbs1_rty_o_r;
 
wire wbm_ack_i_pre_reg;
 
// Register master input signals
always @(posedge wb_clk)
begin
wbm_adr_o_r <= wbm_adr_o;
wbm_dat_o_r <= wbm_dat_o;
wbm_sel_o_r <= wbm_sel_o;
wbm_we_o_r <= wbm_we_o;
wbm_cyc_o_r <= wbm_cyc_o;
wbm_stb_o_r <= wbm_stb_o & !wbm_ack_i_pre_reg & !wbm_ack_i;//classic
wbm_cti_o_r <= wbm_cti_o;
wbm_bte_o_r <= wbm_bte_o;
 
// Slave signals
wbs0_dat_o_r <= wbs0_dat_o;
wbs0_ack_o_r <= wbs0_ack_o;
wbs0_err_o_r <= wbs0_err_o;
wbs0_rty_o_r <= wbs0_rty_o;
wbs1_dat_o_r <= wbs1_dat_o;
wbs1_ack_o_r <= wbs1_ack_o;
wbs1_err_o_r <= wbs1_err_o;
wbs1_rty_o_r <= wbs1_rty_o;
end // always @ (posedge wb_clk)
 
// Slave select
assign slave_sel[0] = wbm_adr_o_r[`WB_ARB_ADDR_MATCH_SEL] ==
slave0_adr;
 
assign slave_sel[1] = wbm_adr_o_r[`WB_ARB_ADDR_MATCH_SEL] ==
slave1_adr;
 
// Slave out assigns
assign wbs0_adr_i = wbm_adr_o_r;
assign wbs0_dat_i = wbm_dat_o_r;
assign wbs0_we_i = wbm_dat_o_r;
assign wbs0_sel_i = wbm_sel_o_r;
assign wbs0_cti_i = wbm_cti_o_r;
assign wbs0_bte_i = wbm_bte_o_r;
assign wbs0_cyc_i = wbm_cyc_o_r & slave_sel[0];
assign wbs0_stb_i = wbm_stb_o_r & slave_sel[0];
 
assign wbs1_adr_i = wbm_adr_o_r;
assign wbs1_dat_i = wbm_dat_o_r;
assign wbs1_we_i = wbm_dat_o_r;
assign wbs1_sel_i = wbm_sel_o_r;
assign wbs1_cti_i = wbm_cti_o_r;
assign wbs1_bte_i = wbm_bte_o_r;
assign wbs1_cyc_i = wbm_cyc_o_r & slave_sel[1];
assign wbs1_stb_i = wbm_stb_o_r & slave_sel[1];
 
// Master out assigns
// Don't care about none selected...
assign wbm_dat_i = slave_sel[1] ? wbs1_dat_o_r :
wbs0_dat_o_r ;
assign wbm_ack_i = (slave_sel[0] & wbs0_ack_o_r) |
(slave_sel[1] & wbs1_ack_o_r)
;
assign wbm_err_i = (slave_sel[0] & wbs0_err_o_r) |
(slave_sel[1] & wbs1_err_o_r) |
watchdog_err;
assign wbm_rty_i = (slave_sel[0] & wbs0_rty_o_r) |
(slave_sel[1] & wbs1_rty_o_r);
 
// Non-registered ack
assign wbm_ack_i_pre_reg = (slave_sel[0] & wbs0_ack_o) |
(slave_sel[1] & wbs1_ack_o);
`else // !`ifdef ARBITER_IBUS_REGISTERING
 
// Slave select
assign slave_sel[0] = wbm_adr_o[`WB_ARB_ADDR_MATCH_SEL] ==
slave0_adr;
 
assign slave_sel[1] = wbm_adr_o[`WB_ARB_ADDR_MATCH_SEL] ==
slave1_adr;
 
// Slave out assigns
assign wbs0_adr_i = wbm_adr_o;
assign wbs0_dat_i = wbm_dat_o;
assign wbs0_we_i = wbm_we_o;
assign wbs0_sel_i = wbm_sel_o;
assign wbs0_cti_i = wbm_cti_o;
assign wbs0_bte_i = wbm_bte_o;
assign wbs0_cyc_i = wbm_cyc_o & slave_sel[0];
assign wbs0_stb_i = wbm_stb_o & slave_sel[0];
 
assign wbs1_adr_i = wbm_adr_o;
assign wbs1_dat_i = wbm_dat_o;
assign wbs1_we_i = wbm_we_o;
assign wbs1_sel_i = wbm_sel_o;
assign wbs1_cti_i = wbm_cti_o;
assign wbs1_bte_i = wbm_bte_o;
assign wbs1_cyc_i = wbm_cyc_o & slave_sel[1];
assign wbs1_stb_i = wbm_stb_o & slave_sel[1];
 
// Master out assigns
// Don't care about none selected...
assign wbm_dat_i = slave_sel[1] ? wbs1_dat_o :
wbs0_dat_o ;
assign wbm_ack_i = (slave_sel[0] & wbs0_ack_o) |
(slave_sel[1] & wbs1_ack_o);
assign wbm_err_i = (slave_sel[0] & wbs0_err_o) |
(slave_sel[1] & wbs1_err_o) |
watchdog_err;
assign wbm_rty_i = (slave_sel[0] & wbs0_rty_o) |
(slave_sel[1] & wbs1_rty_o);
 
`endif
endmodule // arbiter_ibus
 
/verilog/gpio/gpio.v
0,0 → 1,159
/*
*
* Simple 24-bit wide GPIO module
*
* Can be made wider as needed, but must be done manually.
*
* First lot of bytes are the GPIO I/O regs
* Second lot are the direction registers
*
* Set direction bit to '1' to output corresponding data bit.
*
* Register mapping:
*
* For 8 GPIOs we would have
* adr 0: gpio data 7:0
* adr 1: gpio data 15:8
* adr 2: gpio data 23:16
* adr 3: gpio dir 7:0
* adr 4: gpio dir 15:8
* adr 5: gpio dir 23:16
*
* Backend pinout file needs to be updated for any GPIO width changes.
*
*/
 
module gpio(
wb_clk,
wb_rst,
wb_adr_i,
wb_dat_i,
wb_we_i,
wb_cyc_i,
wb_stb_i,
wb_cti_i,
wb_bte_i,
 
wb_ack_o,
wb_dat_o,
wb_err_o,
wb_rty_o,
 
gpio_io);
 
 
parameter gpio_io_width = 24;
 
parameter gpio_dir_reset_val = 0;
parameter gpio_o_reset_val = 0;
parameter wb_dat_width = 8;
parameter wb_adr_width = 3; // 8 bytes addressable
input wb_clk;
input wb_rst;
input [wb_adr_width-1:0] wb_adr_i;
input [wb_dat_width-1:0] wb_dat_i;
input wb_we_i;
input wb_cyc_i;
input wb_stb_i;
input [2:0] wb_cti_i;
input [1:0] wb_bte_i;
output reg [wb_dat_width-1:0] wb_dat_o; // constantly sampling gpio in bus
output reg wb_ack_o;
output wb_err_o;
output wb_rty_o;
 
inout [gpio_io_width-1:0] gpio_io;
 
// Internal registers
reg [gpio_io_width-1:0] gpio_dir;
 
reg [gpio_io_width-1:0] gpio_o;
 
wire [gpio_io_width-1:0] gpio_i;
 
// Tristate logic for IO
genvar i;
generate
for (i=0;i<gpio_io_width;i=i+1) begin: gpio_tris
assign gpio_io[i] = (gpio_dir[i]) ? gpio_o[i] : 1'bz;
assign gpio_i[i] = (gpio_dir[i]) ? gpio_o[i] : gpio_io[i];
end
endgenerate
// GPIO data out register
always @(posedge wb_clk)
if (wb_rst)
gpio_o <= 0; // All set to in at reset
else if (wb_stb_i & wb_we_i)
begin
if (wb_adr_i == 0)
gpio_o[7:0] <= wb_dat_i;
if (wb_adr_i == 1)
gpio_o[15:8] <= wb_dat_i;
if (wb_adr_i == 2)
gpio_o[23:16] <= wb_dat_i;
/* Add appropriate address detection here for wider GPIO */
end
 
 
// GPIO dir register
always @(posedge wb_clk)
if (wb_rst)
gpio_dir <= 0; // All set to in at reset
else if (wb_stb_i & wb_we_i)
begin
if (wb_adr_i == ((gpio_io_width/8)))
gpio_dir[7:0] <= wb_dat_i;
if (wb_adr_i == ((gpio_io_width/8)+1))
gpio_dir[15:8] <= wb_dat_i;
if (wb_adr_i == ((gpio_io_width/8)+2))
//gpio_dir[23:16] <= wb_dat_i;
gpio_dir[21:16] <= wb_dat_i[5:0];
 
/* Add appropriate address detection here for wider GPIO */
 
end
 
// Register the gpio in signal
always @(posedge wb_clk)
begin
// Data regs
if (wb_adr_i == 0)
wb_dat_o[7:0] <= gpio_i[7:0];
if (wb_adr_i == 1)
wb_dat_o[7:0] <= gpio_i[15:8];
if (wb_adr_i == 2)
wb_dat_o[7:0] <= gpio_i[23:16];
/* Add appropriate address detection here for wider GPIO */
// Direction regs
if (wb_adr_i == ((gpio_io_width/8)))
wb_dat_o[7:0] <= gpio_dir[7:0];
if (wb_adr_i == ((gpio_io_width/8)+1))
wb_dat_o[7:0] <= gpio_dir[15:8];
if (wb_adr_i == ((gpio_io_width/8)+2))
wb_dat_o[7:0] <= gpio_dir[23:16];
 
/* Add appropriate address detection here for wider GPIO */
 
end
// Ack generation
always @(posedge wb_clk)
if (wb_rst)
wb_ack_o <= 0;
else if (wb_ack_o)
wb_ack_o <= 0;
else if (wb_stb_i & !wb_ack_o)
wb_ack_o <= 1;
 
assign wb_err_o = 0;
assign wb_rty_o = 0;
 
endmodule // gpio
/verilog/gpio/README
0,0 → 1,7
GPIO RTL
 
This is a simple GPIO implementation. It is variable width, however widths of
multiples of 8 are advised. The first width/8 bytes control are for
reading/writing to the GPIO registers, the second set of width/8 bytes control
the direction.
 

powered by: WebSVN 2.1.0

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