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

Subversion Repositories openrisc

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /
    from Rev 66 to Rev 67
    Reverse comparison

Rev 66 → Rev 67

/openrisc/trunk/orpsocv2/bench/verilog/ddr2_model.v
0,0 → 1,2024
/****************************************************************************************
*
* File Name: ddr2.v
* Version: 5.80
* Model: BUS Functional
*
* Dependencies: ddr2_parameters.vh
*
* Description: Micron SDRAM DDR2 (Double Data Rate 2)
*
* Limitation: - doesn't check for average refresh timings
* - positive ck and ck_n edges are used to form internal clock
* - positive dqs and dqs_n edges are used to latch data
* - test mode is not modeled
*
* Note: - Set simulator resolution to "ps" accuracy
* - Set Debug = 0 to disable $display messages
*
* Disclaimer This software code and all associated documentation, comments or other
* of Warranty: information (collectively "Software") is provided "AS IS" without
* warranty of any kind. MICRON TECHNOLOGY, INC. ("MTI") EXPRESSLY
* DISCLAIMS ALL WARRANTIES EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
* TO, NONINFRINGEMENT OF THIRD PARTY RIGHTS, AND ANY IMPLIED WARRANTIES
* OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE. MTI DOES NOT
* WARRANT THAT THE SOFTWARE WILL MEET YOUR REQUIREMENTS, OR THAT THE
* OPERATION OF THE SOFTWARE WILL BE UNINTERRUPTED OR ERROR-FREE.
* FURTHERMORE, MTI DOES NOT MAKE ANY REPRESENTATIONS REGARDING THE USE OR
* THE RESULTS OF THE USE OF THE SOFTWARE IN TERMS OF ITS CORRECTNESS,
* ACCURACY, RELIABILITY, OR OTHERWISE. THE ENTIRE RISK ARISING OUT OF USE
* OR PERFORMANCE OF THE SOFTWARE REMAINS WITH YOU. IN NO EVENT SHALL MTI,
* ITS AFFILIATED COMPANIES OR THEIR SUPPLIERS BE LIABLE FOR ANY DIRECT,
* INDIRECT, CONSEQUENTIAL, INCIDENTAL, OR SPECIAL DAMAGES (INCLUDING,
* WITHOUT LIMITATION, DAMAGES FOR LOSS OF PROFITS, BUSINESS INTERRUPTION,
* OR LOSS OF INFORMATION) ARISING OUT OF YOUR USE OF OR INABILITY TO USE
* THE SOFTWARE, EVEN IF MTI HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGES. Because some jurisdictions prohibit the exclusion or
* limitation of liability for consequential or incidental damages, the
* above limitation may not apply to you.
*
* Copyright 2003 Micron Technology, Inc. All rights reserved.
*
* Rev Author Date Changes
* ---------------------------------------------------------------------------------------
* 1.00 JMK 07/29/03 Initial Release
* 1.10 JMK 08/09/03 Timing Parameter updates to tIS, tIH, tDS, tDH
* 2.20 JMK 08/07/03 General cleanup
* 2.30 JMK 11/26/03 Added CL_MIN, CL_MAX, wl_min and wl_max parameters.
* Added AL_MIN and AL_MAX parameters.
* Removed support for OCD.
* 2.40 JMK 01/15/04 Removed verilog 2001 constructs.
* 2.50 JMK 01/29/04 Removed tRP checks during Precharge command.
* 2.60 JMK 04/20/04 Fixed tWTR check.
* 2.70 JMK 04/30/04 Added tRFC maximum check.
* Combined Self Refresh and Power Down always blocks.
* Added Reset Function (CKE LOW Anytime).
* 2.80 JMK 08/19/04 Precharge is treated as NOP when bank is not active.
* Added checks for tRAS, tWR, tRTP to any bank during Pre-All.
* tRFC maximum violation will only display one time.
* 2.90 JMK 11/05/04 Fixed DQS checking during write.
* Fixed false tRFC max assertion during power up and self ref.
* Added warning for 200us CKE low time during initialization.
* Added -3, -3E, and -37V speed grades to ddr2_parameters.v
* 3.00 JMK 04/22/05 Removed ODT off requirement during power down.
* Added tAOND, tAOFD, tANPD, tAXPD, tAONPD, and tAOFPD parameters.
* Added ODT status messages.
* Updated the initialization sequence.
* Disable ODT and CLK pins during self refresh.
* Disable cmd and addr pins during power down and self refresh.
* 3.10 JMK 06/07/05 Disable trpa checking if the part does not have 8 banks.
* Changed tAXPD message from error to a warning.
* Added tDSS checking.
* Removed tDQSL checking during tWPRE and tWPST.
* Fixed a burst order error during writes.
* Renamed parameters file with .vh extension.
* 3.20 JMK 07/18/05 Removed 14 tCK requirement from LMR to READ.
* 3.30 JMK 08/03/05 Added check for interrupting a burst with auto precharge.
* 4.00 JMK 11/21/05 Parameter names all UPPERCASE, signal names all lowercase.
* Clock jitter can be tolerated within specification range.
* Clock frequency is sampled from the CK pin.
* Scaleable up to 64 DQ and 16 DQS bits.
* Read data can be randomly skewed using RANDOM_OUT_DELAY.
* Parameterized read and write DQS, and read DQ.
* Initialization can be bypassed using initialize task.
* 4.10 JMK 11/30/05 Fixed compile errors when `MAX_MEM was defined.
* 4.20 JMK 12/09/05 Fixed memory addressing error when `MAX_MEM was defined.
* 4.30 JMK 02/15/06 Added dummy write to initialization sequence.
* Removed tWPST maximum checking.
* Rising dqs_n edge latches data when enabled in EMR.
* Fixed a sign error in the tJIT(cc) calculation.
* 4.40 JMK 02/16/06 Fixed dummy write when`MAX_MEM was defined.
* 4.50 JMK 02/27/06 Fixed extra tDQSS assertions.
* Fixed tRCD and tWTR checking.
* Errors entering Power Down or Self Refresh will cause reset.
* Ignore dqs_n when disabled in EMR.
* 5.00 JMK 04/24/06 Test stimulus now included from external file (subtest.vh)
* Fixed tRFC max assertion during self refresh.
* Fixed tANPD checking during Power Down.
* Removed dummy write from initialization sequence.
* 5.01 JMK 04/28/06 Fixed Auto Precharge to Load Mode, Refresh and Self Refresh.
* Removed Auto Precharge error message during Power Down Enter.
* 5.10 JMK 07/26/06 Created internal clock using ck and ck_n.
* RDQS can only be enabled in EMR for x8 configurations.
* CAS latency is checked vs frequency when DLL locks.
* tMOD changed from tCK units to ns units.
* Added 50 Ohm setting for Rtt in EMR.
* Improved checking of DQS during writes.
* 5.20 JMK 10/02/06 Fixed DQS checking for interrupting write to write and x16.
* 5.30 JMK 05/25/07 Fixed checking for 0-Z transition on write postamble.
* 5.50 JMK 05/30/08 Renamed ddr2_dimm.v to ddr2_module.v and added SODIMM support.
* Added a register delay to ddr2_module.v when RDIMM is defined.
* Added multi-chip package model support in ddr2_mcp.v
* Added High Temp Self Refresh rate setting in EMRS2[7]
* 5.70 JMK 04/23/09 Updated tRPA definition
* Increased internal width to 72 bit DQ bus
* 5.80 SPH 08/12/09 Fixed tRAS maximum violation (only check if bank still open)
****************************************************************************************/
 
// DO NOT CHANGE THE TIMESCALE
// MAKE SURE YOUR SIMULATOR USES "PS" RESOLUTION
`timescale 1ps / 1ps
 
module ddr2_model (
ck,
ck_n,
cke,
cs_n,
ras_n,
cas_n,
we_n,
dm_rdqs,
ba,
addr,
dq,
dqs,
dqs_n,
rdqs_n,
odt
);
 
`include "ddr2_model_parameters.vh"
// text macros
`define DQ_PER_DQS DQ_BITS/DQS_BITS
`define BANKS (1<<BA_BITS)
`define MAX_BITS (BA_BITS+ROW_BITS+COL_BITS-BL_BITS)
`define MAX_SIZE (1<<(BA_BITS+ROW_BITS+COL_BITS-BL_BITS))
`define MEM_SIZE (1<<MEM_BITS)
`define MAX_PIPE 2*(AL_MAX + CL_MAX)
 
// Declare Ports
input ck;
input ck_n;
input cke;
input cs_n;
input ras_n;
input cas_n;
input we_n;
inout [DM_BITS-1:0] dm_rdqs;
input [BA_BITS-1:0] ba;
input [ADDR_BITS-1:0] addr;
inout [DQ_BITS-1:0] dq;
inout [DQS_BITS-1:0] dqs;
inout [DQS_BITS-1:0] dqs_n;
output [DQS_BITS-1:0] rdqs_n;
input odt;
// clock jitter
real tck_avg;
time tck_sample [TDLLK-1:0];
time tch_sample [TDLLK-1:0];
time tcl_sample [TDLLK-1:0];
time tck_i;
time tch_i;
time tcl_i;
real tch_avg;
real tcl_avg;
time tm_ck_pos;
time tm_ck_neg;
real tjit_per_rtime;
integer tjit_cc_time;
real terr_nper_rtime;
 
// clock skew
real out_delay;
integer dqsck [DQS_BITS-1:0];
integer dqsck_min;
integer dqsck_max;
integer dqsq_min;
integer dqsq_max;
integer seed;
 
// Mode Registers
reg burst_order;
reg [BL_BITS:0] burst_length;
integer cas_latency;
integer additive_latency;
reg dll_reset;
reg dll_locked;
reg dll_en;
integer write_recovery;
reg low_power;
reg [1:0] odt_rtt;
reg odt_en;
reg [2:0] ocd;
reg dqs_n_en;
reg rdqs_en;
reg out_en;
integer read_latency;
integer write_latency;
 
// cmd encoding
parameter LOAD_MODE = 4'b0000;
parameter REFRESH = 4'b0001;
parameter PRECHARGE = 4'b0010;
parameter ACTIVATE = 4'b0011;
parameter WRITE = 4'b0100;
parameter READ = 4'b0101;
parameter NOP = 4'b0111;
parameter PWR_DOWN = 4'b1000;
parameter SELF_REF = 4'b100;
 
reg [8*9-1:0] cmd_string [9:0];
initial begin
cmd_string[LOAD_MODE] = "Load Mode";
cmd_string[REFRESH ] = "Refresh ";
cmd_string[PRECHARGE] = "Precharge";
cmd_string[ACTIVATE ] = "Activate ";
cmd_string[WRITE ] = "Write ";
cmd_string[READ ] = "Read ";
cmd_string[NOP ] = "No Op ";
cmd_string[PWR_DOWN ] = "Pwr Down ";
cmd_string[SELF_REF ] = "Self Ref ";
end
 
// command state
reg [`BANKS-1:0] active_bank;
reg [`BANKS-1:0] auto_precharge_bank;
reg [`BANKS-1:0] write_precharge_bank;
reg [`BANKS-1:0] read_precharge_bank;
reg [ROW_BITS-1:0] active_row [`BANKS-1:0];
reg in_power_down;
reg in_self_refresh;
reg [3:0] init_mode_reg;
reg init_done;
integer init_step;
reg er_trfc_max;
reg odt_state;
reg prev_odt;
 
// cmd timers/counters
integer ref_cntr;
integer ck_cntr;
integer ck_load_mode;
integer ck_write;
integer ck_read;
integer ck_write_ap;
integer ck_power_down;
integer ck_slow_exit_pd;
integer ck_self_refresh;
integer ck_cke;
integer ck_odt;
integer ck_dll_reset;
integer ck_bank_write [`BANKS-1:0];
integer ck_bank_read [`BANKS-1:0];
time tm_refresh;
time tm_precharge;
time tm_precharge_all;
time tm_activate;
time tm_write_end;
time tm_self_refresh;
time tm_odt_en;
time tm_bank_precharge [`BANKS-1:0];
time tm_bank_activate [`BANKS-1:0];
time tm_bank_write_end [`BANKS-1:0];
time tm_bank_read_end [`BANKS-1:0];
 
// pipelines
reg [`MAX_PIPE:0] al_pipeline;
reg [`MAX_PIPE:0] wr_pipeline;
reg [`MAX_PIPE:0] rd_pipeline;
reg [`MAX_PIPE:0] odt_pipeline;
reg [BA_BITS-1:0] ba_pipeline [`MAX_PIPE:0];
reg [ROW_BITS-1:0] row_pipeline [`MAX_PIPE:0];
reg [COL_BITS-1:0] col_pipeline [`MAX_PIPE:0];
reg prev_cke;
// data state
reg [BL_MAX*DQ_BITS-1:0] memory_data;
reg [BL_MAX*DQ_BITS-1:0] bit_mask;
reg [BL_BITS-1:0] burst_position;
reg [BL_BITS:0] burst_cntr;
reg [DQ_BITS-1:0] dq_temp;
reg [35:0] check_write_postamble;
reg [35:0] check_write_preamble;
reg [35:0] check_write_dqs_high;
reg [35:0] check_write_dqs_low;
reg [17:0] check_dm_tdipw;
reg [71:0] check_dq_tdipw;
 
// data timers/counters
time tm_cke;
time tm_odt;
time tm_tdqss;
time tm_dm [17:0];
time tm_dqs [17:0];
time tm_dqs_pos [35:0];
time tm_dqss_pos [35:0];
time tm_dqs_neg [35:0];
time tm_dq [71:0];
time tm_cmd_addr [22:0];
reg [8*7-1:0] cmd_addr_string [22:0];
initial begin
cmd_addr_string[ 0] = "CS_N ";
cmd_addr_string[ 1] = "RAS_N ";
cmd_addr_string[ 2] = "CAS_N ";
cmd_addr_string[ 3] = "WE_N ";
cmd_addr_string[ 4] = "BA 0 ";
cmd_addr_string[ 5] = "BA 1 ";
cmd_addr_string[ 6] = "BA 2 ";
cmd_addr_string[ 7] = "ADDR 0";
cmd_addr_string[ 8] = "ADDR 1";
cmd_addr_string[ 9] = "ADDR 2";
cmd_addr_string[10] = "ADDR 3";
cmd_addr_string[11] = "ADDR 4";
cmd_addr_string[12] = "ADDR 5";
cmd_addr_string[13] = "ADDR 6";
cmd_addr_string[14] = "ADDR 7";
cmd_addr_string[15] = "ADDR 8";
cmd_addr_string[16] = "ADDR 9";
cmd_addr_string[17] = "ADDR 10";
cmd_addr_string[18] = "ADDR 11";
cmd_addr_string[19] = "ADDR 12";
cmd_addr_string[20] = "ADDR 13";
cmd_addr_string[21] = "ADDR 14";
cmd_addr_string[22] = "ADDR 15";
end
 
reg [8*5-1:0] dqs_string [1:0];
initial begin
dqs_string[0] = "DQS ";
dqs_string[1] = "DQS_N";
end
 
// Memory Storage
`ifdef MAX_MEM
reg [BL_MAX*DQ_BITS-1:0] memory [0:`MAX_SIZE-1];
`else
reg [BL_MAX*DQ_BITS-1:0] memory [0:`MEM_SIZE-1];
reg [`MAX_BITS-1:0] address [0:`MEM_SIZE-1];
reg [MEM_BITS:0] memory_index;
reg [MEM_BITS:0] memory_used;
`endif
 
// receive
reg ck_in;
reg ck_n_in;
reg cke_in;
reg cs_n_in;
reg ras_n_in;
reg cas_n_in;
reg we_n_in;
reg [17:0] dm_in;
reg [2:0] ba_in;
reg [15:0] addr_in;
reg [71:0] dq_in;
reg [35:0] dqs_in;
reg odt_in;
 
reg [17:0] dm_in_pos;
reg [17:0] dm_in_neg;
reg [71:0] dq_in_pos;
reg [71:0] dq_in_neg;
reg dq_in_valid;
reg dqs_in_valid;
integer wdqs_cntr;
integer wdq_cntr;
integer wdqs_pos_cntr [35:0];
reg b2b_write;
reg [35:0] prev_dqs_in;
reg diff_ck;
 
always @(ck ) ck_in <= #BUS_DELAY ck;
always @(ck_n ) ck_n_in <= #BUS_DELAY ck_n;
always @(cke ) cke_in <= #BUS_DELAY cke;
always @(cs_n ) cs_n_in <= #BUS_DELAY cs_n;
always @(ras_n ) ras_n_in <= #BUS_DELAY ras_n;
always @(cas_n ) cas_n_in <= #BUS_DELAY cas_n;
always @(we_n ) we_n_in <= #BUS_DELAY we_n;
always @(dm_rdqs) dm_in <= #BUS_DELAY dm_rdqs;
always @(ba ) ba_in <= #BUS_DELAY ba;
always @(addr ) addr_in <= #BUS_DELAY addr;
always @(dq ) dq_in <= #BUS_DELAY dq;
always @(dqs or dqs_n) dqs_in <= #BUS_DELAY (dqs_n<<18) | dqs;
always @(odt ) odt_in <= #BUS_DELAY odt;
// create internal clock
always @(posedge ck_in) diff_ck <= ck_in;
always @(posedge ck_n_in) diff_ck <= ~ck_n_in;
 
wire [17:0] dqs_even = dqs_in[17:0];
wire [17:0] dqs_odd = dqs_n_en ? dqs_in[35:18] : ~dqs_in[17:0];
wire [3:0] cmd_n_in = !cs_n_in ? {ras_n_in, cas_n_in, we_n_in} : NOP; //deselect = nop
 
// transmit
reg dqs_out_en;
reg [DQS_BITS-1:0] dqs_out_en_dly;
reg dqs_out;
reg [DQS_BITS-1:0] dqs_out_dly;
reg dq_out_en;
reg [DQ_BITS-1:0] dq_out_en_dly;
reg [DQ_BITS-1:0] dq_out;
reg [DQ_BITS-1:0] dq_out_dly;
integer rdqsen_cntr;
integer rdqs_cntr;
integer rdqen_cntr;
integer rdq_cntr;
 
bufif1 buf_dqs [DQS_BITS-1:0] (dqs, dqs_out_dly, dqs_out_en_dly & {DQS_BITS{out_en}});
bufif1 buf_dm [DM_BITS-1:0] (dm_rdqs, dqs_out_dly, dqs_out_en_dly & {DM_BITS {out_en}} & {DM_BITS{rdqs_en}});
bufif1 buf_dqs_n [DQS_BITS-1:0] (dqs_n, ~dqs_out_dly, dqs_out_en_dly & {DQS_BITS{out_en}} & {DQS_BITS{dqs_n_en}});
bufif1 buf_rdqs_n [DQS_BITS-1:0] (rdqs_n, ~dqs_out_dly, dqs_out_en_dly & {DQS_BITS{out_en}} & {DQS_BITS{dqs_n_en}} & {DQS_BITS{rdqs_en}});
bufif1 buf_dq [DQ_BITS-1:0] (dq, dq_out_dly, dq_out_en_dly & {DQ_BITS {out_en}});
 
initial begin
if (BL_MAX < 2)
$display("%m ERROR: BL_MAX parameter must be >= 2. \nBL_MAX = %d", BL_MAX);
if ((1<<BO_BITS) > BL_MAX)
$display("%m ERROR: 2^BO_BITS cannot be greater than BL_MAX parameter.");
$timeformat (-12, 1, " ps", 1);
reset_task;
seed = RANDOM_SEED;
ck_cntr = 0;
end
 
// calculate the absolute value of a real number
function real abs_value;
input arg;
real arg;
begin
if (arg < 0.0)
abs_value = -1.0 * arg;
else
abs_value = arg;
end
endfunction
 
`ifdef MAX_MEM
`else
function get_index;
input [`MAX_BITS-1:0] addr;
begin : index
get_index = 0;
for (memory_index=0; memory_index<memory_used; memory_index=memory_index+1) begin
if (address[memory_index] == addr) begin
get_index = 1;
disable index;
end
end
end
endfunction
`endif
 
task memory_write;
input [BA_BITS-1:0] bank;
input [ROW_BITS-1:0] row;
input [COL_BITS-1:0] col;
input [BL_MAX*DQ_BITS-1:0] data;
reg [`MAX_BITS-1:0] addr;
begin
// chop off the lowest address bits
addr = {bank, row, col}/BL_MAX;
`ifdef MAX_MEM
memory[addr] = data;
`else
if (get_index(addr)) begin
address[memory_index] = addr;
memory[memory_index] = data;
end else if (memory_used == `MEM_SIZE) begin
$display ("%m: at time %t ERROR: Memory overflow. Write to Address %h with Data %h will be lost.\nYou must increase the MEM_BITS parameter or define MAX_MEM.", $time, addr, data);
if (STOP_ON_ERROR) $stop(0);
end else begin
address[memory_used] = addr;
memory[memory_used] = data;
memory_used = memory_used + 1;
end
`endif
end
endtask
 
task memory_read;
input [BA_BITS-1:0] bank;
input [ROW_BITS-1:0] row;
input [COL_BITS-1:0] col;
output [BL_MAX*DQ_BITS-1:0] data;
reg [`MAX_BITS-1:0] addr;
begin
// chop off the lowest address bits
addr = {bank, row, col}/BL_MAX;
`ifdef MAX_MEM
data = memory[addr];
`else
if (get_index(addr)) begin
data = memory[memory_index];
end else begin
data = {BL_MAX*DQ_BITS{1'bx}};
end
`endif
end
endtask
 
// Before this task runs, the model must be in a valid state for precharge power down.
// After this task runs, NOP commands must be issued until tRFC has been met
task initialize;
input [ADDR_BITS-1:0] mode_reg0;
input [ADDR_BITS-1:0] mode_reg1;
input [ADDR_BITS-1:0] mode_reg2;
input [ADDR_BITS-1:0] mode_reg3;
begin
if (DEBUG) $display ("%m: at time %t INFO: Performing Initialization Sequence", $time);
cmd_task(1, NOP, 'bx, 'bx);
cmd_task(1, PRECHARGE, 'bx, 1<<AP); // Precharege ALL
cmd_task(1, LOAD_MODE, 3, mode_reg3);
cmd_task(1, LOAD_MODE, 2, mode_reg2);
cmd_task(1, LOAD_MODE, 1, mode_reg1);
cmd_task(1, LOAD_MODE, 0, mode_reg0 | 'h100); // DLL Reset
cmd_task(1, PRECHARGE, 'bx, 1<<AP); // Precharege ALL
cmd_task(1, REFRESH, 'bx, 'bx);
cmd_task(1, REFRESH, 'bx, 'bx);
cmd_task(1, LOAD_MODE, 0, mode_reg0);
cmd_task(1, LOAD_MODE, 1, mode_reg1 | 'h380); // OCD Default
cmd_task(1, LOAD_MODE, 1, mode_reg1);
cmd_task(0, NOP, 'bx, 'bx);
end
endtask
task reset_task;
integer i;
begin
// disable inputs
dq_in_valid = 0;
dqs_in_valid <= 0;
wdqs_cntr = 0;
wdq_cntr = 0;
for (i=0; i<36; i=i+1) begin
wdqs_pos_cntr[i] <= 0;
end
b2b_write <= 0;
// disable outputs
out_en = 0;
dqs_n_en = 0;
rdqs_en = 0;
dq_out_en = 0;
rdq_cntr = 0;
dqs_out_en = 0;
rdqs_cntr = 0;
// disable ODT
odt_en = 0;
odt_state = 0;
// reset bank state
active_bank = {`BANKS{1'b1}};
auto_precharge_bank = 0;
read_precharge_bank = 0;
write_precharge_bank = 0;
// require initialization sequence
init_done = 0;
init_step = 0;
init_mode_reg = 0;
// reset DLL
dll_en = 0;
dll_reset = 0;
dll_locked = 0;
ocd = 0;
// exit power down and self refresh
in_power_down = 0;
in_self_refresh = 0;
// clear pipelines
al_pipeline = 0;
wr_pipeline = 0;
rd_pipeline = 0;
odt_pipeline = 0;
// clear memory
`ifdef MAX_MEM
for (i=0; i<=`MAX_SIZE; i=i+1) begin //erase memory ... one address at a time
memory[i] <= 'bx;
end
`else
memory_used <= 0; //erase memory
`endif
// clear maximum timing checks
tm_refresh <= 'bx;
for (i=0; i<`BANKS; i=i+1) begin
tm_bank_activate[i] <= 'bx;
end
end
endtask
 
task chk_err;
input samebank;
input [BA_BITS-1:0] bank;
input [3:0] fromcmd;
input [3:0] cmd;
reg err;
begin
// all matching case expressions will be evaluated
casex ({samebank, fromcmd, cmd})
{1'b0, LOAD_MODE, 4'b0xxx } : begin if (ck_cntr - ck_load_mode < TMRD) $display ("%m: at time %t ERROR: tMRD violation during %s", $time, cmd_string[cmd]); end
{1'b0, LOAD_MODE, 4'b100x } : begin if (ck_cntr - ck_load_mode < TMRD) begin $display ("%m: at time %t INFO: Load Mode to Reset condition.", $time); init_done = 0; end end
{1'b0, REFRESH , 4'b0xxx } : begin if ($time - tm_refresh < TRFC_MIN) $display ("%m: at time %t ERROR: tRFC violation during %s", $time, cmd_string[cmd]); end
{1'b0, REFRESH , PWR_DOWN } : ; // 1 tCK
{1'b0, REFRESH , SELF_REF } : begin if ($time - tm_refresh < TRFC_MIN) begin $display ("%m: at time %t INFO: Refresh to Reset condition", $time); init_done = 0; end end
{1'b0, PRECHARGE, 4'b000x } : begin if ($time - tm_precharge_all < TRPA) $display ("%m: at time %t ERROR: tRPA violation during %s", $time, cmd_string[cmd]);
if ($time - tm_precharge < TRP) $display ("%m: at time %t ERROR: tRP violation during %s", $time, cmd_string[cmd]); end
{1'b1, PRECHARGE, PRECHARGE} : begin if (DEBUG && ($time - tm_precharge_all < TRPA)) $display ("%m: at time %t INFO: Precharge All interruption during %s", $time, cmd_string[cmd]);
if (DEBUG && ($time - tm_bank_precharge[bank] < TRP)) $display ("%m: at time %t INFO: Precharge bank %d interruption during %s", $time, cmd_string[cmd], bank); end
{1'b1, PRECHARGE, ACTIVATE } : begin if ($time - tm_precharge_all < TRPA) $display ("%m: at time %t ERROR: tRPA violation during %s", $time, cmd_string[cmd]);
if ($time - tm_bank_precharge[bank] < TRP) $display ("%m: at time %t ERROR: tRP violation during %s to bank %d", $time, cmd_string[cmd], bank); end
{1'b0, PRECHARGE, PWR_DOWN } : ; //1 tCK, can be concurrent with auto precharge
{1'b0, PRECHARGE, SELF_REF } : begin if (($time - tm_precharge_all < TRPA) || ($time - tm_precharge < TRP)) begin $display ("%m: at time %t INFO: Precharge to Reset condition", $time); init_done = 0; end end
{1'b0, ACTIVATE , REFRESH } : begin if ($time - tm_activate < TRC) $display ("%m: at time %t ERROR: tRC violation during %s", $time, cmd_string[cmd]); end
{1'b1, ACTIVATE , PRECHARGE} : begin if (($time - tm_bank_activate[bank] > TRAS_MAX) && (active_bank[bank] === 1'b1)) $display ("%m: at time %t ERROR: tRAS maximum violation during %s to bank %d", $time, cmd_string[cmd], bank);
if ($time - tm_bank_activate[bank] < TRAS_MIN) $display ("%m: at time %t ERROR: tRAS minimum violation during %s to bank %d", $time, cmd_string[cmd], bank);end
{1'b0, ACTIVATE , ACTIVATE } : begin if ($time - tm_activate < TRRD) $display ("%m: at time %t ERROR: tRRD violation during %s to bank %d", $time, cmd_string[cmd], bank); end
{1'b1, ACTIVATE , ACTIVATE } : begin if ($time - tm_bank_activate[bank] < TRC) $display ("%m: at time %t ERROR: tRC violation during %s to bank %d", $time, cmd_string[cmd], bank); end
{1'b1, ACTIVATE , 4'b010x } : ; // tRCD is checked outside this task
{1'b1, ACTIVATE , PWR_DOWN } : ; // 1 tCK
{1'b1, WRITE , PRECHARGE} : begin if ((ck_cntr - ck_bank_write[bank] <= write_latency + burst_length/2) || ($time - tm_bank_write_end[bank] < TWR)) $display ("%m: at time %t ERROR: tWR violation during %s to bank %d", $time, cmd_string[cmd], bank); end
{1'b0, WRITE , WRITE } : begin if (ck_cntr - ck_write < TCCD) $display ("%m: at time %t ERROR: tCCD violation during %s to bank %d", $time, cmd_string[cmd], bank); end
{1'b0, WRITE , READ } : begin if ((ck_load_mode < ck_write) && (ck_cntr - ck_write < write_latency + burst_length/2 + 2 - additive_latency)) $display ("%m: at time %t ERROR: tWTR violation during %s to bank %d", $time, cmd_string[cmd], bank); end
{1'b0, WRITE , PWR_DOWN } : begin if ((ck_load_mode < ck_write) && (
|write_precharge_bank
|| (ck_cntr - ck_write_ap < 1)
|| (ck_cntr - ck_write < write_latency + burst_length/2 + 2)
|| ($time - tm_write_end < TWTR))) begin $display ("%m: at time %t INFO: Write to Reset condition", $time); init_done = 0; end end
{1'b1, READ , PRECHARGE} : begin if ((ck_cntr - ck_bank_read[bank] < additive_latency + burst_length/2) || ($time - tm_bank_read_end[bank] < TRTP)) $display ("%m: at time %t ERROR: tRTP violation during %s to bank %d", $time, cmd_string[cmd], bank); end
{1'b0, READ , WRITE } : begin if ((ck_load_mode < ck_read) && (ck_cntr - ck_read < read_latency + burst_length/2 + 1 - write_latency)) $display ("%m: at time %t ERROR: tRTW violation during %s to bank %d", $time, cmd_string[cmd], bank); end
{1'b0, READ , READ } : begin if (ck_cntr - ck_read < TCCD) $display ("%m: at time %t ERROR: tCCD violation during %s to bank %d", $time, cmd_string[cmd], bank); end
{1'b0, READ , PWR_DOWN } : begin if ((ck_load_mode < ck_read) && (ck_cntr - ck_read < read_latency + burst_length/2 + 1)) begin $display ("%m: at time %t INFO: Read to Reset condition", $time); init_done = 0; end end
{1'b0, PWR_DOWN , 4'b00xx } : begin if (ck_cntr - ck_power_down < TXP) $display ("%m: at time %t ERROR: tXP violation during %s", $time, cmd_string[cmd]); end
{1'b0, PWR_DOWN , WRITE } : begin if (ck_cntr - ck_power_down < TXP) $display ("%m: at time %t ERROR: tXP violation during %s", $time, cmd_string[cmd]); end
{1'b0, PWR_DOWN , READ } : begin if (ck_cntr - ck_slow_exit_pd < TXARDS - additive_latency) $display ("%m: at time %t ERROR: tXARDS violation during %s", $time, cmd_string[cmd]);
else if (ck_cntr - ck_power_down < TXARD) $display ("%m: at time %t ERROR: tXARD violation during %s", $time, cmd_string[cmd]); end
{1'b0, SELF_REF , 4'b00xx } : begin if ($time - tm_self_refresh < TXSNR) $display ("%m: at time %t ERROR: tXSNR violation during %s", $time, cmd_string[cmd]); end
{1'b0, SELF_REF , WRITE } : begin if ($time - tm_self_refresh < TXSNR) $display ("%m: at time %t ERROR: tXSNR violation during %s", $time, cmd_string[cmd]); end
{1'b0, SELF_REF , READ } : begin if (ck_cntr - ck_self_refresh < TXSRD) $display ("%m: at time %t ERROR: tXSRD violation during %s", $time, cmd_string[cmd]); end
{1'b0, 4'b100x , 4'b100x } : begin if (ck_cntr - ck_cke < TCKE) begin $display ("%m: at time %t ERROR: tCKE violation on CKE", $time); init_done = 0; end end
endcase
end
endtask
 
task cmd_task;
input cke;
input [2:0] cmd;
input [BA_BITS-1:0] bank;
input [ADDR_BITS-1:0] addr;
reg [`BANKS:0] i;
integer j;
reg [`BANKS:0] tfaw_cntr;
reg [COL_BITS-1:0] col;
begin
 
// tRFC max check
if (!er_trfc_max && !in_self_refresh) begin
if ($time - tm_refresh > TRFC_MAX) begin
$display ("%m: at time %t ERROR: tRFC maximum violation during %s", $time, cmd_string[cmd]);
er_trfc_max = 1;
end
end
if (cke) begin
if ((cmd < NOP) && ((cmd != PRECHARGE) || !addr[AP])) begin
for (j=0; j<NOP; j=j+1) begin
chk_err(1'b0, bank, j, cmd);
chk_err(1'b1, bank, j, cmd);
end
chk_err(1'b0, bank, PWR_DOWN, cmd);
chk_err(1'b0, bank, SELF_REF, cmd);
end
 
case (cmd)
LOAD_MODE : begin
if (|active_bank) begin
$display ("%m: at time %t ERROR: %s Failure. All banks must be Precharged.", $time, cmd_string[cmd]);
if (STOP_ON_ERROR) $stop(0);
end else begin
if (DEBUG) $display ("%m: at time %t INFO: %s %d", $time, cmd_string[cmd], bank);
case (bank)
0 : begin
// Burst Length
burst_length = 1<<addr[2:0];
if ((burst_length >= BL_MIN) && (burst_length <= BL_MAX)) begin
if (DEBUG) $display ("%m: at time %t INFO: %s %d Burst Length = %d", $time, cmd_string[cmd], bank, burst_length);
end else begin
$display ("%m: at time %t ERROR: %s %d Illegal Burst Length = %d", $time, cmd_string[cmd], bank, burst_length);
end
// Burst Order
burst_order = addr[3];
if (!burst_order) begin
if (DEBUG) $display ("%m: at time %t INFO: %s %d Burst Order = Sequential", $time, cmd_string[cmd], bank);
end else if (burst_order) begin
if (DEBUG) $display ("%m: at time %t INFO: %s %d Burst Order = Interleaved", $time, cmd_string[cmd], bank);
end else begin
$display ("%m: at time %t ERROR: %s %d Illegal Burst Order = %d", $time, cmd_string[cmd], bank, burst_order);
end
// CAS Latency
cas_latency = addr[6:4];
read_latency = cas_latency + additive_latency;
write_latency = read_latency - 1;
if ((cas_latency >= CL_MIN) && (cas_latency <= CL_MAX)) begin
if (DEBUG) $display ("%m: at time %t INFO: %s %d CAS Latency = %d", $time, cmd_string[cmd], bank, cas_latency);
end else begin
$display ("%m: at time %t ERROR: %s %d Illegal CAS Latency = %d", $time, cmd_string[cmd], bank, cas_latency);
end
// Test Mode
if (!addr[7]) begin
if (DEBUG) $display ("%m: at time %t INFO: %s %d Test Mode = Normal", $time, cmd_string[cmd], bank);
end else begin
$display ("%m: at time %t ERROR: %s %d Illegal Test Mode = %d", $time, cmd_string[cmd], bank, addr[7]);
end
// DLL Reset
dll_reset = addr[8];
if (!dll_reset) begin
if (DEBUG) $display ("%m: at time %t INFO: %s %d DLL Reset = Normal", $time, cmd_string[cmd], bank);
end else if (dll_reset) begin
if (DEBUG) $display ("%m: at time %t INFO: %s %d DLL Reset = Reset DLL", $time, cmd_string[cmd], bank);
dll_locked = 0;
ck_dll_reset <= ck_cntr;
end else begin
$display ("%m: at time %t ERROR: %s %d Illegal DLL Reset = %d", $time, cmd_string[cmd], bank, dll_reset);
end
// Write Recovery
write_recovery = addr[11:9] + 1;
if ((write_recovery >= WR_MIN) && (write_recovery <= WR_MAX)) begin
if (DEBUG) $display ("%m: at time %t INFO: %s %d Write Recovery = %d", $time, cmd_string[cmd], bank, write_recovery);
end else begin
$display ("%m: at time %t ERROR: %s %d Illegal Write Recovery = %d", $time, cmd_string[cmd], bank, write_recovery);
end
// Power Down Mode
low_power = addr[12];
if (!low_power) begin
if (DEBUG) $display ("%m: at time %t INFO: %s %d Power Down Mode = Fast Exit", $time, cmd_string[cmd], bank);
end else if (low_power) begin
if (DEBUG) $display ("%m: at time %t INFO: %s %d Power Down Mode = Slow Exit", $time, cmd_string[cmd], bank);
end else begin
$display ("%m: at time %t ERROR: %s %d Illegal Power Down Mode = %d", $time, cmd_string[cmd], bank, low_power);
end
end
1 : begin
// DLL Enable
dll_en = !addr[0];
if (!dll_en) begin
if (DEBUG) $display ("%m: at time %t INFO: %s %d DLL Enable = Disabled", $time, cmd_string[cmd], bank);
end else if (dll_en) begin
if (DEBUG) $display ("%m: at time %t INFO: %s %d DLL Enable = Enabled", $time, cmd_string[cmd], bank);
end else begin
$display ("%m: at time %t ERROR: %s %d Illegal DLL Enable = %d", $time, cmd_string[cmd], bank, dll_en);
end
// Output Drive Strength
if (!addr[1]) begin
if (DEBUG) $display ("%m: at time %t INFO: %s %d Output Drive Strength = Full", $time, cmd_string[cmd], bank);
end else if (addr[1]) begin
if (DEBUG) $display ("%m: at time %t INFO: %s %d Output Drive Strength = Reduced", $time, cmd_string[cmd], bank);
end else begin
$display ("%m: at time %t ERROR: %s %d Illegal Output Drive Strength = %d", $time, cmd_string[cmd], bank, addr[1]);
end
// ODT Rtt
odt_rtt = {addr[6], addr[2]};
if (odt_rtt == 2'b00) begin
if (DEBUG) $display ("%m: at time %t INFO: %s %d ODT Rtt = Disabled", $time, cmd_string[cmd], bank);
odt_en = 0;
end else if (odt_rtt == 2'b01) begin
if (DEBUG) $display ("%m: at time %t INFO: %s %d ODT Rtt = 75 Ohm", $time, cmd_string[cmd], bank);
odt_en = 1;
tm_odt_en <= $time;
end else if (odt_rtt == 2'b10) begin
if (DEBUG) $display ("%m: at time %t INFO: %s %d ODT Rtt = 150 Ohm", $time, cmd_string[cmd], bank);
odt_en = 1;
tm_odt_en <= $time;
end else if (odt_rtt == 2'b11) begin
if (DEBUG) $display ("%m: at time %t INFO: %s %d ODT Rtt = 50 Ohm", $time, cmd_string[cmd], bank);
odt_en = 1;
tm_odt_en <= $time;
end else begin
$display ("%m: at time %t ERROR: %s %d Illegal ODT Rtt = %d", $time, cmd_string[cmd], bank, odt_rtt);
odt_en = 0;
end
// Additive Latency
additive_latency = addr[5:3];
read_latency = cas_latency + additive_latency;
write_latency = read_latency - 1;
if ((additive_latency >= AL_MIN) && (additive_latency <= AL_MAX)) begin
if (DEBUG) $display ("%m: at time %t INFO: %s %d Additive Latency = %d", $time, cmd_string[cmd], bank, additive_latency);
end else begin
$display ("%m: at time %t ERROR: %s %d Illegal Additive Latency = %d", $time, cmd_string[cmd], bank, additive_latency);
end
// OCD Program
ocd = addr[9:7];
if (ocd == 3'b000) begin
if (DEBUG) $display ("%m: at time %t INFO: %s %d OCD Program = OCD Exit", $time, cmd_string[cmd], bank);
end else if (ocd == 3'b111) begin
if (DEBUG) $display ("%m: at time %t INFO: %s %d OCD Program = OCD Default", $time, cmd_string[cmd], bank);
end else begin
$display ("%m: at time %t ERROR: %s %d Illegal OCD Program = %b", $time, cmd_string[cmd], bank, ocd);
end
 
// DQS_N Enable
dqs_n_en = !addr[10];
if (!dqs_n_en) begin
if (DEBUG) $display ("%m: at time %t INFO: %s %d DQS_N Enable = Disabled", $time, cmd_string[cmd], bank);
end else if (dqs_n_en) begin
if (DEBUG) $display ("%m: at time %t INFO: %s %d DQS_N Enable = Enabled", $time, cmd_string[cmd], bank);
end else begin
$display ("%m: at time %t ERROR: %s %d Illegal DQS_N Enable = %d", $time, cmd_string[cmd], bank, dqs_n_en);
end
// RDQS Enable
rdqs_en = addr[11];
if (!rdqs_en) begin
if (DEBUG) $display ("%m: at time %t INFO: %s %d RDQS Enable = Disabled", $time, cmd_string[cmd], bank);
end else if (rdqs_en) begin
`ifdef x8
if (DEBUG) $display ("%m: at time %t INFO: %s %d RDQS Enable = Enabled", $time, cmd_string[cmd], bank);
`else
$display ("%m: at time %t WARNING: %s %d Illegal RDQS Enable. RDQS only exists on a x8 part", $time, cmd_string[cmd], bank);
rdqs_en = 0;
`endif
end else begin
$display ("%m: at time %t ERROR: %s %d Illegal RDQS Enable = %d", $time, cmd_string[cmd], bank, rdqs_en);
end
// Output Enable
out_en = !addr[12];
if (!out_en) begin
if (DEBUG) $display ("%m: at time %t INFO: %s %d Output Enable = Disabled", $time, cmd_string[cmd], bank);
end else if (out_en) begin
if (DEBUG) $display ("%m: at time %t INFO: %s %d Output Enable = Enabled", $time, cmd_string[cmd], bank);
end else begin
$display ("%m: at time %t ERROR: %s %d Illegal Output Enable = %d", $time, cmd_string[cmd], bank, out_en);
end
end
2 : begin
// High Temperature Self Refresh rate
if (!addr[7]) begin
if (DEBUG) $display ("%m: at time %t INFO: %s %d High Temperature Self Refresh rate = Disabled", $time, cmd_string[cmd], bank);
end else if (addr[1]) begin
if (DEBUG) $display ("%m: at time %t INFO: %s %d High Temperature Self Refresh rate = Enabled", $time, cmd_string[cmd], bank);
end else begin
$display ("%m: at time %t ERROR: %s %d Illegal High Temperature Self Refresh rate = %d", $time, cmd_string[cmd], bank, addr[7]);
end
if ((addr & ~(1<<7)) !== 0) begin
$display ("%m: at time %t ERROR: %s %d Illegal value. Reserved bits must be programmed to zero", $time, cmd_string[cmd], bank);
end
end
3 : begin
if (addr !== 0) begin
$display ("%m: at time %t ERROR: %s %d Illegal value. Reserved bits must be programmed to zero", $time, cmd_string[cmd], bank);
end
end
endcase
init_mode_reg[bank] = 1;
ck_load_mode <= ck_cntr;
end
end
REFRESH : begin
if (|active_bank) begin
$display ("%m: at time %t ERROR: %s Failure. All banks must be Precharged.", $time, cmd_string[cmd]);
if (STOP_ON_ERROR) $stop(0);
end else begin
if (DEBUG) $display ("%m: at time %t INFO: %s", $time, cmd_string[cmd]);
er_trfc_max = 0;
ref_cntr = ref_cntr + 1;
tm_refresh <= $time;
end
end
PRECHARGE : begin
if (addr[AP]) begin
// tRPA timing applies when the PRECHARGE (ALL) command is issued, regardless of
// the number of banks already open or closed.
for (i=0; i<`BANKS; i=i+1) begin
for (j=0; j<NOP; j=j+1) begin
chk_err(1'b0, i, j, cmd);
chk_err(1'b1, i, j, cmd);
end
chk_err(1'b0, i, PWR_DOWN, cmd);
chk_err(1'b0, i, SELF_REF, cmd);
end
if (|auto_precharge_bank) begin
$display ("%m: at time %t ERROR: %s All Failure. Auto Precharge is scheduled.", $time, cmd_string[cmd]);
if (STOP_ON_ERROR) $stop(0);
end else begin
if (DEBUG) $display ("%m: at time %t INFO: %s All", $time, cmd_string[cmd]);
active_bank = 0;
tm_precharge_all <= $time;
end
end else begin
// A PRECHARGE command is allowed if there is no open row in that bank (idle state)
// or if the previously open row is already in the process of precharging.
// However, the precharge period will be determined by the last PRECHARGE command issued to the bank.
if (auto_precharge_bank[bank]) begin
$display ("%m: at time %t ERROR: %s Failure. Auto Precharge is scheduled to bank %d.", $time, cmd_string[cmd], bank);
if (STOP_ON_ERROR) $stop(0);
end else begin
if (DEBUG) $display ("%m: at time %t INFO: %s bank %d", $time, cmd_string[cmd], bank);
active_bank[bank] = 1'b0;
tm_bank_precharge[bank] <= $time;
tm_precharge <= $time;
end
end
end
ACTIVATE : begin
if (`BANKS == 8) begin
tfaw_cntr = 0;
for (i=0; i<`BANKS; i=i+1) begin
if ($time - tm_bank_activate[i] < TFAW) begin
tfaw_cntr = tfaw_cntr + 1;
end
end
if (tfaw_cntr > 3) begin
$display ("%m: at time %t ERROR: tFAW violation during %s to bank %d", $time, cmd_string[cmd], bank);
end
end
 
if (!init_done) begin
$display ("%m: at time %t ERROR: %s Failure. Initialization sequence is not complete.", $time, cmd_string[cmd]);
if (STOP_ON_ERROR) $stop(0);
end else if (active_bank[bank]) begin
$display ("%m: at time %t ERROR: %s Failure. Bank %d must be Precharged.", $time, cmd_string[cmd], bank);
if (STOP_ON_ERROR) $stop(0);
end else begin
if (addr >= 1<<ROW_BITS) begin
$display ("%m: at time %t WARNING: row = %h does not exist. Maximum row = %h", $time, addr, (1<<ROW_BITS)-1);
end
if (DEBUG) $display ("%m: at time %t INFO: %s bank %d row %h", $time, cmd_string[cmd], bank, addr);
active_bank[bank] = 1'b1;
active_row[bank] = addr;
tm_bank_activate[bank] <= $time;
tm_activate <= $time;
end
end
WRITE : begin
if (!init_done) begin
$display ("%m: at time %t ERROR: %s Failure. Initialization sequence is not complete.", $time, cmd_string[cmd]);
if (STOP_ON_ERROR) $stop(0);
end else if (!active_bank[bank]) begin
$display ("%m: at time %t ERROR: %s Failure. Bank %d must be Activated.", $time, cmd_string[cmd], bank);
if (STOP_ON_ERROR) $stop(0);
end else if (auto_precharge_bank[bank]) begin
$display ("%m: at time %t ERROR: %s Failure. Auto Precharge is scheduled to bank %d.", $time, cmd_string[cmd], bank);
if (STOP_ON_ERROR) $stop(0);
end else if ((ck_cntr - ck_write < burst_length/2) && (ck_cntr - ck_write)%2) begin
$display ("%m: at time %t ERROR: %s Failure. Illegal burst interruption.", $time, cmd_string[cmd]);
if (STOP_ON_ERROR) $stop(0);
end else begin
if (addr[AP]) begin
auto_precharge_bank[bank] = 1'b1;
write_precharge_bank[bank] = 1'b1;
end
col = ((addr>>1) & -1*(1<<AP)) | (addr & {AP{1'b1}});
if (col >= 1<<COL_BITS) begin
$display ("%m: at time %t WARNING: col = %h does not exist. Maximum col = %h", $time, col, (1<<COL_BITS)-1);
end
if (DEBUG) $display ("%m: at time %t INFO: %s bank %d col %h, auto precharge %d", $time, cmd_string[cmd], bank, col, addr[AP]);
wr_pipeline[2*write_latency + 1] = 1;
ba_pipeline[2*write_latency + 1] = bank;
row_pipeline[2*write_latency + 1] = active_row[bank];
col_pipeline[2*write_latency + 1] = col;
ck_bank_write[bank] <= ck_cntr;
ck_write <= ck_cntr;
end
end
READ : begin
if (!dll_locked)
$display ("%m: at time %t WARNING: %s prior to DLL locked. Failing to wait for synchronization to occur may result in a violation of the tAC or tDQSCK parameters.", $time, cmd_string[cmd]);
if (!init_done) begin
$display ("%m: at time %t ERROR: %s Failure. Initialization sequence is not complete.", $time, cmd_string[cmd]);
if (STOP_ON_ERROR) $stop(0);
end else if (!active_bank[bank]) begin
$display ("%m: at time %t ERROR: %s Failure. Bank %d must be Activated.", $time, cmd_string[cmd], bank);
if (STOP_ON_ERROR) $stop(0);
end else if (auto_precharge_bank[bank]) begin
$display ("%m: at time %t ERROR: %s Failure. Auto Precharge is scheduled to bank %d.", $time, cmd_string[cmd], bank);
if (STOP_ON_ERROR) $stop(0);
end else if ((ck_cntr - ck_read < burst_length/2) && (ck_cntr - ck_read)%2) begin
$display ("%m: at time %t ERROR: %s Failure. Illegal burst interruption.", $time, cmd_string[cmd]);
if (STOP_ON_ERROR) $stop(0);
end else begin
if (addr[AP]) begin
auto_precharge_bank[bank] = 1'b1;
read_precharge_bank[bank] = 1'b1;
end
col = ((addr>>1) & -1*(1<<AP)) | (addr & {AP{1'b1}});
if (col >= 1<<COL_BITS) begin
$display ("%m: at time %t WARNING: col = %h does not exist. Maximum col = %h", $time, col, (1<<COL_BITS)-1);
end
if (DEBUG) $display ("%m: at time %t INFO: %s bank %d col %h, auto precharge %d", $time, cmd_string[cmd], bank, col, addr[AP]);
rd_pipeline[2*read_latency - 1] = 1;
ba_pipeline[2*read_latency - 1] = bank;
row_pipeline[2*read_latency - 1] = active_row[bank];
col_pipeline[2*read_latency - 1] = col;
ck_bank_read[bank] <= ck_cntr;
ck_read <= ck_cntr;
end
end
NOP: begin
if (in_power_down) begin
if (DEBUG) $display ("%m: at time %t INFO: Power Down Exit", $time);
in_power_down = 0;
if (|active_bank & low_power) begin // slow exit active power down
ck_slow_exit_pd <= ck_cntr;
end
ck_power_down <= ck_cntr;
end
if (in_self_refresh) begin
if ($time - tm_cke < TISXR)
$display ("%m: at time %t ERROR: tISXR violation during Self Refresh Exit", $time);
if (DEBUG) $display ("%m: at time %t INFO: Self Refresh Exit", $time);
in_self_refresh = 0;
ck_dll_reset <= ck_cntr;
ck_self_refresh <= ck_cntr;
tm_self_refresh <= $time;
tm_refresh <= $time;
end
end
endcase
if ((prev_cke !== 1) && (cmd !== NOP)) begin
$display ("%m: at time %t ERROR: NOP or Deselect is required when CKE goes active.", $time);
end
if (!init_done) begin
case (init_step)
0 : begin
if ($time < 200000000)
$display ("%m: at time %t WARNING: 200 us is required before CKE goes active.", $time);
// if (cmd_chk + 200000000 > $time)
// $display("%m: at time %t WARNING: NOP or DESELECT is required for 200 us before CKE is brought high", $time);
init_step = init_step + 1;
end
1 : if (dll_en) init_step = init_step + 1;
2 : begin
if (&init_mode_reg && dll_reset) begin
active_bank = {`BANKS{1'b1}}; // require Precharge All or bank Precharges
ref_cntr = 0; // require refresh
init_step = init_step + 1;
end
end
3 : if (ref_cntr == 2) begin
init_step = init_step + 1;
end
4 : if (!dll_reset) init_step = init_step + 1;
5 : if (ocd == 3'b111) init_step = init_step + 1;
6 : begin
if (ocd == 3'b000) begin
if (DEBUG) $display ("%m: at time %t INFO: Initialization Sequence is complete", $time);
init_done = 1;
end
end
endcase
end
end else if (prev_cke) begin
if ((!init_done) && (init_step > 1)) begin
$display ("%m: at time %t ERROR: CKE must remain active until the initialization sequence is complete.", $time);
if (STOP_ON_ERROR) $stop(0);
end
case (cmd)
REFRESH : begin
for (j=0; j<NOP; j=j+1) begin
chk_err(1'b0, bank, j, SELF_REF);
end
chk_err(1'b0, bank, PWR_DOWN, SELF_REF);
chk_err(1'b0, bank, SELF_REF, SELF_REF);
if (|active_bank) begin
$display ("%m: at time %t ERROR: Self Refresh Failure. All banks must be Precharged.", $time);
if (STOP_ON_ERROR) $stop(0);
init_done = 0;
end else if (odt_en && odt_state) begin
$display ("%m: at time %t ERROR: ODT must be off prior to entering Self Refresh", $time);
if (STOP_ON_ERROR) $stop(0);
init_done = 0;
end else if (!init_done) begin
$display ("%m: at time %t ERROR: Self Refresh Failure. Initialization sequence is not complete.", $time);
if (STOP_ON_ERROR) $stop(0);
end else begin
if (DEBUG) $display ("%m: at time %t INFO: Self Refresh Enter", $time);
in_self_refresh = 1;
dll_locked = 0;
end
end
NOP : begin
// entering slow_exit or precharge power down and tANPD has not been satisfied
if ((low_power || (active_bank == 0)) && (ck_cntr - ck_odt < TANPD))
$display ("%m: at time %t WARNING: tANPD violation during %s. Synchronous or asynchronous change in termination resistance is possible.", $time, cmd_string[PWR_DOWN]);
for (j=0; j<NOP; j=j+1) begin
chk_err(1'b0, bank, j, PWR_DOWN);
end
chk_err(1'b0, bank, PWR_DOWN, PWR_DOWN);
chk_err(1'b0, bank, SELF_REF, PWR_DOWN);
 
if (!init_done) begin
$display ("%m: at time %t ERROR: Power Down Failure. Initialization sequence is not complete.", $time);
if (STOP_ON_ERROR) $stop(0);
end else begin
if (DEBUG) begin
if (|active_bank) begin
$display ("%m: at time %t INFO: Active Power Down Enter", $time);
end else begin
$display ("%m: at time %t INFO: Precharge Power Down Enter", $time);
end
end
in_power_down = 1;
end
end
default : begin
$display ("%m: at time %t ERROR: NOP, Deselect, or Refresh is required when CKE goes inactive.", $time);
init_done = 0;
end
endcase
if (!init_done) begin
if (DEBUG) $display ("%m: at time %t WARNING: Reset has occurred. Device must be re-initialized.", $time);
reset_task;
end
end
prev_cke = cke;
end
endtask
 
task data_task;
reg [BA_BITS-1:0] bank;
reg [ROW_BITS-1:0] row;
reg [COL_BITS-1:0] col;
integer i;
integer j;
begin
 
if (diff_ck) begin
for (i=0; i<36; i=i+1) begin
if (dq_in_valid && dll_locked && ($time - tm_dqs_neg[i] < $rtoi(TDSS*tck_avg)))
$display ("%m: at time %t ERROR: tDSS violation on %s bit %d", $time, dqs_string[i/18], i%18);
if (check_write_dqs_high[i])
$display ("%m: at time %t ERROR: %s bit %d latching edge required during the preceding clock period.", $time, dqs_string[i/18], i%18);
end
check_write_dqs_high <= 0;
end else begin
for (i=0; i<36; i=i+1) begin
if (dll_locked && dq_in_valid) begin
tm_tdqss = abs_value(1.0*tm_ck_pos - tm_dqss_pos[i]);
if ((tm_tdqss < tck_avg/2.0) && (tm_tdqss > TDQSS*tck_avg))
$display ("%m: at time %t ERROR: tDQSS violation on %s bit %d", $time, dqs_string[i/18], i%18);
end
if (check_write_dqs_low[i])
$display ("%m: at time %t ERROR: %s bit %d latching edge required during the preceding clock period", $time, dqs_string[i/18], i%18);
end
check_write_preamble <= 0;
check_write_postamble <= 0;
check_write_dqs_low <= 0;
end
 
if (wr_pipeline[0] || rd_pipeline[0]) begin
bank = ba_pipeline[0];
row = row_pipeline[0];
col = col_pipeline[0];
burst_cntr = 0;
memory_read(bank, row, col, memory_data);
end
 
// burst counter
if (burst_cntr < burst_length) begin
burst_position = col ^ burst_cntr;
if (!burst_order) begin
burst_position[BO_BITS-1:0] = col + burst_cntr;
end
burst_cntr = burst_cntr + 1;
end
 
// write dqs counter
if (wr_pipeline[WDQS_PRE + 1]) begin
wdqs_cntr = WDQS_PRE + burst_length + WDQS_PST - 1;
end
// write dqs
if ((wdqs_cntr == burst_length + WDQS_PST) && (wdq_cntr == 0)) begin //write preamble
check_write_preamble <= ({DQS_BITS{dqs_n_en}}<<18) | {DQS_BITS{1'b1}};
end
if (wdqs_cntr > 1) begin // write data
if ((wdqs_cntr - WDQS_PST)%2) begin
check_write_dqs_high <= ({DQS_BITS{dqs_n_en}}<<18) | {DQS_BITS{1'b1}};
end else begin
check_write_dqs_low <= ({DQS_BITS{dqs_n_en}}<<18) | {DQS_BITS{1'b1}};
end
end
if (wdqs_cntr == WDQS_PST) begin // write postamble
check_write_postamble <= ({DQS_BITS{dqs_n_en}}<<18) | {DQS_BITS{1'b1}};
end
if (wdqs_cntr > 0) begin
wdqs_cntr = wdqs_cntr - 1;
end
 
// write dq
if (dq_in_valid) begin // write data
bit_mask = 0;
if (diff_ck) begin
for (i=0; i<DM_BITS; i=i+1) begin
bit_mask = bit_mask | ({`DQ_PER_DQS{~dm_in_neg[i]}}<<(burst_position*DQ_BITS + i*`DQ_PER_DQS));
end
memory_data = (dq_in_neg<<(burst_position*DQ_BITS) & bit_mask) | (memory_data & ~bit_mask);
end else begin
for (i=0; i<DM_BITS; i=i+1) begin
bit_mask = bit_mask | ({`DQ_PER_DQS{~dm_in_pos[i]}}<<(burst_position*DQ_BITS + i*`DQ_PER_DQS));
end
memory_data = (dq_in_pos<<(burst_position*DQ_BITS) & bit_mask) | (memory_data & ~bit_mask);
end
dq_temp = memory_data>>(burst_position*DQ_BITS);
if (DEBUG) $display ("%m: at time %t INFO: WRITE @ DQS= bank = %h row = %h col = %h data = %h",$time, bank, row, (-1*BL_MAX & col) + burst_position, dq_temp);
if (burst_cntr%BL_MIN == 0) begin
memory_write(bank, row, col, memory_data);
end
end
if (wr_pipeline[1]) begin
wdq_cntr = burst_length;
end
if (wdq_cntr > 0) begin
wdq_cntr = wdq_cntr - 1;
dq_in_valid = 1'b1;
end else begin
dq_in_valid = 1'b0;
dqs_in_valid <= 1'b0;
for (i=0; i<36; i=i+1) begin
wdqs_pos_cntr[i] <= 0;
end
end
if (wr_pipeline[0]) begin
b2b_write <= 1'b0;
end
if (wr_pipeline[2]) begin
if (dqs_in_valid) begin
b2b_write <= 1'b1;
end
dqs_in_valid <= 1'b1;
end
// read dqs enable counter
if (rd_pipeline[RDQSEN_PRE]) begin
rdqsen_cntr = RDQSEN_PRE + burst_length + RDQSEN_PST - 1;
end
if (rdqsen_cntr > 0) begin
rdqsen_cntr = rdqsen_cntr - 1;
dqs_out_en = 1'b1;
end else begin
dqs_out_en = 1'b0;
end
// read dqs counter
if (rd_pipeline[RDQS_PRE]) begin
rdqs_cntr = RDQS_PRE + burst_length + RDQS_PST - 1;
end
// read dqs
if ((rdqs_cntr >= burst_length + RDQS_PST) && (rdq_cntr == 0)) begin //read preamble
dqs_out = 1'b0;
end else if (rdqs_cntr > RDQS_PST) begin // read data
dqs_out = rdqs_cntr - RDQS_PST;
end else if (rdqs_cntr > 0) begin // read postamble
dqs_out = 1'b0;
end else begin
dqs_out = 1'b1;
end
if (rdqs_cntr > 0) begin
rdqs_cntr = rdqs_cntr - 1;
end
 
// read dq enable counter
if (rd_pipeline[RDQEN_PRE]) begin
rdqen_cntr = RDQEN_PRE + burst_length + RDQEN_PST;
end
if (rdqen_cntr > 0) begin
rdqen_cntr = rdqen_cntr - 1;
dq_out_en = 1'b1;
end else begin
dq_out_en = 1'b0;
end
// read dq
if (rd_pipeline[0]) begin
rdq_cntr = burst_length;
end
if (rdq_cntr > 0) begin // read data
dq_temp = memory_data>>(burst_position*DQ_BITS);
dq_out = dq_temp;
if (DEBUG) $display ("%m: at time %t INFO: READ @ DQS= bank = %h row = %h col = %h data = %h",$time, bank, row, (-1*BL_MAX & col) + burst_position, dq_temp);
rdq_cntr = rdq_cntr - 1;
end else begin
dq_out = {DQ_BITS{1'b1}};
end
 
// delay signals prior to output
if (RANDOM_OUT_DELAY && (dqs_out_en || |dqs_out_en_dly || dq_out_en || |dq_out_en_dly)) begin
for (i=0; i<DQS_BITS; i=i+1) begin
// DQSCK requirements
// 1.) less than tDQSCK
// 2.) greater than -tDQSCK
// 3.) cannot change more than tQHS + tDQSQ from previous DQS edge
dqsck_max = TDQSCK;
if (dqsck_max > dqsck[i] + TQHS + TDQSQ) begin
dqsck_max = dqsck[i] + TQHS + TDQSQ;
end
dqsck_min = -1*TDQSCK;
if (dqsck_min < dqsck[i] - TQHS - TDQSQ) begin
dqsck_min = dqsck[i] - TQHS - TDQSQ;
end
 
// DQSQ requirements
// 1.) less than tAC - DQSCK
// 2.) less than tDQSQ
// 3.) greater than -tAC
// 4.) greater than tQH from previous DQS edge
dqsq_min = -1*TAC;
if (dqsq_min < dqsck[i] - TQHS) begin
dqsq_min = dqsck[i] - TQHS;
end
if (dqsck_min == dqsck_max) begin
dqsck[i] = dqsck_min;
end else begin
dqsck[i] = $dist_uniform(seed, dqsck_min, dqsck_max);
end
dqsq_max = TAC;
if (dqsq_max > TDQSQ + dqsck[i]) begin
dqsq_max = TDQSQ + dqsck[i];
end
 
dqs_out_en_dly[i] <= #(tck_avg/2.0 + ($random % TAC)) dqs_out_en;
dqs_out_dly[i] <= #(tck_avg/2.0 + dqsck[i]) dqs_out;
for (j=0; j<`DQ_PER_DQS; j=j+1) begin
if (dq_out_en) begin // tLZ2
dq_out_en_dly[i*`DQ_PER_DQS + j] <= #(tck_avg/2.0 + $dist_uniform(seed, -2*TAC, dqsq_max)) dq_out_en;
end else begin // tHZ
dq_out_en_dly[i*`DQ_PER_DQS + j] <= #(tck_avg/2.0 + ($random % TAC)) dq_out_en;
end
if (dqsq_min == dqsq_max) begin
dq_out_dly [i*`DQ_PER_DQS + j] <= #(tck_avg/2.0 + dqsq_min) dq_out[i*`DQ_PER_DQS + j];
end else begin
dq_out_dly [i*`DQ_PER_DQS + j] <= #(tck_avg/2.0 + $dist_uniform(seed, dqsq_min, dqsq_max)) dq_out[i*`DQ_PER_DQS + j];
end
end
end
end else begin
out_delay = tck_avg/2.0;
dqs_out_en_dly <= #(out_delay) {DQS_BITS{dqs_out_en}};
dqs_out_dly <= #(out_delay) {DQS_BITS{dqs_out }};
dq_out_en_dly <= #(out_delay) {DQ_BITS {dq_out_en }};
dq_out_dly <= #(out_delay) {DQ_BITS {dq_out }};
end
end
endtask
 
always @(diff_ck) begin : main
integer i;
 
if (!in_self_refresh && (diff_ck !== 1'b0) && (diff_ck !== 1'b1))
$display ("%m: at time %t ERROR: CK and CK_N are not allowed to go to an unknown state.", $time);
data_task;
if (diff_ck) begin
// check setup of command signals
if ($time > TIS) begin
if ($time - tm_cke < TIS)
$display ("%m: at time %t ERROR: tIS violation on CKE by %t", $time, tm_cke + TIS - $time);
if (cke_in) begin
for (i=0; i<22; i=i+1) begin
if ($time - tm_cmd_addr[i] < TIS)
$display ("%m: at time %t ERROR: tIS violation on %s by %t", $time, cmd_addr_string[i], tm_cmd_addr[i] + TIS - $time);
end
end
end
 
// update current state
if (!dll_locked && !in_self_refresh && (ck_cntr - ck_dll_reset == TDLLK)) begin
// check CL value against the clock frequency
if (cas_latency*tck_avg < CL_TIME)
$display ("%m: at time %t ERROR: CAS Latency = %d is illegal @tCK(avg) = %f", $time, cas_latency, tck_avg);
// check WR value against the clock frequency
if (write_recovery*tck_avg < TWR)
$display ("%m: at time %t ERROR: Write Recovery = %d is illegal @tCK(avg) = %f", $time, write_recovery, tck_avg);
dll_locked = 1;
end
if (|auto_precharge_bank) begin
for (i=0; i<`BANKS; i=i+1) begin
// Write with Auto Precharge Calculation
// 1. Meet minimum tRAS requirement
// 2. Write Latency PLUS BL/2 cycles PLUS WR after Write command
if (write_precharge_bank[i]
&& ($time - tm_bank_activate[i] >= TRAS_MIN)
&& (ck_cntr - ck_bank_write[i] >= write_latency + burst_length/2 + write_recovery)) begin
 
if (DEBUG) $display ("%m: at time %t INFO: Auto Precharge bank %d", $time, i);
write_precharge_bank[i] = 0;
active_bank[i] = 0;
auto_precharge_bank[i] = 0;
ck_write_ap = ck_cntr;
tm_bank_precharge[i] = $time;
tm_precharge = $time;
end
// Read with Auto Precharge Calculation
// 1. Meet minimum tRAS requirement
// 2. Additive Latency plus BL/2 cycles after Read command
// 3. tRTP after the last 4-bit prefetch
if (read_precharge_bank[i]
&& ($time - tm_bank_activate[i] >= TRAS_MIN)
&& (ck_cntr - ck_bank_read[i] >= additive_latency + burst_length/2)) begin
 
read_precharge_bank[i] = 0;
// In case the internal precharge is pushed out by tRTP, tRP starts at the point where
// the internal precharge happens (not at the next rising clock edge after this event).
if ($time - tm_bank_read_end[i] < TRTP) begin
if (DEBUG) $display ("%m: at time %t INFO: Auto Precharge bank %d", tm_bank_read_end[i] + TRTP, i);
active_bank[i] <= #(tm_bank_read_end[i] + TRTP - $time) 0;
auto_precharge_bank[i] <= #(tm_bank_read_end[i] + TRTP - $time) 0;
tm_bank_precharge[i] <= #(tm_bank_read_end[i] + TRTP - $time) tm_bank_read_end[i] + TRTP;
tm_precharge <= #(tm_bank_read_end[i] + TRTP - $time) tm_bank_read_end[i] + TRTP;
end else begin
if (DEBUG) $display ("%m: at time %t INFO: Auto Precharge bank %d", $time, i);
active_bank[i] = 0;
auto_precharge_bank[i] = 0;
tm_bank_precharge[i] = $time;
tm_precharge = $time;
end
end
end
end
 
// respond to incoming command
if (cke_in ^ prev_cke) begin
ck_cke <= ck_cntr;
end
 
cmd_task(cke_in, cmd_n_in, ba_in, addr_in);
if ((cmd_n_in == WRITE) || (cmd_n_in == READ)) begin
al_pipeline[2*additive_latency] = 1'b1;
end
if (al_pipeline[0]) begin
// check tRCD after additive latency
if ($time - tm_bank_activate[ba_pipeline[2*cas_latency - 1]] < TRCD) begin
if (rd_pipeline[2*cas_latency - 1]) begin
$display ("%m: at time %t ERROR: tRCD violation during %s", $time, cmd_string[READ]);
end else begin
$display ("%m: at time %t ERROR: tRCD violation during %s", $time, cmd_string[WRITE]);
end
end
// check tWTR after additive latency
if (rd_pipeline[2*cas_latency - 1]) begin
if ($time - tm_write_end < TWTR)
$display ("%m: at time %t ERROR: tWTR violation during %s", $time, cmd_string[READ]);
end
end
if (rd_pipeline[2*(cas_latency - burst_length/2 + 2) - 1]) begin
tm_bank_read_end[ba_pipeline[2*(cas_latency - burst_length/2 + 2) - 1]] <= $time;
end
for (i=0; i<`BANKS; i=i+1) begin
if ((ck_cntr - ck_bank_write[i] > write_latency) && (ck_cntr - ck_bank_write[i] <= write_latency + burst_length/2)) begin
tm_bank_write_end[i] <= $time;
tm_write_end <= $time;
end
end
 
// clk pin is disabled during self refresh
if (!in_self_refresh) begin
tjit_cc_time = $time - tm_ck_pos - tck_i;
tck_i = $time - tm_ck_pos;
tck_avg = tck_avg - tck_sample[ck_cntr%TDLLK]/$itor(TDLLK);
tck_avg = tck_avg + tck_i/$itor(TDLLK);
tck_sample[ck_cntr%TDLLK] = tck_i;
tjit_per_rtime = tck_i - tck_avg;
 
if (dll_locked) begin
// check accumulated error
terr_nper_rtime = 0;
for (i=0; i<50; i=i+1) begin
terr_nper_rtime = terr_nper_rtime + tck_sample[i] - tck_avg;
terr_nper_rtime = abs_value(terr_nper_rtime);
case (i)
0 :;
1 : if (terr_nper_rtime - TERR_2PER >= 1.0) $display ("%m: at time %t ERROR: tERR(2per) violation by %f ps.", $time, terr_nper_rtime - TERR_2PER);
2 : if (terr_nper_rtime - TERR_3PER >= 1.0) $display ("%m: at time %t ERROR: tERR(3per) violation by %f ps.", $time, terr_nper_rtime - TERR_3PER);
3 : if (terr_nper_rtime - TERR_4PER >= 1.0) $display ("%m: at time %t ERROR: tERR(4per) violation by %f ps.", $time, terr_nper_rtime - TERR_4PER);
4 : if (terr_nper_rtime - TERR_5PER >= 1.0) $display ("%m: at time %t ERROR: tERR(5per) violation by %f ps.", $time, terr_nper_rtime - TERR_5PER);
5,6,7,8,9 : if (terr_nper_rtime - TERR_N1PER >= 1.0) $display ("%m: at time %t ERROR: tERR(n1per) violation by %f ps.", $time, terr_nper_rtime - TERR_N1PER);
default : if (terr_nper_rtime - TERR_N2PER >= 1.0) $display ("%m: at time %t ERROR: tERR(n2per) violation by %f ps.", $time, terr_nper_rtime - TERR_N2PER);
endcase
end
 
// check tCK min/max/jitter
if (abs_value(tjit_per_rtime) - TJIT_PER >= 1.0)
$display ("%m: at time %t ERROR: tJIT(per) violation by %f ps.", $time, abs_value(tjit_per_rtime) - TJIT_PER);
if (abs_value(tjit_cc_time) - TJIT_CC >= 1.0)
$display ("%m: at time %t ERROR: tJIT(cc) violation by %f ps.", $time, abs_value(tjit_cc_time) - TJIT_CC);
if (TCK_MIN - tck_avg >= 1.0)
$display ("%m: at time %t ERROR: tCK(avg) minimum violation by %f ps.", $time, TCK_MIN - tck_avg);
if (tck_avg - TCK_MAX >= 1.0)
$display ("%m: at time %t ERROR: tCK(avg) maximum violation by %f ps.", $time, tck_avg - TCK_MAX);
if (tm_ck_pos + TCK_MIN - TJIT_PER > $time)
$display ("%m: at time %t ERROR: tCK(abs) minimum violation by %t", $time, tm_ck_pos + TCK_MIN - TJIT_PER - $time);
if (tm_ck_pos + TCK_MAX + TJIT_PER < $time)
$display ("%m: at time %t ERROR: tCK(abs) maximum violation by %t", $time, $time - tm_ck_pos - TCK_MAX - TJIT_PER);
 
// check tCL
if (tm_ck_neg + TCL_MIN*tck_avg - TJIT_DUTY > $time)
$display ("%m: at time %t ERROR: tCL(abs) minimum violation on CLK by %t", $time, tm_ck_neg + TCL_MIN*tck_avg - TJIT_DUTY - $time);
if (tm_ck_neg + TCL_MAX*tck_avg + TJIT_DUTY < $time)
$display ("%m: at time %t ERROR: tCL(abs) maximum violation on CLK by %t", $time, $time - tm_ck_neg - TCL_MAX*tck_avg - TJIT_DUTY);
if (tcl_avg < TCL_MIN*tck_avg)
$display ("%m: at time %t ERROR: tCL(avg) minimum violation on CLK by %t", $time, TCL_MIN*tck_avg - tcl_avg);
if (tcl_avg > TCL_MAX*tck_avg)
$display ("%m: at time %t ERROR: tCL(avg) maximum violation on CLK by %t", $time, tcl_avg - TCL_MAX*tck_avg);
end
 
// calculate the tch avg jitter
tch_avg = tch_avg - tch_sample[ck_cntr%TDLLK]/$itor(TDLLK);
tch_avg = tch_avg + tch_i/$itor(TDLLK);
tch_sample[ck_cntr%TDLLK] = tch_i;
 
// update timers/counters
tcl_i <= $time - tm_ck_neg;
end
 
prev_odt <= odt_in;
// update timers/counters
ck_cntr <= ck_cntr + 1;
tm_ck_pos <= $time;
end else begin
// clk pin is disabled during self refresh
if (!in_self_refresh) begin
if (dll_locked) begin
if (tm_ck_pos + TCH_MIN*tck_avg - TJIT_DUTY > $time)
$display ("%m: at time %t ERROR: tCH(abs) minimum violation on CLK by %t", $time, tm_ck_pos + TCH_MIN*tck_avg - TJIT_DUTY + $time);
if (tm_ck_pos + TCH_MAX*tck_avg + TJIT_DUTY < $time)
$display ("%m: at time %t ERROR: tCH(abs) maximum violation on CLK by %t", $time, $time - tm_ck_pos - TCH_MAX*tck_avg - TJIT_DUTY);
if (tch_avg < TCH_MIN*tck_avg)
$display ("%m: at time %t ERROR: tCH(avg) minimum violation on CLK by %t", $time, TCH_MIN*tck_avg - tch_avg);
if (tch_avg > TCH_MAX*tck_avg)
$display ("%m: at time %t ERROR: tCH(avg) maximum violation on CLK by %t", $time, tch_avg - TCH_MAX*tck_avg);
end
 
// calculate the tcl avg jitter
tcl_avg = tcl_avg - tcl_sample[ck_cntr%TDLLK]/$itor(TDLLK);
tcl_avg = tcl_avg + tcl_i/$itor(TDLLK);
tcl_sample[ck_cntr%TDLLK] = tcl_i;
 
// update timers/counters
tch_i <= $time - tm_ck_pos;
end
tm_ck_neg <= $time;
end
 
// on die termination
if (odt_en) begin
// clk pin is disabled during self refresh
if (!in_self_refresh && diff_ck) begin
if ($time - tm_odt < TIS) begin
$display ("%m: at time %t ERROR: tIS violation on ODT by %t", $time, tm_odt + TIS - $time);
end
if (prev_odt ^ odt_in) begin
if (!dll_locked)
$display ("%m: at time %t WARNING: tDLLK violation during ODT transition.", $time);
if (odt_in && ($time - tm_odt_en < TMOD))
$display ("%m: at time %t ERROR: tMOD violation during ODT transition", $time);
if ($time - tm_self_refresh < TXSNR)
$display ("%m: at time %t ERROR: tXSNR violation during ODT transition", $time);
if (in_self_refresh)
$display ("%m: at time %t ERROR: Illegal ODT transition during Self Refresh.", $time);
 
// async ODT mode applies:
// 1.) during active power down with slow exit
// 2.) during precharge power down
// 3.) if tANPD has not been satisfied
// 4.) until tAXPD has been satisfied
if ((in_power_down && (low_power || (active_bank == 0))) || (ck_cntr - ck_slow_exit_pd < TAXPD)) begin
if (ck_cntr - ck_slow_exit_pd < TAXPD)
$display ("%m: at time %t WARNING: tAXPD violation during ODT transition. Synchronous or asynchronous change in termination resistance is possible.", $time);
if (odt_in) begin
if (DEBUG) $display ("%m: at time %t INFO: Async On Die Termination = %d", $time + TAONPD, 1'b1);
odt_state <= #(TAONPD) 1'b1;
end else begin
if (DEBUG) $display ("%m: at time %t INFO: Async On Die Termination = %d", $time + TAOFPD, 1'b0);
odt_state <= #(TAOFPD) 1'b0;
end
// sync ODT mode applies:
// 1.) during normal operation
// 2.) during active power down with fast exit
end else begin
if (odt_in) begin
i = TAOND*2;
odt_pipeline[i] = 1'b1;
end else begin
i = TAOFD*2;
odt_pipeline[i] = 1'b1;
end
end
ck_odt <= ck_cntr;
end
end
if (odt_pipeline[0]) begin
odt_state = ~odt_state;
if (DEBUG) $display ("%m: at time %t INFO: Sync On Die Termination = %d", $time, odt_state);
end
end
 
// shift pipelines
if (|wr_pipeline || |rd_pipeline || |al_pipeline) begin
al_pipeline = al_pipeline>>1;
wr_pipeline = wr_pipeline>>1;
rd_pipeline = rd_pipeline>>1;
for (i=0; i<`MAX_PIPE; i=i+1) begin
ba_pipeline[i] = ba_pipeline[i+1];
row_pipeline[i] = row_pipeline[i+1];
col_pipeline[i] = col_pipeline[i+1];
end
end
if (|odt_pipeline) begin
odt_pipeline = odt_pipeline>>1;
end
end
 
// receiver(s)
task dqs_even_receiver;
input [4:0] i;
reg [71:0] bit_mask;
begin
bit_mask = {`DQ_PER_DQS{1'b1}}<<(i*`DQ_PER_DQS);
if (dqs_even[i]) begin
if (rdqs_en) begin // rdqs disables dm
dm_in_pos[i] = 1'b0;
end else begin
dm_in_pos[i] = dm_in[i];
end
dq_in_pos = (dq_in & bit_mask) | (dq_in_pos & ~bit_mask);
end
end
endtask
 
always @(posedge dqs_even[ 0]) dqs_even_receiver( 0);
always @(posedge dqs_even[ 1]) dqs_even_receiver( 1);
always @(posedge dqs_even[ 2]) dqs_even_receiver( 2);
always @(posedge dqs_even[ 3]) dqs_even_receiver( 3);
always @(posedge dqs_even[ 4]) dqs_even_receiver( 4);
always @(posedge dqs_even[ 5]) dqs_even_receiver( 5);
always @(posedge dqs_even[ 6]) dqs_even_receiver( 6);
always @(posedge dqs_even[ 7]) dqs_even_receiver( 7);
always @(posedge dqs_even[ 8]) dqs_even_receiver( 8);
always @(posedge dqs_even[ 9]) dqs_even_receiver( 9);
always @(posedge dqs_even[10]) dqs_even_receiver(10);
always @(posedge dqs_even[11]) dqs_even_receiver(11);
always @(posedge dqs_even[12]) dqs_even_receiver(12);
always @(posedge dqs_even[13]) dqs_even_receiver(13);
always @(posedge dqs_even[14]) dqs_even_receiver(14);
always @(posedge dqs_even[15]) dqs_even_receiver(15);
always @(posedge dqs_even[16]) dqs_even_receiver(16);
always @(posedge dqs_even[17]) dqs_even_receiver(17);
 
task dqs_odd_receiver;
input [4:0] i;
reg [71:0] bit_mask;
begin
bit_mask = {`DQ_PER_DQS{1'b1}}<<(i*`DQ_PER_DQS);
if (dqs_odd[i]) begin
if (rdqs_en) begin // rdqs disables dm
dm_in_neg[i] = 1'b0;
end else begin
dm_in_neg[i] = dm_in[i];
end
dq_in_neg = (dq_in & bit_mask) | (dq_in_neg & ~bit_mask);
end
end
endtask
 
always @(posedge dqs_odd[ 0]) dqs_odd_receiver( 0);
always @(posedge dqs_odd[ 1]) dqs_odd_receiver( 1);
always @(posedge dqs_odd[ 2]) dqs_odd_receiver( 2);
always @(posedge dqs_odd[ 3]) dqs_odd_receiver( 3);
always @(posedge dqs_odd[ 4]) dqs_odd_receiver( 4);
always @(posedge dqs_odd[ 5]) dqs_odd_receiver( 5);
always @(posedge dqs_odd[ 6]) dqs_odd_receiver( 6);
always @(posedge dqs_odd[ 7]) dqs_odd_receiver( 7);
always @(posedge dqs_odd[ 8]) dqs_odd_receiver( 8);
always @(posedge dqs_odd[ 9]) dqs_odd_receiver( 9);
always @(posedge dqs_odd[10]) dqs_odd_receiver(10);
always @(posedge dqs_odd[11]) dqs_odd_receiver(11);
always @(posedge dqs_odd[12]) dqs_odd_receiver(12);
always @(posedge dqs_odd[13]) dqs_odd_receiver(13);
always @(posedge dqs_odd[14]) dqs_odd_receiver(14);
always @(posedge dqs_odd[15]) dqs_odd_receiver(15);
always @(posedge dqs_odd[16]) dqs_odd_receiver(16);
always @(posedge dqs_odd[17]) dqs_odd_receiver(17);
// Processes to check hold and pulse width of control signals
always @(cke_in) begin
if ($time > TIH) begin
if ($time - tm_ck_pos < TIH)
$display ("%m: at time %t ERROR: tIH violation on CKE by %t", $time, tm_ck_pos + TIH - $time);
end
if (dll_locked && ($time - tm_cke < $rtoi(TIPW*tck_avg)))
$display ("%m: at time %t ERROR: tIPW violation on CKE by %t", $time, tm_cke + TIPW*tck_avg - $time);
tm_cke = $time;
end
always @(odt_in) begin
if (odt_en && !in_self_refresh) begin
if ($time - tm_ck_pos < TIH)
$display ("%m: at time %t ERROR: tIH violation on ODT by %t", $time, tm_ck_pos + TIH - $time);
if (dll_locked && ($time - tm_odt < $rtoi(TIPW*tck_avg)))
$display ("%m: at time %t ERROR: tIPW violation on ODT by %t", $time, tm_odt + TIPW*tck_avg - $time);
end
tm_odt = $time;
end
 
task cmd_addr_timing_check;
input i;
reg [4:0] i;
begin
if (prev_cke) begin
if ($time - tm_ck_pos < TIH)
$display ("%m: at time %t ERROR: tIH violation on %s by %t", $time, cmd_addr_string[i], tm_ck_pos + TIH - $time);
if (dll_locked && ($time - tm_cmd_addr[i] < $rtoi(TIPW*tck_avg)))
$display ("%m: at time %t ERROR: tIPW violation on %s by %t", $time, cmd_addr_string[i], tm_cmd_addr[i] + TIPW*tck_avg - $time);
end
tm_cmd_addr[i] = $time;
end
endtask
 
always @(cs_n_in ) cmd_addr_timing_check( 0);
always @(ras_n_in ) cmd_addr_timing_check( 1);
always @(cas_n_in ) cmd_addr_timing_check( 2);
always @(we_n_in ) cmd_addr_timing_check( 3);
always @(ba_in [ 0]) cmd_addr_timing_check( 4);
always @(ba_in [ 1]) cmd_addr_timing_check( 5);
always @(ba_in [ 2]) cmd_addr_timing_check( 6);
always @(addr_in[ 0]) cmd_addr_timing_check( 7);
always @(addr_in[ 1]) cmd_addr_timing_check( 8);
always @(addr_in[ 2]) cmd_addr_timing_check( 9);
always @(addr_in[ 3]) cmd_addr_timing_check(10);
always @(addr_in[ 4]) cmd_addr_timing_check(11);
always @(addr_in[ 5]) cmd_addr_timing_check(12);
always @(addr_in[ 6]) cmd_addr_timing_check(13);
always @(addr_in[ 7]) cmd_addr_timing_check(14);
always @(addr_in[ 8]) cmd_addr_timing_check(15);
always @(addr_in[ 9]) cmd_addr_timing_check(16);
always @(addr_in[10]) cmd_addr_timing_check(17);
always @(addr_in[11]) cmd_addr_timing_check(18);
always @(addr_in[12]) cmd_addr_timing_check(19);
always @(addr_in[13]) cmd_addr_timing_check(20);
always @(addr_in[14]) cmd_addr_timing_check(21);
always @(addr_in[15]) cmd_addr_timing_check(22);
 
// Processes to check setup and hold of data signals
task dm_timing_check;
input i;
reg [4:0] i;
begin
if (dqs_in_valid) begin
if ($time - tm_dqs[i] < TDH)
$display ("%m: at time %t ERROR: tDH violation on DM bit %d by %t", $time, i, tm_dqs[i] + TDH - $time);
if (check_dm_tdipw[i]) begin
if (dll_locked && ($time - tm_dm[i] < $rtoi(TDIPW*tck_avg)))
$display ("%m: at time %t ERROR: tDIPW violation on DM bit %d by %t", $time, i, tm_dm[i] + TDIPW*tck_avg - $time);
end
end
check_dm_tdipw[i] <= 1'b0;
tm_dm[i] = $time;
end
endtask
 
always @(dm_in[ 0]) dm_timing_check( 0);
always @(dm_in[ 1]) dm_timing_check( 1);
always @(dm_in[ 2]) dm_timing_check( 2);
always @(dm_in[ 3]) dm_timing_check( 3);
always @(dm_in[ 4]) dm_timing_check( 4);
always @(dm_in[ 5]) dm_timing_check( 5);
always @(dm_in[ 6]) dm_timing_check( 6);
always @(dm_in[ 7]) dm_timing_check( 7);
always @(dm_in[ 8]) dm_timing_check( 8);
always @(dm_in[ 9]) dm_timing_check( 9);
always @(dm_in[10]) dm_timing_check(10);
always @(dm_in[11]) dm_timing_check(11);
always @(dm_in[12]) dm_timing_check(12);
always @(dm_in[13]) dm_timing_check(13);
always @(dm_in[14]) dm_timing_check(14);
always @(dm_in[15]) dm_timing_check(15);
always @(dm_in[16]) dm_timing_check(16);
always @(dm_in[17]) dm_timing_check(17);
 
task dq_timing_check;
input i;
reg [6:0] i;
begin
if (dqs_in_valid) begin
if ($time - tm_dqs[i/`DQ_PER_DQS] < TDH)
$display ("%m: at time %t ERROR: tDH violation on DQ bit %d by %t", $time, i, tm_dqs[i/`DQ_PER_DQS] + TDH - $time);
if (check_dq_tdipw[i]) begin
if (dll_locked && ($time - tm_dq[i] < $rtoi(TDIPW*tck_avg)))
$display ("%m: at time %t ERROR: tDIPW violation on DQ bit %d by %t", $time, i, tm_dq[i] + TDIPW*tck_avg - $time);
end
end
check_dq_tdipw[i] <= 1'b0;
tm_dq[i] = $time;
end
endtask
 
always @(dq_in[ 0]) dq_timing_check( 0);
always @(dq_in[ 1]) dq_timing_check( 1);
always @(dq_in[ 2]) dq_timing_check( 2);
always @(dq_in[ 3]) dq_timing_check( 3);
always @(dq_in[ 4]) dq_timing_check( 4);
always @(dq_in[ 5]) dq_timing_check( 5);
always @(dq_in[ 6]) dq_timing_check( 6);
always @(dq_in[ 7]) dq_timing_check( 7);
always @(dq_in[ 8]) dq_timing_check( 8);
always @(dq_in[ 9]) dq_timing_check( 9);
always @(dq_in[10]) dq_timing_check(10);
always @(dq_in[11]) dq_timing_check(11);
always @(dq_in[12]) dq_timing_check(12);
always @(dq_in[13]) dq_timing_check(13);
always @(dq_in[14]) dq_timing_check(14);
always @(dq_in[15]) dq_timing_check(15);
always @(dq_in[16]) dq_timing_check(16);
always @(dq_in[17]) dq_timing_check(17);
always @(dq_in[18]) dq_timing_check(18);
always @(dq_in[19]) dq_timing_check(19);
always @(dq_in[20]) dq_timing_check(20);
always @(dq_in[21]) dq_timing_check(21);
always @(dq_in[22]) dq_timing_check(22);
always @(dq_in[23]) dq_timing_check(23);
always @(dq_in[24]) dq_timing_check(24);
always @(dq_in[25]) dq_timing_check(25);
always @(dq_in[26]) dq_timing_check(26);
always @(dq_in[27]) dq_timing_check(27);
always @(dq_in[28]) dq_timing_check(28);
always @(dq_in[29]) dq_timing_check(29);
always @(dq_in[30]) dq_timing_check(30);
always @(dq_in[31]) dq_timing_check(31);
always @(dq_in[32]) dq_timing_check(32);
always @(dq_in[33]) dq_timing_check(33);
always @(dq_in[34]) dq_timing_check(34);
always @(dq_in[35]) dq_timing_check(35);
always @(dq_in[36]) dq_timing_check(36);
always @(dq_in[37]) dq_timing_check(37);
always @(dq_in[38]) dq_timing_check(38);
always @(dq_in[39]) dq_timing_check(39);
always @(dq_in[40]) dq_timing_check(40);
always @(dq_in[41]) dq_timing_check(41);
always @(dq_in[42]) dq_timing_check(42);
always @(dq_in[43]) dq_timing_check(43);
always @(dq_in[44]) dq_timing_check(44);
always @(dq_in[45]) dq_timing_check(45);
always @(dq_in[46]) dq_timing_check(46);
always @(dq_in[47]) dq_timing_check(47);
always @(dq_in[48]) dq_timing_check(48);
always @(dq_in[49]) dq_timing_check(49);
always @(dq_in[50]) dq_timing_check(50);
always @(dq_in[51]) dq_timing_check(51);
always @(dq_in[52]) dq_timing_check(52);
always @(dq_in[53]) dq_timing_check(53);
always @(dq_in[54]) dq_timing_check(54);
always @(dq_in[55]) dq_timing_check(55);
always @(dq_in[56]) dq_timing_check(56);
always @(dq_in[57]) dq_timing_check(57);
always @(dq_in[58]) dq_timing_check(58);
always @(dq_in[59]) dq_timing_check(59);
always @(dq_in[60]) dq_timing_check(60);
always @(dq_in[61]) dq_timing_check(61);
always @(dq_in[62]) dq_timing_check(62);
always @(dq_in[63]) dq_timing_check(63);
always @(dq_in[64]) dq_timing_check(64);
always @(dq_in[65]) dq_timing_check(65);
always @(dq_in[66]) dq_timing_check(66);
always @(dq_in[67]) dq_timing_check(67);
always @(dq_in[68]) dq_timing_check(68);
always @(dq_in[69]) dq_timing_check(69);
always @(dq_in[70]) dq_timing_check(70);
always @(dq_in[71]) dq_timing_check(71);
 
task dqs_pos_timing_check;
input i;
reg [5:0] i;
reg [3:0] j;
begin
if (dqs_in_valid && ((wdqs_pos_cntr[i] < burst_length/2) || b2b_write) && (dqs_n_en || i<18)) begin
if (dqs_in[i] ^ prev_dqs_in[i]) begin
if (dll_locked) begin
if (check_write_preamble[i]) begin
if ($time - tm_dqs_neg[i] < $rtoi(TWPRE*tck_avg))
$display ("%m: at time %t ERROR: tWPRE violation on &s bit %d", $time, dqs_string[i/18], i%18);
end else if (check_write_postamble[i]) begin
if ($time - tm_dqs_neg[i] < $rtoi(TWPST*tck_avg))
$display ("%m: at time %t ERROR: tWPST violation on %s bit %d", $time, dqs_string[i/18], i%18);
end else begin
if ($time - tm_dqs_neg[i] < $rtoi(TDQSL*tck_avg))
$display ("%m: at time %t ERROR: tDQSL violation on %s bit %d", $time, dqs_string[i/18], i%18);
end
end
if ($time - tm_dm[i%18] < TDS)
$display ("%m: at time %t ERROR: tDS violation on DM bit %d by %t", $time, i, tm_dm[i%18] + TDS - $time);
if (!dq_out_en) begin
for (j=0; j<`DQ_PER_DQS; j=j+1) begin
if ($time - tm_dq[i*`DQ_PER_DQS+j] < TDS)
$display ("%m: at time %t ERROR: tDS violation on DQ bit %d by %t", $time, i*`DQ_PER_DQS+j, tm_dq[i*`DQ_PER_DQS+j] + TDS - $time);
check_dq_tdipw[i*`DQ_PER_DQS+j] <= 1'b1;
end
end
if ((wdqs_pos_cntr[i] < burst_length/2) && !b2b_write) begin
wdqs_pos_cntr[i] <= wdqs_pos_cntr[i] + 1;
end else begin
wdqs_pos_cntr[i] <= 1;
end
check_dm_tdipw[i%18] <= 1'b1;
check_write_preamble[i] <= 1'b0;
check_write_postamble[i] <= 1'b0;
check_write_dqs_low[i] <= 1'b0;
tm_dqs[i%18] <= $time;
end else begin
$display ("%m: at time %t ERROR: Invalid latching edge on %s bit %d", $time, dqs_string[i/18], i%18);
end
end
tm_dqss_pos[i] <= $time;
tm_dqs_pos[i] = $time;
prev_dqs_in[i] <= dqs_in[i];
end
endtask
 
always @(posedge dqs_in[ 0]) dqs_pos_timing_check( 0);
always @(posedge dqs_in[ 1]) dqs_pos_timing_check( 1);
always @(posedge dqs_in[ 2]) dqs_pos_timing_check( 2);
always @(posedge dqs_in[ 3]) dqs_pos_timing_check( 3);
always @(posedge dqs_in[ 4]) dqs_pos_timing_check( 4);
always @(posedge dqs_in[ 5]) dqs_pos_timing_check( 5);
always @(posedge dqs_in[ 6]) dqs_pos_timing_check( 6);
always @(posedge dqs_in[ 7]) dqs_pos_timing_check( 7);
always @(posedge dqs_in[ 8]) dqs_pos_timing_check( 8);
always @(posedge dqs_in[ 9]) dqs_pos_timing_check( 9);
always @(posedge dqs_in[10]) dqs_pos_timing_check(10);
always @(posedge dqs_in[11]) dqs_pos_timing_check(11);
always @(posedge dqs_in[12]) dqs_pos_timing_check(12);
always @(posedge dqs_in[13]) dqs_pos_timing_check(13);
always @(posedge dqs_in[14]) dqs_pos_timing_check(14);
always @(posedge dqs_in[15]) dqs_pos_timing_check(15);
always @(posedge dqs_in[16]) dqs_pos_timing_check(16);
always @(posedge dqs_in[17]) dqs_pos_timing_check(17);
always @(negedge dqs_in[18]) dqs_pos_timing_check(18);
always @(negedge dqs_in[19]) dqs_pos_timing_check(19);
always @(negedge dqs_in[20]) dqs_pos_timing_check(20);
always @(negedge dqs_in[21]) dqs_pos_timing_check(21);
always @(negedge dqs_in[22]) dqs_pos_timing_check(22);
always @(negedge dqs_in[23]) dqs_pos_timing_check(23);
always @(negedge dqs_in[24]) dqs_pos_timing_check(24);
always @(negedge dqs_in[25]) dqs_pos_timing_check(25);
always @(negedge dqs_in[26]) dqs_pos_timing_check(26);
always @(negedge dqs_in[27]) dqs_pos_timing_check(27);
always @(negedge dqs_in[28]) dqs_pos_timing_check(28);
always @(negedge dqs_in[29]) dqs_pos_timing_check(29);
always @(negedge dqs_in[30]) dqs_pos_timing_check(30);
always @(negedge dqs_in[31]) dqs_pos_timing_check(31);
always @(negedge dqs_in[32]) dqs_neg_timing_check(32);
always @(negedge dqs_in[33]) dqs_neg_timing_check(33);
always @(negedge dqs_in[34]) dqs_neg_timing_check(34);
always @(negedge dqs_in[35]) dqs_neg_timing_check(35);
 
task dqs_neg_timing_check;
input i;
reg [5:0] i;
reg [3:0] j;
begin
if (dqs_in_valid && (wdqs_pos_cntr[i] > 0) && check_write_dqs_high[i] && (dqs_n_en || i < 18)) begin
if (dqs_in[i] ^ prev_dqs_in[i]) begin
if (dll_locked) begin
if ($time - tm_dqs_pos[i] < $rtoi(TDQSH*tck_avg))
$display ("%m: at time %t ERROR: tDQSH violation on %s bit %d", $time, dqs_string[i/18], i%18);
if ($time - tm_ck_pos < $rtoi(TDSH*tck_avg))
$display ("%m: at time %t ERROR: tDSH violation on %s bit %d", $time, dqs_string[i/18], i%18);
end
if ($time - tm_dm[i%18] < TDS)
$display ("%m: at time %t ERROR: tDS violation on DM bit %d by %t", $time, i, tm_dm[i%18] + TDS - $time);
if (!dq_out_en) begin
for (j=0; j<`DQ_PER_DQS; j=j+1) begin
if ($time - tm_dq[i*`DQ_PER_DQS+j] < TDS)
$display ("%m: at time %t ERROR: tDS violation on DQ bit %d by %t", $time, i*`DQ_PER_DQS+j, tm_dq[i*`DQ_PER_DQS+j] + TDS - $time);
check_dq_tdipw[i*`DQ_PER_DQS+j] <= 1'b1;
end
end
check_dm_tdipw[i%18] <= 1'b1;
check_write_dqs_high[i] <= 1'b0;
tm_dqs[i%18] <= $time;
end else begin
$display ("%m: at time %t ERROR: Invalid latching edge on %s bit %d", $time, dqs_string[i/18], i%18);
end
end
tm_dqs_neg[i] = $time;
prev_dqs_in[i] <= dqs_in[i];
end
endtask
 
always @(negedge dqs_in[ 0]) dqs_neg_timing_check( 0);
always @(negedge dqs_in[ 1]) dqs_neg_timing_check( 1);
always @(negedge dqs_in[ 2]) dqs_neg_timing_check( 2);
always @(negedge dqs_in[ 3]) dqs_neg_timing_check( 3);
always @(negedge dqs_in[ 4]) dqs_neg_timing_check( 4);
always @(negedge dqs_in[ 5]) dqs_neg_timing_check( 5);
always @(negedge dqs_in[ 6]) dqs_neg_timing_check( 6);
always @(negedge dqs_in[ 7]) dqs_neg_timing_check( 7);
always @(negedge dqs_in[ 8]) dqs_neg_timing_check( 8);
always @(negedge dqs_in[ 9]) dqs_neg_timing_check( 9);
always @(negedge dqs_in[10]) dqs_neg_timing_check(10);
always @(negedge dqs_in[11]) dqs_neg_timing_check(11);
always @(negedge dqs_in[12]) dqs_neg_timing_check(12);
always @(negedge dqs_in[13]) dqs_neg_timing_check(13);
always @(negedge dqs_in[14]) dqs_neg_timing_check(14);
always @(negedge dqs_in[15]) dqs_neg_timing_check(15);
always @(negedge dqs_in[16]) dqs_neg_timing_check(16);
always @(negedge dqs_in[17]) dqs_neg_timing_check(17);
always @(posedge dqs_in[18]) dqs_neg_timing_check(18);
always @(posedge dqs_in[19]) dqs_neg_timing_check(19);
always @(posedge dqs_in[20]) dqs_neg_timing_check(20);
always @(posedge dqs_in[21]) dqs_neg_timing_check(21);
always @(posedge dqs_in[22]) dqs_neg_timing_check(22);
always @(posedge dqs_in[23]) dqs_neg_timing_check(23);
always @(posedge dqs_in[24]) dqs_neg_timing_check(24);
always @(posedge dqs_in[25]) dqs_neg_timing_check(25);
always @(posedge dqs_in[26]) dqs_neg_timing_check(26);
always @(posedge dqs_in[27]) dqs_neg_timing_check(27);
always @(posedge dqs_in[28]) dqs_neg_timing_check(28);
always @(posedge dqs_in[29]) dqs_neg_timing_check(29);
always @(posedge dqs_in[30]) dqs_neg_timing_check(30);
always @(posedge dqs_in[31]) dqs_neg_timing_check(31);
always @(posedge dqs_in[32]) dqs_neg_timing_check(32);
always @(posedge dqs_in[33]) dqs_neg_timing_check(33);
always @(posedge dqs_in[34]) dqs_neg_timing_check(34);
always @(posedge dqs_in[35]) dqs_neg_timing_check(35);
 
endmodule
/openrisc/trunk/orpsocv2/bench/verilog/cy7c1354.v
0,0 → 1,482
//************************************************************************
//************************************************************************
//** This model is the property of Cypress Semiconductor Corp and is **
//** protected by the US copyright laws, any unauthorized copying and **
//** distribution is prohibited. Cypress reserves the right to change **
//** any of the functional specifications without any prior notice. **
//** Cypress is not liable for any damages which may result from the **
//** use of this functional model. **
//** **
//** File Name : CY7C1354B **
//** **
//** Revision : 1.1 - 01/30/2004 **
//** **
//** The timings are to be selected by the user depending upon the **
//** frequency of operation from the datasheet. **
//** **
//** Model : CY7C1354B - 256K x 36 NoBL Pipelined SRAM **
//** Queries : MPD Applications **
//** e-mail: mpd_apps@cypress.com **
//************************************************************************
//************************************************************************
 
`timescale 1ns / 10ps
 
// NOTE : Any setup/hold errors will force input signal to x state
// or if results indeterminant (write addr) core is reset x
 
// define fixed values
 
`define wordsize (36 -1) //
`define no_words (262144 -1) // 256K x 36 RAM
 
module cy7c1354 ( d, clk, a, bws, we_b, adv_lb, ce1b, ce2, ce3b, oeb, cenb, mode);
 
inout [`wordsize:0] d;
input clk, // clock input (R)
we_b, // byte write enable(L)
adv_lb, // burst(H)/load(L) address
ce1b, // chip enable(L)
ce2, // chip enable(H)
ce3b, // chip enable(L)
oeb, // async output enable(L)(read)
cenb, // clock enable(L)
mode; // interleave(H)/linear(L) burst
input [3:0] bws; // byte write select(L)
input [18:0] a; // address bus
 
// *** NOTE DEVICE OPERATES #0.01 AFTER CLOCK ***
// *** THEREFORE DELAYS HAVE TO TAKE THIS INTO ACCOUNT ***
 
//**********************************************************************
// This model is configured for 166 MHz Operation (CY7C1354-166).
//**********************************************************************
`define teohz #3.5
`define teolz #0
`define tchz #3.5
`define tclz #1.5
`define tco #3.5
`define tdoh #1.5
 
`define tas 1.5
`define tah 0.5
 
/**********************************************************************
// Timings for 225MHz
//**********************************************************************
`define teohz #2.8
`define teolz #0
`define tchz #2.8
`define tclz #1.5
`define tco #2.8
`define tdoh #1.5
 
`define tas 1.5
`define tah 0.5
 
//***********************************************************************
// Timings for 200MHz
//**********************************************************************
`define teohz #3.2
`define teolz #0
`define tchz #3.2
`define tclz #1.5
`define tco #3.2
`define tdoh #1.5
 
`define tas 1.5
`define tah 0.5
***********************************************************************/
 
reg notifier; // error support reg's
reg noti1_0;
reg noti1_1;
reg noti1_2;
reg noti1_3;
reg noti1_4;
reg noti1_5;
reg noti1_6;
reg noti2;
 
 
wire chipen; // combined chip enable (high for an active chip)
 
reg chipen_d; // _d = delayed
reg chipen_o; // _o = operational = delayed sig or _d sig
 
wire writestate; // holds 1 if any of writebus is low
reg writestate_d;
reg writestate_o;
 
wire loadcyc; // holds 1 for load cycles (setup and hold checks)
wire writecyc; // holds 1 for write cycles (setup and hold checks)
wire [3:0] bws; // holds the bws values
 
wire [3:0] writebusb; // holds the "internal" bws bus based on we_b
reg [3:0] writebusb_d;
reg [3:0] writebusb_o;
 
wire [2:0] operation; // holds chipen, adv_ld and writestate
reg [2:0] operation_d;
reg [2:0] operation_o;
 
wire [17:0] a; // address input bus
reg [17:0] a_d;
reg [17:0] a_o;
 
reg [`wordsize:0] do; // data output reg
reg [`wordsize:0] di; // data input bus
reg [`wordsize:0] dd; // data delayed bus
 
wire tristate; // tristate output (on a bytewise basis) when asserted
reg cetri; // register set by chip disable which sets the tristate
reg oetri; // register set by oe which sets the tristate
reg enable; // register to make the ram enabled when equal to 1
reg [17:0] addreg; // register to hold the input address
reg [`wordsize:0] pipereg; // register for the output data
 
reg [`wordsize:0] mem [0:`no_words]; // RAM array
 
reg [`wordsize:0] writeword; // temporary holding register for the write data
reg burstinit; // register to hold a[0] for burst type
reg [18:0] i; // temporary register used to write to all mem locs.
reg writetri; // tristate
reg lw, bw; // pipelined write functions
reg we_bl;
 
 
wire [`wordsize:0] d = !tristate ? do[`wordsize:0] : 36'bz ; // data bus
 
assign chipen = (adv_lb == 1 ) ? chipen_d :
~ce1b & ce2 & ~ce3b ;
 
assign writestate = ~& writebusb;
 
assign operation = {chipen, adv_lb, writestate};
 
assign writebusb[3:0] = ( we_b ==0 & adv_lb ==0) ? bws[3:0]:
( we_b ==1 & adv_lb ==0) ? 4'b1111 :
( we_bl ==0 & adv_lb ==1) ? bws[3:0]:
( we_bl ==1 & adv_lb ==1) ? 4'b1111 :
4'bxxxx ;
 
assign loadcyc = chipen & !cenb;
 
assign writecyc = writestate_d & enable & ~cenb & chipen; // check
 
assign tristate = cetri | writetri | oetri;
 
pullup (mode);
 
// formers for notices/errors etc
//
//$display("NOTICE : xxx :");
//$display("WARNING : xxx :");
//$display("ERROR *** : xxx :");
 
 
// initialize the output to be tri-state, ram to be disabled
 
initial
begin
// signals
 
writetri = 0;
cetri = 1;
enable = 0;
lw = 0;
bw = 0;
 
// error signals
 
notifier = 0;
noti1_0 = 0;
noti1_1 = 0;
noti1_2 = 0;
noti1_3 = 0;
noti1_4 = 0;
noti1_5 = 0;
noti1_6 = 0;
noti2 = 0;
 
end
 
 
 
// asynchronous OE
 
always @(oeb)
begin
if (oeb == 1)
oetri <= `teohz 1;
else
oetri <= `teolz 0;
end
 
// *** SETUP / HOLD VIOLATIONS ***
 
always @(noti2)
begin
$display("NOTICE : 020 : Data bus corruption");
force d =36'bx;
#1;
release d;
end
 
always @(noti1_0)
begin
$display("NOTICE : 010 : Byte write corruption");
force bws = 4'bx;
#1;
release bws;
end
 
always @(noti1_1)
begin
$display("NOTICE : 011 : Byte enable corruption");
force we_b = 1'bx;
#1;
release we_b;
end
 
always @(noti1_2)
begin
$display("NOTICE : 012 : CE1B corruption");
force ce1b =1'bx;
#1;
release ce1b;
end
 
always @(noti1_3)
begin
$display("NOTICE : 013 : CE2 corruption");
force ce2 =1'bx;
#1;
release ce2;
end
 
always @(noti1_4)
begin
$display("NOTICE : 014 : CE3B corruption");
force ce3b =1'bx;
#1;
release ce3b;
end
 
always @(noti1_5)
begin
$display("NOTICE : 015 : CENB corruption");
force cenb =1'bx;
#1;
release cenb;
end
 
always @(noti1_6)
begin
$display("NOTICE : 016 : ADV_LB corruption");
force adv_lb = 1'bx;
#1;
release adv_lb;
end
 
// synchronous functions from clk edge
 
always @(posedge clk)
if (!cenb)
begin
#0.01;
// latch conditions on adv_lb
 
if (adv_lb)
we_bl <= we_bl;
else
we_bl <= we_b;
 
chipen_d <= chipen;
 
chipen_o <= chipen;
writestate_o <= writestate;
writestate_d <= writestate_o;
writebusb_o <= writebusb;
writebusb_d <= writebusb_o;
operation_o <= operation;
a_o <= a;
a_d <= a_o;
di = d;
 
// execute previously pipelined fns
 
if (lw) begin
loadwrite;
lw =0;
end
 
if (bw) begin
burstwrite;
bw =0;
end
 
// decode input/piplined state
 
casex (operation_o)
3'b0?? : turnoff;
3'b101 : setlw;
3'b111 : setbw;
3'b100 : loadread;
3'b110 : burstread;
default : unknown; // output unknown values and display an error message
endcase
 
do <= `tco pipereg;
 
end
 
// *** task section ***
 
task read;
begin
if (enable) cetri <= `tclz 0;
do <= `tdoh 36'hx;
writetri <= `tchz 0;
pipereg = mem[addreg];
end
endtask
 
task write;
begin
if (enable) cetri <= `tclz 0;
writeword = mem[addreg]; // set up a word to hold the data for the current location
/* overwrite the current word for the bytes being written to */
if (!writebusb_d[3]) writeword[35:27] = di[35:27];
if (!writebusb_d[2]) writeword[26:18] = di[26:18];
if (!writebusb_d[1]) writeword[17:9] = di[17:9];
if (!writebusb_d[0]) writeword[8:0] = di[8:0];
writeword = writeword & writeword; //convert z to x states
mem[addreg] = writeword; // store the new word into the memory location
//writetri <= `tchz 1; // tristate the outputs
end
endtask
 
task setlw;
begin
lw =1;
writetri <= `tchz 1; // tristate the outputs
end
endtask
 
task setbw;
begin
bw =1;
writetri <= `tchz 1; // tristate the outputs
end
endtask
 
task loadread;
begin
burstinit = a_o[0];
addreg = a_o;
enable = 1;
read;
end
endtask
 
task loadwrite;
begin
burstinit = a_d[0];
addreg = a_d;
enable = 1;
write;
end
endtask
 
task burstread;
begin
burst;
read;
end
endtask
 
task burstwrite;
begin
burst;
write;
end
endtask
 
task unknown;
begin
do = 36'bx;
// $display ("Unknown function: Operation = %b\n", operation);
end
endtask
 
task turnoff;
begin
enable = 0;
cetri <= `tchz 1;
pipereg = 36'h0;
end
endtask
 
task burst;
begin
if (burstinit == 0 || mode == 0)
begin
case (addreg[1:0])
2'b00: addreg[1:0] = 2'b01;
2'b01: addreg[1:0] = 2'b10;
2'b10: addreg[1:0] = 2'b11;
2'b11: addreg[1:0] = 2'b00;
default: addreg[1:0] = 2'bxx;
endcase
end
else
begin
case (addreg[1:0])
2'b00: addreg[1:0] = 2'b11;
2'b01: addreg[1:0] = 2'b00;
2'b10: addreg[1:0] = 2'b01;
2'b11: addreg[1:0] = 2'b10;
default: addreg[1:0] = 2'bxx;
endcase
end
end
endtask
 
// IO checks
 
specify
// specify the setup and hold checks
 
// notifier will wipe memory as result is indeterminent
 
$setuphold(posedge clk &&& loadcyc, a, `tas, `tah, notifier);
 
// noti1 should make ip = 'bx;
 
$setuphold(posedge clk, bws, `tas, `tah, noti1_0);
 
$setuphold(posedge clk, we_b, `tas, `tah, noti1_1);
$setuphold(posedge clk, ce1b, `tas, `tah, noti1_2);
$setuphold(posedge clk, ce2, `tas, `tah, noti1_3);
$setuphold(posedge clk, ce3b, `tas, `tah, noti1_4);
 
// noti2 should make d = 36'hxxxxxxxxx;
 
$setuphold(posedge clk &&& writecyc, d, `tas, `tah, noti2);
//$setuphold(posedge clk &&& WriteTimingCheck , d, `tas, `tah, noti2);
 
// add extra tests here.
 
$setuphold(posedge clk, cenb, `tas, `tah, noti1_5);
$setuphold(posedge clk, adv_lb, `tas, `tah, noti1_6);
 
endspecify
 
endmodule
 
 
/openrisc/trunk/orpsocv2/bench/verilog/or1200_monitor.v
93,15 → 93,19
// Development version of RTL. Libraries are missing.
//
//
 
`include "timescale.v"
`include "or1200_defines.v"
`include "orpsoc_testbench_defines.v"
 
//
// Top of OR1200 inside test bench
//
`define OR1200_TOP orpsoc_testbench.dut.i_or1k.i_or1200_top
 
`ifndef OR1200_TOP
`define OR1200_TOP orpsoc_testbench.dut.i_or1k.i_or1200_top
`include "orpsoc_testbench_defines.v"
`else
`include `TESTBENCH_DEFINES
`endif
//
// Enable display_arch_state task
//
177,20 → 181,30
gpr[29] = `OR1200_TOP.or1200_cpu.or1200_rf.rf_a.xcv_ram32x8d_3.ram32x1d_5.mem[gpr_no];
gpr[30] = `OR1200_TOP.or1200_cpu.or1200_rf.rf_a.xcv_ram32x8d_3.ram32x1d_6.mem[gpr_no];
gpr[31] = `OR1200_TOP.or1200_cpu.or1200_rf.rf_a.xcv_ram32x8d_3.ram32x1d_7.mem[gpr_no];
`else
`ifdef OR1200_XILINX_RAMB4
`else
`ifdef OR1200_XILINX_RAMB4
for(j = 0; j < 16; j = j + 1) begin
gpr[j] = `OR1200_TOP.or1200_cpu.or1200_rf.rf_a.ramb4_s16_0.mem[gpr_no*16+j];
end
for(j = 0; j < 16; j = j + 1) begin
gpr[j+16] = `OR1200_TOP.or1200_cpu.or1200_rf.rf_a.ramb4_s16_1.mem[gpr_no*16+j];
end
`else
`ifdef OR1200_ARTISAN_SDP
for(j = 0; j < 16; j = j + 1) begin
gpr[j+16] = `OR1200_TOP.or1200_cpu.or1200_rf.rf_a.ramb4_s16_1.mem[gpr_no*16+j];
end
`else
gpr = `OR1200_TOP.or1200_cpu.or1200_rf.rf_a.mem[gpr_no];
`ifdef OR1200_ARTISAN_SDP
`else
`ifdef OR1200_XILINX_RAMB16
`ifdef legacy_model
for(j = 0; j < 32; j = j + 1) begin
gpr[j] = `OR1200_TOP.or1200_cpu.or1200_rf.rf_a.ramb16_s36_s36.mem[gpr_no*32+j];
end
`else
gpr = `OR1200_TOP.or1200_cpu.or1200_rf.rf_a.ramb16_s36_s36.mem[gpr_no];
`endif
`else
gpr = `OR1200_TOP.or1200_cpu.or1200_rf.rf_a.mem[gpr_no];
`endif
`endif
`endif
`endif
`endif
`endif
end
/openrisc/trunk/orpsocv2/rtl/verilog/wb_conbus_defines.v
0,0 → 1,12
`define dw 32 // Data bus Width
`define aw 32 // Address bus Width
`define sw `dw / 8 // Number of Select Lines
`define mbusw `aw + `sw + `dw +4 //address width + byte select width + dat width + cyc + we + stb +cab , input from master interface
`define sbusw 3 // ack + err + rty, input from slave interface
`define mselectw 8 // number of masters
`define sselectw 8 // number of slavers
 
 
// Define the following to enable logic to generate the first few instructions at reset
`define OR1200_BOOT_LOGIC
 
/openrisc/trunk/orpsocv2/rtl/verilog/components/spi_ctrl/spi_flash_clgen.v
0,0 → 1,110
//////////////////////////////////////////////////////////////////////
//// ////
//// spi_clgen.v ////
//// ////
//// This file is part of the SPI IP core project ////
//// http://www.opencores.org/projects/spi/ ////
//// ////
//// Author(s): ////
//// - Simon Srot (simons@opencores.org) ////
//// ////
//// All additional information is avaliable in the Readme.txt ////
//// file. ////
//// ////
//////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 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 ////
//// ////
//////////////////////////////////////////////////////////////////////
 
`include "spi_defines.v"
`include "timescale.v"
 
module spi_flash_clgen (clk_in, rst, go, enable, last_clk, clk_out, pos_edge, neg_edge);
parameter divider_len = 2;
parameter divider = 1;
parameter Tp = 1;
input clk_in; // input clock (system clock)
input rst; // reset
input enable; // clock enable
input go; // start transfer
input last_clk; // last clock
//input [spi_divider_len-1:0] divider; // clock divider (output clock is divided by this value)
output clk_out; // output clock
output pos_edge; // pulse marking positive edge of clk_out
output neg_edge; // pulse marking negative edge of clk_out
reg clk_out;
reg pos_edge;
reg neg_edge;
reg [divider_len-1:0] cnt; // clock counter
wire cnt_zero; // conter is equal to zero
wire cnt_one; // conter is equal to one
assign cnt_zero = cnt == {divider_len{1'b0}};
assign cnt_one = cnt == {{divider_len-1{1'b0}}, 1'b1};
// Counter counts half period
always @(posedge clk_in or posedge rst)
begin
if(rst)
cnt <= #Tp {divider_len{1'b1}};
else
begin
if(!enable || cnt_zero)
cnt <= #Tp divider;
else
cnt <= #Tp cnt - {{divider_len-1{1'b0}}, 1'b1};
end
end
// clk_out is asserted every other half period
always @(posedge clk_in or posedge rst)
begin
if(rst)
clk_out <= #Tp 1'b0;
else
clk_out <= #Tp (enable && cnt_zero && (!last_clk || clk_out)) ? ~clk_out : clk_out;
end
// Pos and neg edge signals
always @(posedge clk_in or posedge rst)
begin
if(rst)
begin
pos_edge <= #Tp 1'b0;
neg_edge <= #Tp 1'b0;
end
else
begin
pos_edge <= #Tp (enable && !clk_out && cnt_one) || (!(|divider) && clk_out) || (!(|divider) && go && !enable);
neg_edge <= #Tp (enable && clk_out && cnt_one) || (!(|divider) && !clk_out && enable);
end
end
endmodule
/openrisc/trunk/orpsocv2/rtl/verilog/components/spi_ctrl/spi_flash_shift.v
0,0 → 1,149
//////////////////////////////////////////////////////////////////////
//// ////
//// spi_shift.v ////
//// ////
//// This file is part of the SPI IP core project ////
//// http://www.opencores.org/projects/spi/ ////
//// ////
//// Author(s): ////
//// - Simon Srot (simons@opencores.org) ////
//// ////
//// All additional information is avaliable in the Readme.txt ////
//// file. ////
//// ////
//////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 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 ////
//// ////
//////////////////////////////////////////////////////////////////////
 
`include "spi_defines.v"
`include "timescale.v"
 
module spi_flash_shift
(
clk, rst, latch, byte_sel, len, go,
pos_edge, neg_edge,
lsb, rx_negedge, tx_negedge,
tip, last,
p_in, p_out, s_clk, s_in, s_out);
parameter Tp = 1;
input clk; // system clock
input rst; // reset
input latch; // latch signal for storing the data in shift register
input [3:0] byte_sel; // byte select signals for storing the data in shift register
input [`SPI_CHAR_LEN_BITS-1:0] len; // data len in bits (minus one)
input lsb; // lbs first on the line
input tx_negedge;
input rx_negedge;
input go; // start stansfer
input pos_edge; // recognize posedge of sclk
input neg_edge; // recognize negedge of sclk
output tip; // transfer in progress
output last; // last bit
input [31:0] p_in; // parallel in
output [`SPI_MAX_CHAR-1:0] p_out; // parallel out
input s_clk; // serial clock
input s_in; // serial in
output s_out; // serial out
reg s_out;
reg tip;
reg [`SPI_CHAR_LEN_BITS:0] cnt; // data bit count
reg [`SPI_MAX_CHAR-1:0] data; // shift register
wire [`SPI_CHAR_LEN_BITS:0] tx_bit_pos; // next bit position
wire [`SPI_CHAR_LEN_BITS:0] rx_bit_pos; // next bit position
wire rx_clk; // rx clock enable
wire tx_clk; // tx clock enable
 
assign p_out = data;
assign tx_bit_pos = lsb ? {!(|len), len} - cnt : cnt - {{`SPI_CHAR_LEN_BITS{1'b0}},1'b1};
assign rx_bit_pos = lsb ? {!(|len), len} - (rx_negedge ? cnt + {{`SPI_CHAR_LEN_BITS{1'b0}},1'b1} : cnt) : (rx_negedge ? cnt : cnt - {{`SPI_CHAR_LEN_BITS{1'b0}},1'b1});
assign last = !(|cnt);
 
assign rx_clk = (rx_negedge ? neg_edge : pos_edge) && (!last || s_clk);
 
assign tx_clk = (tx_negedge ? neg_edge : pos_edge) && !last;
// Character bit counter
always @(posedge clk or posedge rst)
begin
if(rst)
cnt <= #Tp {`SPI_CHAR_LEN_BITS+1{1'b0}};
else
begin
if(tip)
cnt <= #Tp pos_edge ? (cnt - {{`SPI_CHAR_LEN_BITS{1'b0}}, 1'b1}) : cnt;
else
cnt <= #Tp !(|len) ? {1'b1, {`SPI_CHAR_LEN_BITS{1'b0}}} : {1'b0, len};
end
end
// Transfer in progress
always @(posedge clk or posedge rst)
begin
if(rst)
tip <= #Tp 1'b0;
else if(go && ~tip)
tip <= #Tp 1'b1;
else if(tip && last && pos_edge)
tip <= #Tp 1'b0;
end
// Sending bits to the line
always @(posedge clk or posedge rst)
begin
if (rst)
s_out <= #Tp 1'b0;
else
s_out <= #Tp (tx_clk || !tip) ? data[tx_bit_pos[`SPI_CHAR_LEN_BITS-1:0]] : s_out;
end
// Receiving bits from the line
always @(posedge clk or posedge rst)
if (rst)
data <= #Tp `SPI_CHAR_RST;
else
if (latch & !tip)
begin
if (byte_sel[0])
data[7:0] <= #Tp p_in[7:0];
if (byte_sel[1])
data[15:8] <= #Tp p_in[15:8];
if (byte_sel[2])
data[23:16] <= #Tp p_in[23:16];
if (byte_sel[3])
data[31:24] <= #Tp p_in[31:24];
end
else
data[rx_bit_pos[`SPI_CHAR_LEN_BITS-1:0]] <= #Tp rx_clk ? s_in : data[rx_bit_pos[`SPI_CHAR_LEN_BITS-1:0]];
endmodule
 
/openrisc/trunk/orpsocv2/rtl/verilog/components/spi_ctrl/spi_defines.v
0,0 → 1,139
//////////////////////////////////////////////////////////////////////
//// ////
//// spi_define.v ////
//// ////
//// This file is part of the SPI IP core project ////
//// http://www.opencores.org/projects/spi/ ////
//// ////
//// Author(s): ////
//// - Simon Srot (simons@opencores.org) ////
//// ////
//// All additional information is avaliable in the Readme.txt ////
//// file. ////
//// ////
//////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 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 ////
//// ////
//////////////////////////////////////////////////////////////////////
 
//
// Number of bits used for devider register. If used in system with
// low frequency of system clock this can be reduced.
// Use SPI_DIVIDER_LEN for fine tuning theexact number.
//
`define SPI_DIVIDER_LEN_8
//`define SPI_DIVIDER_LEN_16
//`define SPI_DIVIDER_LEN_24
//`define SPI_DIVIDER_LEN_32
 
`ifdef SPI_DIVIDER_LEN_8
`define SPI_DIVIDER_LEN 4 // Can be set from 1 to 8
`endif
`ifdef SPI_DIVIDER_LEN_16
`define SPI_DIVIDER_LEN 16 // Can be set from 9 to 16
`endif
`ifdef SPI_DIVIDER_LEN_24
`define SPI_DIVIDER_LEN 24 // Can be set from 17 to 24
`endif
`ifdef SPI_DIVIDER_LEN_32
`define SPI_DIVIDER_LEN 32 // Can be set from 25 to 32
`endif
 
//
// Maximum nuber of bits that can be send/received at once.
// Use SPI_MAX_CHAR for fine tuning the exact number, when using
// SPI_MAX_CHAR_32, SPI_MAX_CHAR_24, SPI_MAX_CHAR_16, SPI_MAX_CHAR_8.
//
//`define SPI_MAX_CHAR_128
//`define SPI_MAX_CHAR_64
`define SPI_MAX_CHAR_32
//`define SPI_MAX_CHAR_24
//`define SPI_MAX_CHAR_16
//`define SPI_MAX_CHAR_8
 
`ifdef SPI_MAX_CHAR_128
`define SPI_MAX_CHAR 128 // Can only be set to 128
`define SPI_CHAR_LEN_BITS 7
`endif
`ifdef SPI_MAX_CHAR_64
`define SPI_MAX_CHAR 64 // Can only be set to 64
`define SPI_CHAR_LEN_BITS 6
`endif
`ifdef SPI_MAX_CHAR_32
`define SPI_MAX_CHAR 32 // Can be set from 25 to 32
`define SPI_CHAR_LEN_BITS 6
`define SPI_CHAR_RST 32'h03000000
`endif
`ifdef SPI_MAX_CHAR_24
`define SPI_MAX_CHAR 24 // Can be set from 17 to 24
`define SPI_CHAR_LEN_BITS 5
`endif
`ifdef SPI_MAX_CHAR_16
`define SPI_MAX_CHAR 16 // Can be set from 9 to 16
`define SPI_CHAR_LEN_BITS 4
`endif
`ifdef SPI_MAX_CHAR_8
`define SPI_MAX_CHAR 8 // Can be set from 1 to 8
`define SPI_CHAR_LEN_BITS 3
`endif
 
//
// Number of device select signals. Use SPI_SS_NB for fine tuning the
// exact number.
//
`define SPI_SS_NB 2 // Can be set from 1 to 2
 
//
// Bits of WISHBONE address used for partial decoding of SPI registers.
//
`define SPI_OFS_BITS 4:2
 
//
// Register offset
//
`define SPI_RX_0 0
`define SPI_RX_1 1
`define SPI_RX_2 2
`define SPI_RX_3 3
`define SPI_TX_0 0
`define SPI_TX_1 1
`define SPI_TX_2 2
`define SPI_TX_3 3
`define SPI_CTRL 4
`define SPI_DEVIDE 5
`define SPI_SS 6
 
//
// Number of bits in ctrl register
//
`define SPI_CTRL_BIT_NB 14
`define SPI_CTRL_BIT_RST 14'h420
//
// Control register bits
//
//`define SPI_CTRL_LSB
`define SPI_CTRL_TX_NEGEDGE
//`define SPI_CTRL_RX_NEGEDGE
 
/openrisc/trunk/orpsocv2/rtl/verilog/components/spi_ctrl/spi_flash_top.v
0,0 → 1,224
//////////////////////////////////////////////////////////////////////
//// ////
//// spi_top.v ////
//// ////
//// This file is part of the SPI IP core project ////
//// http://www.opencores.org/projects/spi/ ////
//// ////
//// Author(s): ////
//// - Simon Srot (simons@opencores.org) ////
//// ////
//// All additional information is avaliable in the Readme.txt ////
//// file. ////
//// ////
//////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 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 ////
//// ////
//////////////////////////////////////////////////////////////////////
 
 
`include "spi_defines.v"
`include "timescale.v"
 
module spi_flash_top
(
// Wishbone signals
wb_clk_i, wb_rst_i, wb_adr_i, wb_dat_i, wb_dat_o, wb_sel_i,
wb_we_i, wb_stb_i, wb_cyc_i, wb_ack_o,
// SPI signals
ss_pad_o, sclk_pad_o, mosi_pad_o, miso_pad_i
);
parameter divider_len = 2;
parameter divider = 0;
parameter Tp = 1;
// Wishbone signals
input wb_clk_i; // master clock input
input wb_rst_i; // synchronous active high reset
input [4:2] wb_adr_i; // lower address bits
input [31:0] wb_dat_i; // databus input
output [31:0] wb_dat_o; // databus output
input [3:0] wb_sel_i; // byte select inputs
input wb_we_i; // write enable input
input wb_stb_i; // stobe/core select signal
input wb_cyc_i; // valid bus cycle input
output wb_ack_o; // bus cycle acknowledge output
// SPI signals
output [`SPI_SS_NB-1:0] ss_pad_o; // slave select
output sclk_pad_o; // serial clock
output mosi_pad_o; // master out slave in
input miso_pad_i; // master in slave out
reg [31:0] wb_dat_o;
reg wb_ack_o;
// Internal signals
// reg [`SPI_DIVIDER_LEN-1:0] divider; // Divider register
wire [`SPI_CTRL_BIT_NB-1:0] ctrl; // Control and status register
reg [`SPI_SS_NB-1:0] ss; // Slave select register
wire [`SPI_MAX_CHAR-1:0] rx; // Rx register
 
wire [5:0] char_len;
reg char_len_ctrl; // char len
reg go; // go
wire spi_ctrl_sel; // ctrl register select
wire spi_tx_sel; // tx_l register select
wire spi_ss_sel; // ss register select
wire tip; // transfer in progress
wire pos_edge; // recognize posedge of sclk
wire neg_edge; // recognize negedge of sclk
wire last_bit; // marks last character bit
 
wire rx_negedge; // miso is sampled on negative edge
wire tx_negedge; // mosi is driven on negative edge
wire lsb; // lsb first on line
wire ass; // automatic slave select
// Address decoder
assign spi_ctrl_sel = wb_cyc_i & wb_stb_i & (wb_adr_i[`SPI_OFS_BITS] == `SPI_CTRL);
assign spi_tx_sel = wb_cyc_i & wb_stb_i & (wb_adr_i[`SPI_OFS_BITS] == `SPI_TX_0);
assign spi_ss_sel = wb_cyc_i & wb_stb_i & (wb_adr_i[`SPI_OFS_BITS] == `SPI_SS);
// Read from registers
// Wb data out
always @(posedge wb_clk_i or posedge wb_rst_i)
begin
if (wb_rst_i)
wb_dat_o <= #Tp 32'b0;
else
case (wb_adr_i[`SPI_OFS_BITS])
`SPI_RX_0: wb_dat_o <= rx;
`SPI_CTRL: wb_dat_o <= {18'd0, ctrl};
`SPI_DEVIDE: wb_dat_o <= divider;//{{32-divider_len{1'b0}}, divider}; -- icarus couldn't compile original -- jb
`SPI_SS: wb_dat_o <= {{32-`SPI_SS_NB{1'b0}}, ss};
default: wb_dat_o <= rx;
endcase
end
// Wb acknowledge
always @(posedge wb_clk_i or posedge wb_rst_i)
begin
if (wb_rst_i)
wb_ack_o <= #Tp 1'b0;
else
wb_ack_o <= #Tp wb_cyc_i & wb_stb_i & ~wb_ack_o;
end
// Ctrl register
always @(posedge wb_clk_i or posedge wb_rst_i)
begin
if (wb_rst_i)
{go,char_len_ctrl} <= #Tp 2'b01;
else if(spi_ctrl_sel && wb_we_i && !tip)
begin
if (wb_sel_i[0])
char_len_ctrl <= #Tp wb_dat_i[5];
if (wb_sel_i[1])
go <= #Tp wb_dat_i[8];
end
else if(tip && last_bit && pos_edge)
go <= #Tp 1'b0;
end
 
assign char_len = char_len_ctrl ? 6'd32 : 6'd8;
`ifdef SPI_CTRL_ASS
assign ass = 1'b1;
`else
assign ass = 1'b0;
`endif
`ifdef SPI_CTRL_LSB
assign lsb = 1'b1;
`else
assign lsb = 1'b0;
`endif
`ifdef SPI_CTRL_RX_NEGEDGE
assign rx_negedge = 1'b1;
`else
assign rx_negedge = 1'b0;
`endif
`ifdef SPI_CTRL_TX_NEGEDGE
assign tx_negedge = 1'b1;
`else
assign tx_negedge = 1'b1;
`endif
 
assign ctrl = {ass,1'b0,lsb,tx_negedge,rx_negedge,go,1'b0,1'b0,char_len};
// Slave select register
always @(posedge wb_clk_i or posedge wb_rst_i)
if (wb_rst_i)
ss <= #Tp {`SPI_SS_NB{1'b0}};
else if(spi_ss_sel && wb_we_i && !tip)
if (wb_sel_i[0])
ss <= #Tp wb_dat_i[`SPI_SS_NB-1:0];
assign ss_pad_o = ~((ss & {`SPI_SS_NB{tip & ass}}) | (ss & {`SPI_SS_NB{!ass}}));
spi_flash_clgen
#
(
.divider_len(divider_len),
.divider(divider)
)
clgen
(
.clk_in(wb_clk_i),
.rst(wb_rst_i),
.go(go),
.enable(tip),
.last_clk(last_bit),
.clk_out(sclk_pad_o),
.pos_edge(pos_edge),
.neg_edge(neg_edge)
);
spi_flash_shift shift
(
.clk(wb_clk_i),
.rst(wb_rst_i),
.len(char_len[`SPI_CHAR_LEN_BITS-1:0]),
.latch(spi_tx_sel & wb_we_i),
.byte_sel(wb_sel_i),
.go(go),
.pos_edge(pos_edge),
.neg_edge(neg_edge),
.lsb(lsb),
.rx_negedge(rx_negedge),
.tx_negedge(tx_negedge),
.tip(tip),
.last(last_bit),
.p_in(wb_dat_i),
.p_out(rx),
.s_clk(sclk_pad_o),
.s_in(miso_pad_i),
.s_out(mosi_pad_o)
);
endmodule
/openrisc/trunk/orpsocv2/rtl/verilog/components/wb_conbus/wb_conbus_top.v
46,19 → 46,9
// Max speed >60M , and 374 SLICE if using Multiplexor bus
// or 150 SLICE if using tri-state bus.
//
`define dw 32 // Data bus Width
`define aw 32 // Address bus Width
`define sw `dw / 8 // Number of Select Lines
`define mbusw `aw + `sw + `dw +4 //address width + byte select width + dat width + cyc + we + stb +cab , input from master interface
`define sbusw 3 // ack + err + rty, input from slave interface
`define mselectw 8 // number of masters
`define sselectw 8 // number of slavers
 
//`define WB_USE_TRISTATE
 
// Define the following to enable logic to generate the first few instructions at reset
`define OR1200_BOOT_LOGIC
 
module wb_conbus_top(
clk_i, rst_i,
 
128,12 → 118,13
 
);
 
 
`include "wb_conbus_defines.v"
 
////////////////////////////////////////////////////////////////////
//
//
// Module Parameters
//
 
 
parameter s0_addr_w = 4 ; // slave 0 address decode width
parameter s0_addr = 4'h0; // slave 0 address
parameter s1_addr_w = 4 ; // slave 1 address decode width
146,7 → 137,7
parameter s6_addr = 8'h96; // slave 6 address
parameter s7_addr = 8'h97; // slave 7 address
 
 
////////////////////////////////////////////////////////////////////
//
// Module IOs
openrisc/trunk/orpsocv2/rtl/verilog/components/tap/tap.v Property changes : Deleted: svn:executable ## -1 +0,0 ## -* \ No newline at end of property Index: openrisc/trunk/orpsocv2/rtl/verilog/components/or1200r2/or1200_du.v =================================================================== --- openrisc/trunk/orpsocv2/rtl/verilog/components/or1200r2/or1200_du.v (revision 66) +++ openrisc/trunk/orpsocv2/rtl/verilog/components/or1200r2/or1200_du.v (revision 67) @@ -1107,7 +1107,7 @@ // // When To Compare (Match Condition 0) // -always @(dcr0 or dcpu_cycstb_i) +always @(dcr0 or dcpu_cycstb_i or dcpu_we_i) case (dcr0[`OR1200_DU_DCR_CT]) // synopsys parallel_case 3'b000: match_cond0_stb = 1'b0; //comparison disabled 3'b001: match_cond0_stb = 1'b1; // insn fetch EA @@ -1185,7 +1185,7 @@ // // When To Compare (Match Condition 1) // -always @(dcr1 or dcpu_cycstb_i) +always @(dcr1 or dcpu_cycstb_i or dcpu_we_i) case (dcr1[`OR1200_DU_DCR_CT]) // synopsys parallel_case 3'b000: match_cond1_stb = 1'b0; //comparison disabled 3'b001: match_cond1_stb = 1'b1; // insn fetch EA @@ -1256,7 +1256,7 @@ // // When To Compare (Match Condition 2) // -always @(dcr2 or dcpu_cycstb_i) +always @(dcr2 or dcpu_cycstb_i or dcpu_we_i) case (dcr2[`OR1200_DU_DCR_CT]) // synopsys parallel_case 3'b000: match_cond2_stb = 1'b0; //comparison disabled 3'b001: match_cond2_stb = 1'b1; // insn fetch EA @@ -1329,7 +1329,7 @@ // // When To Compare (Match Condition 3) // -always @(dcr3 or dcpu_cycstb_i) +always @(dcr3 or dcpu_cycstb_i or dcpu_we_i) case (dcr3[`OR1200_DU_DCR_CT]) // synopsys parallel_case 3'b000: match_cond3_stb = 1'b0; //comparison disabled 3'b001: match_cond3_stb = 1'b1; // insn fetch EA @@ -1402,7 +1402,7 @@ // // When To Compare (Match Condition 4) // -always @(dcr4 or dcpu_cycstb_i) +always @(dcr4 or dcpu_cycstb_i or dcpu_we_i) case (dcr4[`OR1200_DU_DCR_CT]) // synopsys parallel_case 3'b000: match_cond4_stb = 1'b0; //comparison disabled 3'b001: match_cond4_stb = 1'b1; // insn fetch EA @@ -1476,7 +1476,7 @@ // // When To Compare (Match Condition 5) // -always @(dcr5 or dcpu_cycstb_i) +always @(dcr5 or dcpu_cycstb_i or dcpu_we_i) case (dcr5[`OR1200_DU_DCR_CT]) // synopsys parallel_case 3'b000: match_cond5_stb = 1'b0; //comparison disabled 3'b001: match_cond5_stb = 1'b1; // insn fetch EA @@ -1549,7 +1549,7 @@ // // When To Compare (Match Condition 6) // -always @(dcr6 or dcpu_cycstb_i) +always @(dcr6 or dcpu_cycstb_i or dcpu_we_i) case (dcr6[`OR1200_DU_DCR_CT]) // synopsys parallel_case 3'b000: match_cond6_stb = 1'b0; //comparison disabled 3'b001: match_cond6_stb = 1'b1; // insn fetch EA @@ -1623,7 +1623,7 @@ // // When To Compare (Match Condition 7) // -always @(dcr7 or dcpu_cycstb_i) +always @(dcr7 or dcpu_cycstb_i or dcpu_we_i) case (dcr7[`OR1200_DU_DCR_CT]) // synopsys parallel_case 3'b000: match_cond7_stb = 1'b0; //comparison disabled 3'b001: match_cond7_stb = 1'b1; // insn fetch EA Index: openrisc/trunk/orpsocv2/rtl/verilog/components/fpu/post_norm.v =================================================================== --- openrisc/trunk/orpsocv2/rtl/verilog/components/fpu/post_norm.v (revision 66) +++ openrisc/trunk/orpsocv2/rtl/verilog/components/fpu/post_norm.v (revision 67) @@ -366,19 +366,19 @@ assign round2a = !exp_out_fe | !fract_out_7fffff | (exp_out_fe & fract_out_7fffff); assign round2_fasu = ((r | s) & !r_sign) & (!exp_out[7] | (exp_out[7] & round2a)); -assign round2_fmul = !r_sign & - ( - (exp_ovf[1] & !fract_in_00 & - ( ((!exp_out1_co | op_dn) & (r | s | (!rem_00 & op_div) )) | fract_out_00 | (!op_dn & !op_div)) - ) | + assign round2_fmul = !r_sign & ( - (r | s | (!rem_00 & op_div)) & ( - (!exp_ovf[1] & (exp_in_80 | !exp_ovf[0])) | op_div | - ( exp_ovf[1] & !exp_ovf[0] & exp_out1_co) - ) - ) - ); - + (exp_ovf[1] & !fract_in_00 & + ( ((!exp_out1_co | op_dn) & (r | s | (!rem_00 & op_div) )) | fract_out_00 | (!op_dn & !op_div)) + ) | + ( + (r | s | (!rem_00 & op_div)) & ( + (!exp_ovf[1] & (exp_in_80 | !exp_ovf[0])) | op_div | + ( exp_ovf[1] & !exp_ovf[0] & exp_out1_co) + ) + ) + ); + assign round2_f2i = rmode_10 & (( |fract_in[23:0] & !opas & (exp_in<8'h80 )) | (|fract_trunc)); assign round2 = (op_mul | op_div) ? round2_fmul : op_f2i ? round2_f2i : round2_fasu; @@ -409,42 +409,42 @@ // Fix Output for denormalized and special numbers wire max_num, inf_out; -assign max_num = ( !rmode_00 & (op_mul | op_div ) & ( - ( exp_ovf[1] & exp_ovf[0]) | - (!exp_ovf[1] & !exp_ovf[0] & exp_in_ff & (fi_ldz_2<24) & (exp_out!=8'hfe) ) - ) - ) | - - ( op_div & ( - ( rmode_01 & ( div_inf | - (exp_out_ff & !exp_ovf[1] ) | - (exp_ovf[1] & exp_ovf[0] ) - ) - ) | - - ( rmode[1] & !exp_ovf[1] & ( + assign max_num = ( !rmode_00 & (op_mul | op_div ) & ( + ( exp_ovf[1] & exp_ovf[0]) | + (!exp_ovf[1] & !exp_ovf[0] & exp_in_ff & (fi_ldz_2<24) & (exp_out!=8'hfe) ) + ) + ) | + + ( op_div & ( + ( rmode_01 & ( div_inf | + (exp_out_ff & !exp_ovf[1] ) | + (exp_ovf[1] & exp_ovf[0] ) + ) + ) | + + ( rmode[1] & !exp_ovf[1] & ( ( exp_ovf[0] & exp_in_ff & r_sign & fract_in[47] - ) | - + ) | + ( r_sign & ( (fract_in[47] & div_inf) | (exp_in[7] & !exp_out_rnd[7] & !exp_in_80 & exp_out!=8'h7f ) | (exp_in[7] & exp_out_rnd[7] & r_sign & exp_out_ff & op_dn & - div_exp1>9'h0fe ) + div_exp1>9'h0fe ) ) - ) | - + ) | + ( exp_in_00 & r_sign & ( - div_inf | - (r_sign & exp_out_ff & fi_ldz_2<24) - ) + div_inf | + (r_sign & exp_out_ff & fi_ldz_2<24) + ) + ) ) - ) - ) - ) - ); + ) + ) + ); + - assign inf_out = (rmode[1] & (op_mul | op_div) & !r_sign & ( (exp_in_ff & !op_div) | (exp_ovf[1] & exp_ovf[0] & (exp_in_00 | exp_in[7]) ) ) @@ -534,97 +534,11 @@ op_i2f ? (|fract_trunc) : ((r & !dn) | (s & !dn) | max_num | (op_div & !rem_00)); -// --------------------------------------------------------------------- -// Debugging Stuff -// synopsys translate_off -/* -wire [26:0] fracta_del, fractb_del; -wire [2:0] grs_del; -wire dn_del; -wire [7:0] exp_in_del; -wire [7:0] exp_out_del; -wire [22:0] fract_out_del; -wire [47:0] fract_in_del; -wire overflow_del; -wire [1:0] exp_ovf_del; -wire [22:0] fract_out_x_del, fract_out_rnd2a_del; -wire [24:0] trunc_xx_del; -wire exp_rnd_adj2a_del; -wire [22:0] fract_dn_del; -wire [4:0] div_opa_ldz_del; -wire [23:0] fracta_div_del; -wire [23:0] fractb_div_del; -wire div_inf_del; -wire [7:0] fi_ldz_2_del; -wire inf_out_del, max_out_del; -wire [5:0] fi_ldz_del; -wire rx_del; -wire ez_del; -wire lr; -wire [7:0] shr, shl, exp_div_del; +endmodule -delay2 #26 ud000(clk, test.u0.fracta, fracta_del); -delay2 #26 ud001(clk, test.u0.fractb, fractb_del); -delay1 #2 ud002(clk, {g,r,s}, grs_del); -delay1 #0 ud004(clk, dn, dn_del); -delay1 #7 ud005(clk, exp_in, exp_in_del); -delay1 #7 ud007(clk, exp_out_rnd, exp_out_del); -delay1 #47 ud009(clk, fract_in, fract_in_del); -delay1 #0 ud010(clk, overflow, overflow_del); -delay1 #1 ud011(clk, exp_ovf, exp_ovf_del); -delay1 #22 ud014(clk, fract_out, fract_out_x_del); -delay1 #24 ud015(clk, fract_trunc, trunc_xx_del); -delay1 #0 ud017(clk, exp_rnd_adj2a, exp_rnd_adj2a_del); -delay1 #4 ud019(clk, div_opa_ldz, div_opa_ldz_del); -delay3 #23 ud020(clk, test.u0.fdiv_opa[49:26], fracta_div_del); -delay3 #23 ud021(clk, test.u0.fractb_mul, fractb_div_del); -delay1 #0 ud023(clk, div_inf, div_inf_del); -delay1 #7 ud024(clk, fi_ldz_2, fi_ldz_2_del); -delay1 #0 ud025(clk, inf_out, inf_out_del); -delay1 #0 ud026(clk, max_num, max_num_del); -delay1 #5 ud027(clk, fi_ldz, fi_ldz_del); -delay1 #0 ud028(clk, rem_00, rx_del); -delay1 #0 ud029(clk, left_right, lr); -delay1 #7 ud030(clk, shift_right, shr); -delay1 #7 ud031(clk, shift_left, shl); -delay1 #22 ud032(clk, fract_out_rnd2a, fract_out_rnd2a_del); -delay1 #7 ud033(clk, exp_div, exp_div_del); - -always @(test.error_event) - begin - - $display("\n----------------------------------------------"); - - $display("ERROR: GRS: %b exp_ovf: %b dn: %h exp_in: %h exp_out: %h, exp_rnd_adj2a: %b", - grs_del, exp_ovf_del, dn_del, exp_in_del, exp_out_del, exp_rnd_adj2a_del); - - $display(" div_opa: %b, div_opb: %b, rem_00: %b, exp_div: %h", - fracta_div_del, fractb_div_del, rx_del, exp_div_del); - - $display(" lr: %b, shl: %h, shr: %h", - lr, shl, shr); - - - $display(" overflow: %b, fract_in=%b fa:%h fb:%h", - overflow_del, fract_in_del, fracta_del, fractb_del); - - $display(" div_opa_ldz: %h, div_inf: %b, inf_out: %b, max_num: %b, fi_ldz: %h, fi_ldz_2: %h", - div_opa_ldz_del, div_inf_del, inf_out_del, max_num_del, fi_ldz_del, fi_ldz_2_del); - - $display(" fract_out_x: %b, fract_out_rnd2a_del: %h, fract_trunc: %b\n", - fract_out_x_del, fract_out_rnd2a_del, trunc_xx_del); - end - - -// synopsys translate_on -*/ -endmodule - -// synopsys translate_off - module delay1(clk, in, out); parameter N = 1; input [N:0] in; @@ -674,4 +588,3 @@ endmodule -// synopsys translate_on \ No newline at end of file
/openrisc/trunk/orpsocv2/rtl/verilog/components/fpu/fpu.v
493,47 → 493,7
always @(posedge clk)
snan <= #1 snan_d;
 
// synopsys translate_off
/*
wire mul_uf_del;
wire uf2_del, ufb2_del, ufc2_del, underflow_d_del;
wire co_del;
wire [30:0] out_d_del;
wire ov_fasu_del, ov_fmul_del;
wire [2:0] fop;
wire [4:0] ldza_del;
wire [49:0] quo_del;
 
delay1 #0 ud000(clk, underflow_fmul1, mul_uf_del);
delay1 #0 ud001(clk, underflow_fmul_r[0], uf2_del);
delay1 #0 ud002(clk, underflow_fmul_r[1], ufb2_del);
delay1 #0 ud003(clk, underflow_d, underflow_d_del);
delay1 #0 ud004(clk, test.u0.u4.exp_out1_co, co_del);
delay1 #0 ud005(clk, underflow_fmul_r[2], ufc2_del);
delay1 #30 ud006(clk, out_d, out_d_del);
 
delay1 #0 ud007(clk, overflow_fasu, ov_fasu_del);
delay1 #0 ud008(clk, overflow_fmul, ov_fmul_del);
 
delay1 #2 ud009(clk, fpu_op_r3, fop);
 
delay3 #4 ud010(clk, div_opa_ldz_d, ldza_del);
 
delay1 #49 ud012(clk, quo, quo_del);
 
always @(test.error_event)
begin
#0.2
$display("muf: %b uf0: %b uf1: %b uf2: %b, tx0: %b, co: %b, out_d: %h (%h %h), ov_fasu: %b, ov_fmul: %b, fop: %h",
mul_uf_del, uf2_del, ufb2_del, ufc2_del, underflow_d_del, co_del, out_d_del, out_d_del[30:23], out_d_del[22:0],
ov_fasu_del, ov_fmul_del, fop );
$display("ldza: %h, quo: %b",
ldza_del, quo_del);
end
// synopsys translate_on
*/
 
 
// Status Outputs
always @(posedge clk)
qnan <= #1 fpu_op_r3[2] ? 0 : (
openrisc/trunk/orpsocv2/rtl/verilog/components/or1k_startup/spi_flash_top.v Property changes : Deleted: svn:executable ## -1 +0,0 ## -* \ No newline at end of property Index: openrisc/trunk/orpsocv2/rtl/verilog/components/or1k_startup/spi_flash_shift.v =================================================================== --- openrisc/trunk/orpsocv2/rtl/verilog/components/or1k_startup/spi_flash_shift.v (revision 66) +++ openrisc/trunk/orpsocv2/rtl/verilog/components/or1k_startup/spi_flash_shift.v (nonexistent) @@ -1,149 +0,0 @@ -////////////////////////////////////////////////////////////////////// -//// //// -//// spi_shift.v //// -//// //// -//// This file is part of the SPI IP core project //// -//// http://www.opencores.org/projects/spi/ //// -//// //// -//// Author(s): //// -//// - Simon Srot (simons@opencores.org) //// -//// //// -//// All additional information is avaliable in the Readme.txt //// -//// file. //// -//// //// -////////////////////////////////////////////////////////////////////// -//// //// -//// Copyright (C) 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 //// -//// //// -////////////////////////////////////////////////////////////////////// - -`include "spi_defines.v" -`include "timescale.v" - -module spi_flash_shift - ( - clk, rst, latch, byte_sel, len, go, - pos_edge, neg_edge, - lsb, rx_negedge, tx_negedge, - tip, last, - p_in, p_out, s_clk, s_in, s_out); - - parameter Tp = 1; - - input clk; // system clock - input rst; // reset - input latch; // latch signal for storing the data in shift register - input [3:0] byte_sel; // byte select signals for storing the data in shift register - input [`SPI_CHAR_LEN_BITS-1:0] len; // data len in bits (minus one) - input lsb; // lbs first on the line - input tx_negedge; - input rx_negedge; - input go; // start stansfer - input pos_edge; // recognize posedge of sclk - input neg_edge; // recognize negedge of sclk - output tip; // transfer in progress - output last; // last bit - input [31:0] p_in; // parallel in - output [`SPI_MAX_CHAR-1:0] p_out; // parallel out - input s_clk; // serial clock - input s_in; // serial in - output s_out; // serial out - - reg s_out; - reg tip; - - reg [`SPI_CHAR_LEN_BITS:0] cnt; // data bit count - reg [`SPI_MAX_CHAR-1:0] data; // shift register - wire [`SPI_CHAR_LEN_BITS:0] tx_bit_pos; // next bit position - wire [`SPI_CHAR_LEN_BITS:0] rx_bit_pos; // next bit position - wire rx_clk; // rx clock enable - wire tx_clk; // tx clock enable - - - assign p_out = data; - - assign tx_bit_pos = lsb ? {!(|len), len} - cnt : cnt - {{`SPI_CHAR_LEN_BITS{1'b0}},1'b1}; - assign rx_bit_pos = lsb ? {!(|len), len} - (rx_negedge ? cnt + {{`SPI_CHAR_LEN_BITS{1'b0}},1'b1} : cnt) : (rx_negedge ? cnt : cnt - {{`SPI_CHAR_LEN_BITS{1'b0}},1'b1}); - - assign last = !(|cnt); - - assign rx_clk = (rx_negedge ? neg_edge : pos_edge) && (!last || s_clk); - - assign tx_clk = (tx_negedge ? neg_edge : pos_edge) && !last; - - // Character bit counter - always @(posedge clk or posedge rst) - begin - if(rst) - cnt <= #Tp {`SPI_CHAR_LEN_BITS+1{1'b0}}; - else - begin - if(tip) - cnt <= #Tp pos_edge ? (cnt - {{`SPI_CHAR_LEN_BITS{1'b0}}, 1'b1}) : cnt; - else - cnt <= #Tp !(|len) ? {1'b1, {`SPI_CHAR_LEN_BITS{1'b0}}} : {1'b0, len}; - end - end - - // Transfer in progress - always @(posedge clk or posedge rst) - begin - if(rst) - tip <= #Tp 1'b0; - else if(go && ~tip) - tip <= #Tp 1'b1; - else if(tip && last && pos_edge) - tip <= #Tp 1'b0; - end - - // Sending bits to the line - always @(posedge clk or posedge rst) - begin - if (rst) - s_out <= #Tp 1'b0; - else - s_out <= #Tp (tx_clk || !tip) ? data[tx_bit_pos[`SPI_CHAR_LEN_BITS-1:0]] : s_out; - end - - // Receiving bits from the line - always @(posedge clk or posedge rst) - if (rst) - data <= #Tp `SPI_CHAR_RST; - else - if (latch & !tip) - begin - if (byte_sel[0]) - data[7:0] <= #Tp p_in[7:0]; - if (byte_sel[1]) - data[15:8] <= #Tp p_in[15:8]; - if (byte_sel[2]) - data[23:16] <= #Tp p_in[23:16]; - if (byte_sel[3]) - data[31:24] <= #Tp p_in[31:24]; - end - else - data[rx_bit_pos[`SPI_CHAR_LEN_BITS-1:0]] <= #Tp rx_clk ? s_in : data[rx_bit_pos[`SPI_CHAR_LEN_BITS-1:0]]; - -endmodule -
openrisc/trunk/orpsocv2/rtl/verilog/components/or1k_startup/spi_flash_shift.v Property changes : Deleted: svn:executable ## -1 +0,0 ## -* \ No newline at end of property Index: openrisc/trunk/orpsocv2/rtl/verilog/components/or1k_startup/spi_flash_clgen.v =================================================================== --- openrisc/trunk/orpsocv2/rtl/verilog/components/or1k_startup/spi_flash_clgen.v (revision 66) +++ openrisc/trunk/orpsocv2/rtl/verilog/components/or1k_startup/spi_flash_clgen.v (nonexistent) @@ -1,110 +0,0 @@ -////////////////////////////////////////////////////////////////////// -//// //// -//// spi_clgen.v //// -//// //// -//// This file is part of the SPI IP core project //// -//// http://www.opencores.org/projects/spi/ //// -//// //// -//// Author(s): //// -//// - Simon Srot (simons@opencores.org) //// -//// //// -//// All additional information is avaliable in the Readme.txt //// -//// file. //// -//// //// -////////////////////////////////////////////////////////////////////// -//// //// -//// Copyright (C) 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 //// -//// //// -////////////////////////////////////////////////////////////////////// - -`include "spi_defines.v" -`include "timescale.v" - -module spi_flash_clgen (clk_in, rst, go, enable, last_clk, clk_out, pos_edge, neg_edge); - - parameter divider_len = 2; - parameter divider = 1; - - parameter Tp = 1; - - input clk_in; // input clock (system clock) - input rst; // reset - input enable; // clock enable - input go; // start transfer - input last_clk; // last clock - //input [spi_divider_len-1:0] divider; // clock divider (output clock is divided by this value) - output clk_out; // output clock - output pos_edge; // pulse marking positive edge of clk_out - output neg_edge; // pulse marking negative edge of clk_out - - reg clk_out; - reg pos_edge; - reg neg_edge; - - reg [divider_len-1:0] cnt; // clock counter - wire cnt_zero; // conter is equal to zero - wire cnt_one; // conter is equal to one - - - assign cnt_zero = cnt == {divider_len{1'b0}}; - assign cnt_one = cnt == {{divider_len-1{1'b0}}, 1'b1}; - - // Counter counts half period - always @(posedge clk_in or posedge rst) - begin - if(rst) - cnt <= #Tp {divider_len{1'b1}}; - else - begin - if(!enable || cnt_zero) - cnt <= #Tp divider; - else - cnt <= #Tp cnt - {{divider_len-1{1'b0}}, 1'b1}; - end - end - - // clk_out is asserted every other half period - always @(posedge clk_in or posedge rst) - begin - if(rst) - clk_out <= #Tp 1'b0; - else - clk_out <= #Tp (enable && cnt_zero && (!last_clk || clk_out)) ? ~clk_out : clk_out; - end - - // Pos and neg edge signals - always @(posedge clk_in or posedge rst) - begin - if(rst) - begin - pos_edge <= #Tp 1'b0; - neg_edge <= #Tp 1'b0; - end - else - begin - pos_edge <= #Tp (enable && !clk_out && cnt_one) || (!(|divider) && clk_out) || (!(|divider) && go && !enable); - neg_edge <= #Tp (enable && clk_out && cnt_one) || (!(|divider) && !clk_out && enable); - end - end -endmodule
openrisc/trunk/orpsocv2/rtl/verilog/components/or1k_startup/spi_flash_clgen.v Property changes : Deleted: svn:executable ## -1 +0,0 ## -* \ No newline at end of property Index: openrisc/trunk/orpsocv2/rtl/verilog/components/or1k_startup/spi_defines.v =================================================================== --- openrisc/trunk/orpsocv2/rtl/verilog/components/or1k_startup/spi_defines.v (revision 66) +++ openrisc/trunk/orpsocv2/rtl/verilog/components/or1k_startup/spi_defines.v (nonexistent) @@ -1,139 +0,0 @@ -////////////////////////////////////////////////////////////////////// -//// //// -//// spi_define.v //// -//// //// -//// This file is part of the SPI IP core project //// -//// http://www.opencores.org/projects/spi/ //// -//// //// -//// Author(s): //// -//// - Simon Srot (simons@opencores.org) //// -//// //// -//// All additional information is avaliable in the Readme.txt //// -//// file. //// -//// //// -////////////////////////////////////////////////////////////////////// -//// //// -//// Copyright (C) 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 //// -//// //// -////////////////////////////////////////////////////////////////////// - -// -// Number of bits used for devider register. If used in system with -// low frequency of system clock this can be reduced. -// Use SPI_DIVIDER_LEN for fine tuning theexact number. -// -`define SPI_DIVIDER_LEN_8 -//`define SPI_DIVIDER_LEN_16 -//`define SPI_DIVIDER_LEN_24 -//`define SPI_DIVIDER_LEN_32 - -`ifdef SPI_DIVIDER_LEN_8 - `define SPI_DIVIDER_LEN 4 // Can be set from 1 to 8 -`endif -`ifdef SPI_DIVIDER_LEN_16 - `define SPI_DIVIDER_LEN 16 // Can be set from 9 to 16 -`endif -`ifdef SPI_DIVIDER_LEN_24 - `define SPI_DIVIDER_LEN 24 // Can be set from 17 to 24 -`endif -`ifdef SPI_DIVIDER_LEN_32 - `define SPI_DIVIDER_LEN 32 // Can be set from 25 to 32 -`endif - -// -// Maximum nuber of bits that can be send/received at once. -// Use SPI_MAX_CHAR for fine tuning the exact number, when using -// SPI_MAX_CHAR_32, SPI_MAX_CHAR_24, SPI_MAX_CHAR_16, SPI_MAX_CHAR_8. -// -//`define SPI_MAX_CHAR_128 -//`define SPI_MAX_CHAR_64 -`define SPI_MAX_CHAR_32 -//`define SPI_MAX_CHAR_24 -//`define SPI_MAX_CHAR_16 -//`define SPI_MAX_CHAR_8 - -`ifdef SPI_MAX_CHAR_128 - `define SPI_MAX_CHAR 128 // Can only be set to 128 - `define SPI_CHAR_LEN_BITS 7 -`endif -`ifdef SPI_MAX_CHAR_64 - `define SPI_MAX_CHAR 64 // Can only be set to 64 - `define SPI_CHAR_LEN_BITS 6 -`endif -`ifdef SPI_MAX_CHAR_32 - `define SPI_MAX_CHAR 32 // Can be set from 25 to 32 - `define SPI_CHAR_LEN_BITS 6 - `define SPI_CHAR_RST 32'h03000000 -`endif -`ifdef SPI_MAX_CHAR_24 - `define SPI_MAX_CHAR 24 // Can be set from 17 to 24 - `define SPI_CHAR_LEN_BITS 5 -`endif -`ifdef SPI_MAX_CHAR_16 - `define SPI_MAX_CHAR 16 // Can be set from 9 to 16 - `define SPI_CHAR_LEN_BITS 4 -`endif -`ifdef SPI_MAX_CHAR_8 - `define SPI_MAX_CHAR 8 // Can be set from 1 to 8 - `define SPI_CHAR_LEN_BITS 3 -`endif - -// -// Number of device select signals. Use SPI_SS_NB for fine tuning the -// exact number. -// -`define SPI_SS_NB 2 // Can be set from 1 to 2 - -// -// Bits of WISHBONE address used for partial decoding of SPI registers. -// -`define SPI_OFS_BITS 4:2 - -// -// Register offset -// -`define SPI_RX_0 0 -`define SPI_RX_1 1 -`define SPI_RX_2 2 -`define SPI_RX_3 3 -`define SPI_TX_0 0 -`define SPI_TX_1 1 -`define SPI_TX_2 2 -`define SPI_TX_3 3 -`define SPI_CTRL 4 -`define SPI_DEVIDE 5 -`define SPI_SS 6 - -// -// Number of bits in ctrl register -// -`define SPI_CTRL_BIT_NB 14 -`define SPI_CTRL_BIT_RST 14'h420 -// -// Control register bits -// -//`define SPI_CTRL_LSB -`define SPI_CTRL_TX_NEGEDGE -//`define SPI_CTRL_RX_NEGEDGE -
openrisc/trunk/orpsocv2/rtl/verilog/components/or1k_startup/spi_defines.v Property changes : Deleted: svn:executable ## -1 +0,0 ## -* \ No newline at end of property Index: openrisc/trunk/orpsocv2/sim/bin/modelsim.scr =================================================================== --- openrisc/trunk/orpsocv2/sim/bin/modelsim.scr (revision 66) +++ openrisc/trunk/orpsocv2/sim/bin/modelsim.scr (revision 67) @@ -7,6 +7,7 @@ +incdir+$RTL_DIR/components/ethernet +incdir+$RTL_DIR/components/fpu +incdir+$RTL_DIR/components/or1k_startup ++incdir+$RTL_DIR/components/spi_ctrl +incdir+$RTL_DIR/components/or1k_top +incdir+$RTL_DIR/components/or1200r2 +incdir+$RTL_DIR/components/tap @@ -23,6 +24,7 @@ -y $RTL_DIR/components/ethernet -y $RTL_DIR/components/fpu -y $RTL_DIR/components/or1k_startup +-y $RTL_DIR/components/spi_ctrl -y $RTL_DIR/components/or1k_top -y $RTL_DIR/components/or1200r2 -y $RTL_DIR/components/tap @@ -37,134 +39,8 @@ $BACKEND_DIR/generic_pll.v $BACKEND_DIR/generic_buffers.v -// Verilog component files -$RTL_DIR/components/uart16550/uart_rfifo.v -$RTL_DIR/components/uart16550/uart_debug_if.v -$RTL_DIR/components/uart16550/raminfr.v -$RTL_DIR/components/uart16550/uart_transmitter.v -$RTL_DIR/components/uart16550/uart_sync_flops.v -$RTL_DIR/components/uart16550/uart_receiver.v -$RTL_DIR/components/uart16550/uart_top.v -$RTL_DIR/components/uart16550/uart_regs.v -$RTL_DIR/components/uart16550/uart_tfifo.v -$RTL_DIR/components/uart16550/uart_wb.v -$RTL_DIR/components/wb_conbus/wb_conbus_top.v -$RTL_DIR/components/wb_conbus/wb_conbus_arb.v -$RTL_DIR/components/wb_sdram_ctrl/delay.v -$RTL_DIR/components/wb_sdram_ctrl/wb_sdram_ctrl.v -$RTL_DIR/components/wb_sdram_ctrl/wb_sdram_ctrl_fsm.v -$RTL_DIR/components/wb_sdram_ctrl/wb_sdram_ctrl_fifo.v -$RTL_DIR/components/ethernet/eth_top.v -$RTL_DIR/components/ethernet/eth_maccontrol.v -$RTL_DIR/components/ethernet/eth_crc.v -$RTL_DIR/components/ethernet/eth_rxethmac.v -//$RTL_DIR/components/ethernet/eth_cop.v -$RTL_DIR/components/ethernet/eth_spram_256x32.v -$RTL_DIR/components/ethernet/eth_outputcontrol.v -$RTL_DIR/components/ethernet/eth_rxstatem.v -$RTL_DIR/components/ethernet/eth_register.v -$RTL_DIR/components/ethernet/eth_registers.v -$RTL_DIR/components/ethernet/eth_transmitcontrol.v -$RTL_DIR/components/ethernet/eth_clockgen.v -$RTL_DIR/components/ethernet/eth_random.v -$RTL_DIR/components/ethernet/eth_macstatus.v -//$RTL_DIR/components/ethernet/xilinx_dist_ram_16x32.v -$RTL_DIR/components/ethernet/eth_txcounters.v -$RTL_DIR/components/ethernet/eth_shiftreg.v -$RTL_DIR/components/ethernet/eth_txethmac.v -$RTL_DIR/components/ethernet/eth_wishbone.v -$RTL_DIR/components/ethernet/eth_rxaddrcheck.v -$RTL_DIR/components/ethernet/eth_miim.v -$RTL_DIR/components/ethernet/eth_rxcounters.v -$RTL_DIR/components/ethernet/eth_fifo.v -$RTL_DIR/components/ethernet/eth_receivecontrol.v -$RTL_DIR/components/ethernet/eth_txstatem.v -$RTL_DIR/components/or1200r2/or1200_immu_top.v -$RTL_DIR/components/or1200r2/or1200_sb_fifo.v -$RTL_DIR/components/or1200r2/or1200_freeze.v -$RTL_DIR/components/or1200r2/or1200_dpram_256x32.v -$RTL_DIR/components/or1200r2/or1200_ic_fsm.v -$RTL_DIR/components/or1200r2/or1200_spram_2048x32_bw.v -$RTL_DIR/components/or1200r2/or1200_dc_fsm.v -$RTL_DIR/components/or1200r2/or1200_spram_1024x32.v -$RTL_DIR/components/or1200r2/or1200_spram_64x24.v -$RTL_DIR/components/or1200r2/or1200_xcv_ram32x8d.v -$RTL_DIR/components/or1200r2/or1200_wb_biu.v -$RTL_DIR/components/or1200r2/or1200_spram.v -$RTL_DIR/components/or1200r2/or1200_du.v -$RTL_DIR/components/or1200r2/or1200_operandmuxes.v -$RTL_DIR/components/or1200r2/or1200_dc_top.v -$RTL_DIR/components/or1200r2/or1200_mem2reg.v -$RTL_DIR/components/or1200r2/or1200_spram_64x22.v -$RTL_DIR/components/or1200r2/or1200_except.v -$RTL_DIR/components/or1200r2/or1200_immu_tlb.v -$RTL_DIR/components/or1200r2/or1200_cpu.v -$RTL_DIR/components/or1200r2/or1200_fpu.v -$RTL_DIR/components/or1200r2/or1200_genpc.v -$RTL_DIR/components/or1200r2/or1200_pic.v -$RTL_DIR/components/or1200r2/or1200_dpram_32x32.v -$RTL_DIR/components/or1200r2/or1200_lsu.v -$RTL_DIR/components/or1200r2/or1200_spram_1024x32_bw.v -$RTL_DIR/components/or1200r2/or1200_amultp2_32x32.v -$RTL_DIR/components/or1200r2/or1200_iwb_biu.v -$RTL_DIR/components/or1200r2/or1200_dc_ram.v -$RTL_DIR/components/or1200r2/or1200_spram_1024x8.v -$RTL_DIR/components/or1200r2/or1200_spram_2048x32.v -$RTL_DIR/components/or1200r2/or1200_spram_256x21.v -$RTL_DIR/components/or1200r2/or1200_ic_top.v -$RTL_DIR/components/or1200r2/or1200_dmmu_top.v -$RTL_DIR/components/or1200r2/or1200_dmmu_tlb.v -$RTL_DIR/components/or1200r2/or1200_mult_mac.v -$RTL_DIR/components/or1200r2/or1200_ctrl.v -$RTL_DIR/components/or1200r2/or1200_ic_tag.v -$RTL_DIR/components/or1200r2/or1200_top.v -//$RTL_DIR/components/or1200r2/or1200_dpram.v -$RTL_DIR/components/or1200r2/or1200_spram_32x24.v -$RTL_DIR/components/or1200r2/or1200_if.v -$RTL_DIR/components/or1200r2/or1200_dc_tag.v -$RTL_DIR/components/or1200r2/or1200_spram_512x20.v -$RTL_DIR/components/or1200r2/or1200_rf.v -$RTL_DIR/components/or1200r2/or1200_spram_128x32.v -$RTL_DIR/components/or1200r2/or1200_spram_2048x8.v -$RTL_DIR/components/or1200r2/or1200_spram_64x14.v -$RTL_DIR/components/or1200r2/or1200_gmultp2_32x32.v -$RTL_DIR/components/or1200r2/or1200_sprs.v -$RTL_DIR/components/or1200r2/or1200_reg2mem.v -$RTL_DIR/components/or1200r2/or1200_qmem_top.v -$RTL_DIR/components/or1200r2/or1200_tt.v -$RTL_DIR/components/or1200r2/or1200_pm.v -$RTL_DIR/components/or1200r2/or1200_tpram_32x32.v -$RTL_DIR/components/or1200r2/or1200_alu.v -$RTL_DIR/components/or1200r2/or1200_rfram_generic.v -$RTL_DIR/components/or1200r2/or1200_ic_ram.v -$RTL_DIR/components/or1200r2/or1200_cfgr.v -$RTL_DIR/components/or1200r2/or1200_wbmux.v -$RTL_DIR/components/or1200r2/or1200_sb.v -$RTL_DIR/components/or1k_top/or1k_top.v -$RTL_DIR/components/fpu/fpu.v -$RTL_DIR/components/fpu/fcmp.v -$RTL_DIR/components/fpu/mul_r2.v -$RTL_DIR/components/fpu/add_sub27.v -$RTL_DIR/components/fpu/div_r2.v -$RTL_DIR/components/fpu/post_norm.v -$RTL_DIR/components/fpu/except.v -$RTL_DIR/components/fpu/pre_norm.v -$RTL_DIR/components/fpu/pre_norm_fmul.v -$RTL_DIR/components/smii/smii_txrx.v -$RTL_DIR/components/tap/tap_top.v -$RTL_DIR/components/or1k_startup/OR1K_startup.v -$RTL_DIR/components/or1k_startup/spi_flash_shift.v -$RTL_DIR/components/or1k_startup/spi_flash_top.v -$RTL_DIR/components/or1k_startup/spi_flash_clgen.v -$RTL_DIR/components/ram_wb/ram_wb_sc_sw.v -$RTL_DIR/components/ram_wb/ram_wb.v -$RTL_DIR/components/debug_if/dbg_register.v -$RTL_DIR/components/debug_if/dbg_cpu_registers.v -$RTL_DIR/components/debug_if/dbg_crc32_d1.v -$RTL_DIR/components/debug_if/dbg_top.v -$RTL_DIR/components/debug_if/dbg_cpu.v -$RTL_DIR/components/debug_if/dbg_wb.v -$RTL_DIR/dummy_slave.v +// Modelsim doesn't assume this?!?!? ++libext+.v $RTL_DIR/orpsoc_top.v
/openrisc/trunk/orpsocv2/sim/bin/icarus.scr
7,6 → 7,7
+incdir+$RTL_DIR/components/ethernet
+incdir+$RTL_DIR/components/fpu
+incdir+$RTL_DIR/components/or1k_startup
+incdir+$RTL_DIR/components/spi_ctrl
+incdir+$RTL_DIR/components/or1k_top
+incdir+$RTL_DIR/components/or1200r2
+incdir+$RTL_DIR/components/tap
23,6 → 24,7
-y $RTL_DIR/components/ethernet
-y $RTL_DIR/components/fpu
-y $RTL_DIR/components/or1k_startup
-y $RTL_DIR/components/spi_ctrl
-y $RTL_DIR/components/or1k_top
-y $RTL_DIR/components/or1200r2
-y $RTL_DIR/components/tap
/openrisc/trunk/orpsocv2/sim/bin/Makefile
237,7 → 237,7
CUR_DIR=$(shell pwd)
 
# The root path of the whole project
PROJECT_ROOT=$(CUR_DIR)/../..
PROJECT_ROOT ?=$(CUR_DIR)/../..
 
# Tests is only defined if it wasn't already defined when make was called
# This is the default list of every test that is currently possible
244,14 → 244,15
TESTS ?= basic-nocache cbasic-nocache-O2 dhry-nocache-O2 except-nocache mmu-nocache mul-nocache-O2 syscall-nocache tick-nocache uart-nocache basic-icdc cbasic-icdc-O2 dhry-icdc-O2 except-icdc mmu-icdc mul-icdc-O2 syscall-icdc tick-icdc uart-icdc
 
# Paths to other important parts of this test suite
SIM_DIR=$(PROJECT_ROOT)/sim
SIM_DIR ?=$(PROJECT_ROOT)/sim
SIM_RUN_DIR=$(SIM_DIR)/run
SIM_BIN_DIR=$(SIM_DIR)/bin
SIM_RESULTS_DIR=$(SIM_DIR)/results
SIM_VLT_DIR=$(SIM_DIR)/vlt
BENCH_DIR=$(PROJECT_ROOT)/bench
BACKEND_DIR=$(PROJECT_ROOT)/backend
BACKEND_DIR ?=$(PROJECT_ROOT)/backend
BENCH_VERILOG_DIR=$(BENCH_DIR)/verilog
BENCH_TOP_VERILOG_DIR ?= $(BENCH_DIR)/verilog
BENCH_SYSC_DIR=$(BENCH_DIR)/sysc
BENCH_SYSC_SRC_DIR=$(BENCH_SYSC_DIR)/src
BENCH_SYSC_INCLUDE_DIR=$(BENCH_SYSC_DIR)/include
330,6 → 331,9
VOPT_ARGS=-voptargs="+acc=rnp"
endif
 
# RTL testbench toplevel name
RTL_TESTBENCH_TOP ?= orpsoc_testbench
 
# Simulation compile and run commands, depending on your
# simulator.
 
336,7 → 340,7
# Icarus Verilog
ifeq ($(SIMULATOR), $(ICARUS))
# Icarus Verilog Simulator compile and run commands
SIM_COMMANDCOMPILE=rm -f $(SIM_RUN_DIR)/a.out; $(ICARUS) -sorpsoc_testbench -c $(SIM_RUN_DIR)/$(GENERATED_COMMANDFILE) $(EVENT_SIM_FLAGS)
SIM_COMMANDCOMPILE=rm -f $(SIM_RUN_DIR)/a.out; $(ICARUS) -s$(RTL_TESTBENCH_TOP) -c $(SIM_RUN_DIR)/$(GENERATED_COMMANDFILE) $(EVENT_SIM_FLAGS)
# Icarus Verilog run command
SIM_COMMANDRUN=$(ICARUS_VVP) -l $(SIM_RESULTS_DIR)/$$TEST-vvp-out.log a.out
endif
344,12 → 348,12
# Modelsim
ifeq ($(SIMULATOR), $(VSIM))
# Line to compile the orpsoc design into a modelsim library.
SIM_COMMANDCOMPILE=if [ ! -e work ]; then vlib work; vlib $(MGC_ORPSOC_LIB); vlog -work orpsoc -f $(SIM_RUN_DIR)/$(GENERATED_COMMANDFILE); fi
SIM_COMMANDCOMPILE=if [ ! -e work ]; then vlib work; vlib $(MGC_ORPSOC_LIB); vlog -work $(MGC_ORPSOC_LIB) -f $(SIM_RUN_DIR)/$(GENERATED_COMMANDFILE); fi
# Final modelsim compile, done each time, pulling in or1200
# monitor and the new test_defines.v file:
VSIM_COMPILE_TB=vlog +incdir+. +incdir+$(BENCH_VERILOG_DIR) +incdir+$(RTL_VERILOG_DIR) +define+TEST_DEFINE_FILE $(BENCH_VERILOG_DIR)/or1200_monitor.v $(BENCH_VERILOG_DIR)/orpsoc_testbench.v
VSIM_COMPILE_TB=vlog +incdir+. +incdir+$(BENCH_VERILOG_DIR) +incdir+$(BENCH_TOP_VERILOG_DIR) +incdir+$(RTL_VERILOG_DIR) +define+TEST_DEFINE_FILE $(BENCH_VERILOG_DIR)/or1200_monitor.v $(BENCH_TOP_VERILOG_DIR)/$(RTL_TESTBENCH_TOP).v
# Simulation run command:
SIM_COMMANDRUN=$(VSIM_COMPILE_TB); $(VSIM) -c -quiet +nowarnTFMPC -L $(MGC_ORPSOC_LIB) $(VOPT_ARGS) -do "run -all; exit" orpsoc_testbench
SIM_COMMANDRUN=$(VSIM_COMPILE_TB); $(VSIM) -c -quiet +nowarnTFMPC -L $(MGC_ORPSOC_LIB) $(VOPT_ARGS) -do "run -all; exit" $(RTL_TESTBENCH_TOP)
endif
 
# NCVerilog
556,7 → 560,7
@echo
@echo "\t#### Compiling RTL ####"
$(Q)rm -f $(SIM_RUN_DIR)/a.out
$(Q)$(ICARUS) -sorpsoc_testbench -c $(SIM_RUN_DIR)/$(ICARUS_COMMAND_FILE).generated $(EVENT_SIM_FLAGS)
$(Q)$(ICARUS) -s$(RTL_TESTBENCH_TOP) -c $(SIM_RUN_DIR)/$(ICARUS_COMMAND_FILE).generated $(EVENT_SIM_FLAGS)
@echo
@echo "\t#### Beginning simulation with VPI debug module enabled ####"; echo
$(Q)$(ICARUS_VVP) $(ICARUS_VPI_OPTS) -l $(SIM_RESULTS_DIR)/$(VPI_TEST_SW)-vvp-out.log a.out
/openrisc/trunk/orpsocv2/sim/bin/verilator.scr
7,6 → 7,7
+incdir+$RTL_DIR/components/ethernet
+incdir+$RTL_DIR/components/fpu
+incdir+$RTL_DIR/components/or1k_startup
+incdir+$RTL_DIR/components/spi_ctrl
+incdir+$RTL_DIR/components/or1k_top
+incdir+$RTL_DIR/components/or1200r2
+incdir+$RTL_DIR/components/tap
22,6 → 23,7
-y $RTL_DIR/components/ethernet
-y $RTL_DIR/components/fpu
-y $RTL_DIR/components/or1k_startup
-y $RTL_DIR/components/spi_ctrl
-y $RTL_DIR/components/or1k_top
-y $RTL_DIR/components/or1200r2
-y $RTL_DIR/components/tap
/openrisc/trunk/orpsocv2/sw/utils/bin2vmem.c
59,8 → 59,8
// eg: ./bin2vmem data.bin -synfmt > data.vmem
//
 
#define WORDS_PER_LINE 4
#define BYTES_PER_WORD 4
#define WORDS_PER_LINE_DEFAULT 4
#define BYTES_PER_WORD_DEFAULT 4
 
#define FILENAME_CMDLINE_INDEX 1
#define FMT_CMDLINE_INDEX 2
68,26 → 68,40
#define FMT_WITH_ADDR 0
#define FMT_SYN 1
 
#define PAD_FILL 0
 
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
int main(int argc, char **argv)
{
 
FILE *fd;
FILE *fd = NULL;
int c;
int i = 0;
int write_size_word=0; // Disabled by default
unsigned int image_size;
int output_fmt = FMT_WITH_ADDR; // 0 - standard 4 per line with address, 1 - synfmt
int bytes_per_word = BYTES_PER_WORD;
//int output_fmt = FMT_WITH_ADDR; // 0 - standard 4 per line with address, 1 - synfmt
int bytes_per_word = BYTES_PER_WORD_DEFAULT, bytes_per_word_tmp;
int words_per_line = WORDS_PER_LINE_DEFAULT;
int printing_addr = 1; // Print address by default
int pad_row_end = 0; // Default is we don't pad
int pad_addr_end = 0; // Default is we don't pad
int pad_row_number = 0;
int pad_addr_number = 0;
 
// Counters keeping track of what we've printed
int current_addr = 0;
int current_word_addr = 0;
int word_counter = 0;
int total_word_counter = 0;
int byte_counter = 0;
int total_byte_counter = 0;
int row_counter = 1;
 
 
if(argc < 2) {
fprintf(stderr,"\n\tInsufficient options.\n");
fprintf(stderr,"\tPlease specify a binary file to convert to VMEM\n");
103,36 → 117,143
fprintf(stderr,"\tswitch -bpw=N after specifying the -synfmt option. Example:\n");
fprintf(stderr,"\t\t./bin2vmem prog.bin -synfmt -bpw=2 > prog.vmem\n");
fprintf(stderr,"\n");
fprintf(stderr,"\n");
fprintf(stderr,"Padding options:\n");
fprintf(stderr,"\t--pad-to-row <num>\tPad up to num rows with 0\n");
fprintf(stderr,"\t--pad-to-addr <addr>\t Pad UP to (not including) that address with 0\n");
fprintf(stderr,"\n");
exit(1);
}
 
fd = fopen( argv[FILENAME_CMDLINE_INDEX], "r" );
 
if (argc > 2) // check for the -synfmt switch
if (argc > 1) // check for the -synfmt switch
{
if (strcmp("-synfmt", argv[FMT_CMDLINE_INDEX]) == 0)
for (i = 1; i< argc; i++)
{
output_fmt = FMT_SYN; // synthesis friendly format - single column, no addr
int bytes_per_word_tmp;
if (argc > 3) // Check for extra bytes per word option
if (1 == sscanf(argv[FMT_CMDLINE_INDEX+1], "-bpw=%d", &bytes_per_word_tmp))
{
if(bytes_per_word_tmp < 4 && bytes_per_word_tmp > 0)
if ((strcmp("-synfmt", argv[i]) == 0) || (strcmp("--synfmt", argv[i]) == 0))
{
words_per_line = 1;
printing_addr = 0;
//output_fmt = FMT_SYN; // output synthesis friendly format
}
else if ((1 == sscanf(argv[i], "-bpw=%d", &bytes_per_word_tmp)) ||
(strcmp("--bpw", argv[i]) == 0))
{
if (strcmp("--bpw", argv[i]) == 0)
if (i+1 < argc)
{
//printf("# Bytes per word: %d\n", bytes_per_word_tmp);
bytes_per_word = bytes_per_word_tmp;
bytes_per_word_tmp = atoi(argv[i+1]);
i++;
}
if(bytes_per_word_tmp > 0)
{
bytes_per_word = bytes_per_word_tmp;
}
}
else if ((strcmp("--bpw", argv[i]) == 0))
{
if (i+1 < argc)
{
bytes_per_word_tmp = atoi(argv[i+1]);
i++;
}
if (bytes_per_word_tmp < 4 && bytes_per_word_tmp > 0)
{
bytes_per_word = bytes_per_word_tmp;
}
 
}
else if (strcmp("--pad-to-row", argv[i]) == 0)
{
if (i+1 < argc)
{
uint32_t tmp_addr_dec;
if (!(sscanf(argv[i+1], "%d", &tmp_addr_dec) == 1))
{
fprintf(stderr,
"Error: Number of rows to pad to not specified\n");
exit(1);
}
pad_row_number = tmp_addr_dec;
}
else
{
fprintf(stderr,
"Error: Number of rows to pad to specified\n");
exit(1);
}
if (pad_addr_end)
{
fprintf(stderr, "Error: Can only specify one padding style\n");
exit(1);
}
pad_row_end = 1;
i++;
}
else if (strcmp("--pad-to-addr", argv[i]) == 0)
{
// Get address
if (i+1 < argc)
{
uint32_t tmp_addr_hex, hex_used = 0, tmp_addr_dec, dec_used = 0;
if (sscanf(argv[i+1], "0x%x", &tmp_addr_hex) == 1)
hex_used = 1;
else if (sscanf(argv[i+1], "%d", &tmp_addr_dec) == 1)
dec_used = 1;
else
{
fprintf(stderr,
"Error: No address to pad to specified. Use either hex with 0x prefixed, or decimal\n");
exit(1);
}
if (hex_used)
pad_addr_number = tmp_addr_hex;
else
pad_addr_number = tmp_addr_dec;
}
else
{
fprintf(stderr,
"Error: No address to pad to specified\n");
exit(1);
}
if (pad_addr_end)
{
fprintf(stderr, "Error: Can only specify one padding style\n");
exit(1);
}
pad_addr_end = 1;
i++;
}
else
{
// File to open
fd = fopen( argv[i], "r" );
if (fd == NULL) {
fprintf(stderr,"failed to open input file: %s\n",argv[i]);
exit(1);
}
}
}
}
 
if (fd == NULL) {
fprintf(stderr,"failed to open input file: %s\n",argv[1]);
exit(1);
fprintf(stderr,"failed to open input file: %s\n",argv[i]);
exit(1);
}
 
 
fseek(fd, 0, SEEK_END);
image_size = ftell(fd);
fseek(fd,0,SEEK_SET);
139,8 → 260,9
 
if (write_size_word)
{
// or1200 startup method of determining size of boot image we're copying by reading out
// the very first word in flash is used. Determine the length of this file
// or1200 startup method of determining size of boot image we're
// copying by reading out the very first word in flash is used.
// Determine the length of this file.
fseek(fd, 0, SEEK_END);
image_size = ftell(fd);
fseek(fd,0,SEEK_SET);
156,16 → 278,12
}
// Now write out the image size
printf("@%8x", current_addr);
printf("@%8x", current_word_addr);
printf("%8x", image_size);
current_addr += WORDS_PER_LINE * bytes_per_word;
current_word_addr += words_per_line * bytes_per_word;
}
 
 
// Fix for the current bootloader software! Skip the first 4
// bytes of application data. Hopefully it's not important. 030509 -- jb
//for(i=0;i<4;i++)
// c=fgetc(fd);
i=0;
int starting_new_line = 1;
// Now write out the binary data to specified format. Either
174,50 → 292,142
// or simple, synplifyfriendly format which is just a list of
// the words
while ((c = fgetc(fd)) != EOF) {
if (output_fmt == FMT_WITH_ADDR) // Default format
{
if (starting_new_line)
{
// New line - print the current addr and then increment it
printf("@%.8x", current_addr);
current_addr += WORDS_PER_LINE;
starting_new_line = 0;
}
if (byte_counter == 0)
printf(" ");
printf("%.2x", (unsigned int) c); // now print the actual char
byte_counter++;
while ((c = fgetc(fd)) != EOF)
{
if (starting_new_line)
{
// New line - print the current addr and then increment it
if (printing_addr)
printf("@%.8x", current_word_addr);
starting_new_line = 0;
}
if ( (byte_counter == 0) &&
((words_per_line > 1) || (printing_addr)) )
printf(" ");
printf("%.2x", (unsigned int) c); // now print the actual char
byte_counter++;
if (byte_counter == bytes_per_word)
{
word_counter++;
total_word_counter++;
byte_counter=0;
}
if (word_counter == WORDS_PER_LINE)
if (word_counter == words_per_line)
{
printf("\n");
word_counter = 0;
current_word_addr += words_per_line;
starting_new_line = 1;
row_counter++;
}
} // End of FMT_WITH_ADDR
else if (output_fmt == FMT_SYN) // simple list of data words
{
printf("%.2x", (unsigned int) c); // now print the actual char
byte_counter++;
if (byte_counter == bytes_per_word)
{
printf("\n");
}
/* Padding stuff */
/* Pad until a set number of rows */
if (pad_row_end)
{
// First see if we need to pad to the end of the current word
if (byte_counter > 0)
{
for(i=0;i<(bytes_per_word - byte_counter); i++)
{
printf("%.2x", (unsigned int) PAD_FILL);
}
byte_counter = 0;
word_counter++;
}
if (word_counter == words_per_line)
{
printf("\n");
word_counter = 0;
current_word_addr += words_per_line;
starting_new_line = 1;
row_counter++;
}
while (row_counter < pad_row_number + 1)
{
if (starting_new_line)
{
// New line - print the current addr and then increment it
if (printing_addr)
printf("@%.8x", current_word_addr);
starting_new_line = 0;
}
if ( (byte_counter == 0) &&
((words_per_line > 1) || (printing_addr)) )
printf(" ");
printf("%.2x", (unsigned int) PAD_FILL); // PAD
byte_counter++;
if (byte_counter == bytes_per_word)
{
word_counter++;
total_word_counter++;
byte_counter=0;
}
}
if (word_counter == words_per_line)
{
printf("\n");
word_counter = 0;
current_word_addr += words_per_line;
starting_new_line = 1;
row_counter++;
}
}
}
 
}
if (pad_addr_end || pad_row_end)
{
// Figure out where we are
total_byte_counter = (current_word_addr * bytes_per_word) + (word_counter * bytes_per_word) + byte_counter;
 
// Loop again, generating 0s this time instead
while ( (pad_addr_end && (total_byte_counter < pad_addr_number)) ||
(pad_row_end && (row_counter < pad_row_number+1)) )
{
if (starting_new_line)
{
// New line - print the current addr and then increment it
if (printing_addr)
printf("@%.8x", current_word_addr);
starting_new_line = 0;
}
if ( (byte_counter == 0) &&
((words_per_line > 1) || (printing_addr)) )
printf(" ");
printf("%.2x", (unsigned int) PAD_FILL); // PAD
total_byte_counter++;
byte_counter++;
if (byte_counter == bytes_per_word)
{
word_counter++;
total_word_counter++;
byte_counter=0;
}
if (word_counter == words_per_line)
{
printf("\n");
word_counter = 0;
current_word_addr += words_per_line;
starting_new_line = 1;
row_counter++;
}
}
}
return 0;
}
/openrisc/trunk/orpsocv2/sw/support/reset.S
1,7 → 1,6
/* Support file for c based tests */
#include "spr_defs.h"
#include "board.h"
#include "mc.h"
 
.section .stack
.space 0x10000
44,12 → 43,6
l.addi r30,r0,0x0
l.addi r31,r0,0x0
 
/*
l.movhi r3,hi(MC_BASE_ADDR)
l.ori r3,r3,MC_BA_MASK
l.addi r5,r0,0x00
l.sw 0(r3),r5
*/
l.movhi r3,hi(_start)
l.ori r3,r3,lo(_start)
l.jr r3
/openrisc/trunk/orpsocv2/sw/support/uart.c
74,3 → 74,9
c = REG8(UART_BASE + UART_RX);
return c;
}
 
int uart_check_for_char()
{
return CHECK_FOR_CHAR;
}
/openrisc/trunk/orpsocv2/sw/support/uart.h
2,6 → 2,7
void uart_init(void);
void uart_putc(char);
char uart_getc(void);
int uart_check_for_char(void);
 
#define UART_RX 0 /* In: Receive buffer (DLAB=0) */
#define UART_TX 0 /* Out: Transmit buffer (DLAB=0) */
/openrisc/trunk/orpsocv2/boards/tools.inc
0,0 → 1,8
 
# Vendor tool paths - set to your own
 
XILINX_PATH=/software/xilinx
XILINX_VERILOG_SRC=$(XILINX_PATH)/verilog/src
XILINX_SETTINGS_SCRIPT=$(XILINX_PATH)/settings32.sh
 
 
/openrisc/trunk/orpsocv2/boards/xilinx/ml501/bench/ml501_testbench.v
0,0 → 1,521
//////////////////////////////////////////////////////////////////////
//// ////
//// ORPSoC on ml501 testbench ////
//// ////
//// Description ////
//// ORPSoC Testbench file ////
//// ////
//// To Do: ////
//// Update ethernet and SPI models appropriately ////
//// ////
//// 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 ////
//// ////
//////////////////////////////////////////////////////////////////////
 
`timescale 1ns/1ps
`include "glbl.v"
`include "ml501_defines.v"
`include "ml501_testbench_defines.v"
 
module ml501_testbench();
 
reg clk, clk_200;
reg rst_n;
wire clk_200_p, clk_200_n;
// Setup global clock. Period defined in orpsoc_testbench_defines.v
initial
begin
clk <= 0;
clk_200 <= 0;
rst_n <= 1;
end
 
always
#2500 clk_200 <= ~clk_200;
always
#((`CLOCK_PERIOD)/2) clk <= ~clk;
 
assign clk_200_p = clk_200;
assign clk_200_n = ~clk_200;
// Assert rst_n and then bring it low again
initial
begin
repeat (4) @(negedge clk);
rst_n <= 0;
repeat (16) @(negedge clk);
rst_n <= 1;
end
 
 
wire usr_rst_in, usr_rst_out;
assign usr_rst_in = usr_rst_out;
// Wires for the dut
wire spi_sd_sclk_o;
wire spi_sd_ss_o;
wire spi_sd_miso_i;
wire spi_sd_mosi_o;
 
`ifdef ML501_MEMORY_SSRAM
wire `tsramtrace sram_clk;
wire sram_clk_fb;
wire `tsramtrace sram_adv_ld_n;
wire [3:0] `tsramtrace sram_bw;
wire `tsramtrace sram_cen;
wire [21:1] `tsramtrace sram_flash_addr;
wire [31:0] `tsramtrace sram_flash_data;
wire `tsramtrace sram_flash_oe_n;
wire `tsramtrace sram_flash_we_n;
wire `tsramtrace sram_mode;
`endif // `ifdef ML501_MEMORY_SSRAM
 
 
`ifdef ML501_MEMORY_DDR2
 
`include "ml501_ddr2_params.vh"
localparam DEVICE_WIDTH = 16; // Memory device data width
localparam real CLK_PERIOD_NS = CLK_PERIOD / 1000.0;
localparam real TCYC_200 = 5.0;
localparam real TPROP_DQS = 0.00; // Delay for DQS signal during Write Operation
localparam real TPROP_DQS_RD = 0.00; // Delay for DQS signal during Read Operation
localparam real TPROP_PCB_CTRL = 0.00; // Delay for Address and Ctrl signals
localparam real TPROP_PCB_DATA = 0.00; // Delay for data signal during Write operation
localparam real TPROP_PCB_DATA_RD = 0.00; // Delay for data signal during Read operation
 
wire [DQ_WIDTH-1:0] ddr2_dq_sdram;
wire [DQS_WIDTH-1:0] ddr2_dqs_sdram;
wire [DQS_WIDTH-1:0] ddr2_dqs_n_sdram;
wire [DM_WIDTH-1:0] ddr2_dm_sdram;
reg [DM_WIDTH-1:0] ddr2_dm_sdram_tmp;
reg [CLK_WIDTH-1:0] ddr2_ck_sdram;
reg [CLK_WIDTH-1:0] ddr2_ck_n_sdram;
reg [ROW_WIDTH-1:0] ddr2_a_sdram;
reg [BANK_WIDTH-1:0] ddr2_ba_sdram;
reg ddr2_ras_n_sdram;
reg ddr2_cas_n_sdram;
reg ddr2_we_n_sdram;
reg [CS_WIDTH-1:0] ddr2_cs_n_sdram;
reg [CKE_WIDTH-1:0] ddr2_cke_sdram;
reg [ODT_WIDTH-1:0] ddr2_odt_sdram;
 
wire [DQ_WIDTH-1:0] ddr2_dq_fpga;
wire [DQS_WIDTH-1:0] ddr2_dqs_fpga;
wire [DQS_WIDTH-1:0] ddr2_dqs_n_fpga;
wire [DM_WIDTH-1:0] ddr2_dm_fpga;
wire [CLK_WIDTH-1:0] ddr2_ck_fpga;
wire [CLK_WIDTH-1:0] ddr2_ck_n_fpga;
wire [ROW_WIDTH-1:0] ddr2_a_fpga;
wire [BANK_WIDTH-1:0] ddr2_ba_fpga;
wire ddr2_ras_n_fpga;
wire ddr2_cas_n_fpga;
wire ddr2_we_n_fpga;
wire [CS_WIDTH-1:0] ddr2_cs_n_fpga;
wire [CKE_WIDTH-1:0] ddr2_cke_fpga;
wire [ODT_WIDTH-1:0] ddr2_odt_fpga;
`endif
`ifdef USE_SPI_FLASH
wire spi_flash_sclk_o;
wire spi_flash_ss_o;
wire spi_flash_miso_i;
wire spi_flash_mosi_o;
wire spi_flash_w_n_o;
wire spi_flash_hold_n_o;
`endif
 
`ifdef USE_ETHERNET
wire phy_tx_clk;
wire [3:0] phy_tx_data;
wire phy_tx_en;
wire phy_tx_er;
wire phy_rx_clk;
wire [3:0] phy_rx_data;
wire phy_dv;
wire phy_rx_er;
wire phy_col;
wire phy_crs;
wire phy_smi_clk;
wire phy_smi_data;
wire phy_rst_n;
`endif
wire spi1_mosi_o;
wire spi1_miso_i;
wire spi1_ss_o;
wire spi1_sclk_o;
wire [25:0] gpio;
wire uart0_srx_i;
wire uart0_stx_o;
wire dbg_tdi_i;
wire dbg_tck_i;
wire dbg_tms_i;
wire dbg_tdo_o;
wire rst_i;
wire rst_o;
wire clk_i;
 
assign clk_i = clk;
assign rst_i = rst_n;
 
// Tie off some inputs
assign spi1_miso_i = 0;
assign uart0_srx_i = 1;
 
ml501 dut
(
.sys_rst_in (rst_i),
.sys_clk_in (clk_i),
.sys_clk_in_p (clk_200_p),
.sys_clk_in_n (clk_200_n),
.usr_rst_in (usr_rst_in),
.usr_rst_out (usr_rst_out),
 
// UART
.uart0_stx_pad_o (uart0_stx_o),
.uart0_srx_pad_i (uart0_srx_i),
// JTAG
.dbg_tdo_pad_o (dbg_tdo_o),
.dbg_tdi_pad_i (dbg_tdi_i),
.dbg_tck_pad_i (dbg_tck_i),
.dbg_tms_pad_i (dbg_tms_i),
 
`ifdef USE_ETHERNET
.phy_tx_clk(phy_tx_clk),
.phy_tx_data(phy_tx_data),
.phy_tx_en(phy_tx_en),
.phy_tx_er(phy_tx_er),
.phy_rx_clk(phy_rx_clk),
.phy_rx_data(phy_rx_data),
.phy_dv(phy_dv),
.phy_rx_er(phy_rx_er),
.phy_col(phy_col),
.phy_crs(phy_crs),
.phy_smi_clk(phy_smi_clk),
.phy_smi_data(phy_smi_data),
.phy_rst_n(phy_rst_n),
`endif
`ifdef ML501_MEMORY_SSRAM
// ZBT SSRAM
.sram_clk (sram_clk),
.sram_flash_addr (sram_flash_addr),
.sram_cen (sram_cen),
.sram_flash_oe_n (sram_flash_oe_n),
.sram_flash_we_n (sram_flash_we_n),
.sram_bw (sram_bw),
.sram_adv_ld_n (sram_adv_ld_n),
.sram_mode (sram_mode),
.sram_clk_fb (sram_clk_fb),
.sram_flash_data (sram_flash_data),
`endif // `ifdef ML501_MEMORY_SSRAM
 
`ifdef ML501_MEMORY_DDR2
.ddr2_a (ddr2_a_fpga),
.ddr2_ba (ddr2_ba_fpga),
.ddr2_ras_n (ddr2_ras_n_fpga),
.ddr2_cas_n (ddr2_cas_n_fpga),
.ddr2_we_n (ddr2_we_n_fpga),
.ddr2_cs_n (ddr2_cs_n_fpga),
.ddr2_odt (ddr2_odt_fpga),
.ddr2_cke (ddr2_cke_fpga),
.ddr2_dm (ddr2_dm_fpga),
.ddr2_ck (ddr2_ck_fpga),
.ddr2_ck_n (ddr2_ck_n_fpga),
.ddr2_dq (ddr2_dq_fpga),
.ddr2_dqs (ddr2_dqs_fpga),
.ddr2_dqs_n (ddr2_dqs_n_fpga),
`endif // `ifdef ML501_MEMORY_DDR2
`ifdef USE_SPI_FLASH
.spi_flash_sclk_pad_o (spi_flash_sclk_o),
.spi_flash_ss_pad_o (spi_flash_ss_o),
.spi_flash_mosi_pad_o (spi_flash_mosi_o),
.spi_flash_w_n_pad_o (spi_flash_w_n_o),
.spi_flash_hold_n_pad_o (spi_flash_hold_n_o),
.spi_flash_miso_pad_i (spi_flash_miso_i),
`endif
// GPIO
.gpio (gpio)
);
`ifndef POST_SYNTHESIS_SIM
// Make the RF be quiet
defparam dut.i_or1k.i_or1200_top.or1200_cpu.or1200_rf.rf_a.ramb16_s36_s36.SIM_COLLISION_CHECK = "NONE";
defparam dut.i_or1k.i_or1200_top.or1200_cpu.or1200_rf.rf_b.ramb16_s36_s36.SIM_COLLISION_CHECK = "NONE";
`endif
`ifdef VPI_DEBUG_ENABLE
// Debugging interface
vpi_debug_module vpi_dbg(
.tms(dbg_tms_i),
.tck(dbg_tck_i),
.tdi(dbg_tdi_i),
.tdo(dbg_tdo_o));
`else
// If no VPI debugging, tie off JTAG inputs
assign dbg_tdi_i = 1;
assign dbg_tck_i = 0;
assign dbg_tms_i = 1;
`endif
 
`ifdef USE_ETHERNET
eth_phy eth_phy0
(
// Outputs
.mtx_clk_o (phy_tx_clk),
.mrx_clk_o (phy_rx_clk),
.mrxd_o (phy_rx_data),
.mrxdv_o (phy_dv),
.mrxerr_o (phy_rx_er),
.mcoll_o (phy_col),
.mcrs_o (phy_crs),
// Inouts
.md_io (phy_smi_data),
// Inputs
.m_rst_n_i (phy_rst_n),
.mtxd_i (phy_tx_data),
.mtxen_i (phy_tx_en),
.mtxerr_i (phy_tx_er),
.mdc_i (phy_smi_clk));
`endif
 
// External memories, if enabled
 
`ifdef ML501_MEMORY_SSRAM
wire [18:0] sram_a;
wire [3:0] dqp;
assign sram_a[18:0] = sram_flash_addr[19:1];
wire sram_ce1b, sram_ce2, sram_ce3b;
assign sram_ce1b = 1'b0;
assign sram_ce2 = 1'b1;
assign sram_ce3b = 1'b0;
assign sram_clk_fb = sram_clk;
 
cy7c1354 ssram0
(
// Inouts
// This model puts each parity bit after each byte, but the ML501's part
// doesn't, so we wire up the data bus like so.
.d ({dqp[3],sram_flash_data[31:24],dqp[2],sram_flash_data[23:16],dqp[1],sram_flash_data[15:8],dqp[0],sram_flash_data[7:0]}),
// Inputs
.clk (sram_clk),
.we_b (sram_flash_we_n),
.adv_lb (sram_adv_ld_n),
.ce1b (sram_ce1b),
.ce2 (sram_ce2),
.ce3b (sram_ce3b),
.oeb (sram_flash_oe_n),
.cenb (sram_cen),
.mode (sram_mode),
.bws (sram_bw),
.a (sram_a));
 
`endif // `ifdef ML501_MEMORY_SSRAM
 
 
 
`ifdef ML501_MEMORY_DDR2
 
`ifndef POST_SYNTHESIS_SIM
defparam dut.ml501_mc0.ml501_ddr2_wb_if0.ddr2_mig0.SIM_ONLY = 1;
`endif
 
always @( * ) begin
ddr2_ck_sdram <= #(TPROP_PCB_CTRL) ddr2_ck_fpga;
ddr2_ck_n_sdram <= #(TPROP_PCB_CTRL) ddr2_ck_n_fpga;
ddr2_a_sdram <= #(TPROP_PCB_CTRL) ddr2_a_fpga;
ddr2_ba_sdram <= #(TPROP_PCB_CTRL) ddr2_ba_fpga;
ddr2_ras_n_sdram <= #(TPROP_PCB_CTRL) ddr2_ras_n_fpga;
ddr2_cas_n_sdram <= #(TPROP_PCB_CTRL) ddr2_cas_n_fpga;
ddr2_we_n_sdram <= #(TPROP_PCB_CTRL) ddr2_we_n_fpga;
ddr2_cs_n_sdram <= #(TPROP_PCB_CTRL) ddr2_cs_n_fpga;
ddr2_cke_sdram <= #(TPROP_PCB_CTRL) ddr2_cke_fpga;
ddr2_odt_sdram <= #(TPROP_PCB_CTRL) ddr2_odt_fpga;
ddr2_dm_sdram_tmp <= #(TPROP_PCB_DATA) ddr2_dm_fpga;//DM signal generation
end // always @ ( * )
// Model delays on bi-directional BUS
genvar dqwd;
generate
for (dqwd = 0;dqwd < DQ_WIDTH;dqwd = dqwd+1) begin : dq_delay
WireDelay #
(
.Delay_g (TPROP_PCB_DATA),
.Delay_rd (TPROP_PCB_DATA_RD)
)
u_delay_dq
(
.A (ddr2_dq_fpga[dqwd]),
.B (ddr2_dq_sdram[dqwd]),
.reset (rst_n)
);
end
endgenerate
genvar dqswd;
generate
for (dqswd = 0;dqswd < DQS_WIDTH;dqswd = dqswd+1) begin : dqs_delay
WireDelay #
(
.Delay_g (TPROP_DQS),
.Delay_rd (TPROP_DQS_RD)
)
u_delay_dqs
(
.A (ddr2_dqs_fpga[dqswd]),
.B (ddr2_dqs_sdram[dqswd]),
.reset (rst_n)
);
WireDelay #
(
.Delay_g (TPROP_DQS),
.Delay_rd (TPROP_DQS_RD)
)
u_delay_dqs_n
(
.A (ddr2_dqs_n_fpga[dqswd]),
.B (ddr2_dqs_n_sdram[dqswd]),
.reset (rst_n)
);
end
endgenerate
assign ddr2_dm_sdram = ddr2_dm_sdram_tmp;
 
genvar i, j;
generate
// if the data width is multiple of 16
for(j = 0; j < CS_NUM; j = j+1) begin : gen_cs
for(i = 0; i < DQS_WIDTH/2; i = i+1) begin : gen
ddr2_model u_mem0
(
.ck (ddr2_ck_sdram[CLK_WIDTH*i/DQS_WIDTH]),
.ck_n (ddr2_ck_n_sdram[CLK_WIDTH*i/DQS_WIDTH]),
.cke (ddr2_cke_sdram[j]),
.cs_n (ddr2_cs_n_sdram[CS_WIDTH*i/DQS_WIDTH]),
.ras_n (ddr2_ras_n_sdram),
.cas_n (ddr2_cas_n_sdram),
.we_n (ddr2_we_n_sdram),
.dm_rdqs (ddr2_dm_sdram[(2*(i+1))-1 : i*2]),
.ba (ddr2_ba_sdram),
.addr (ddr2_a_sdram),
.dq (ddr2_dq_sdram[(16*(i+1))-1 : i*16]),
.dqs (ddr2_dqs_sdram[(2*(i+1))-1 : i*2]),
.dqs_n (ddr2_dqs_n_sdram[(2*(i+1))-1 : i*2]),
.rdqs_n (),
.odt (ddr2_odt_sdram[ODT_WIDTH*i/DQS_WIDTH])
);
end
end
endgenerate
`endif // `ifdef ML501_MEMORY_DDR2
`ifdef USE_SPI_FLASH
// SPI Flash
AT26DFxxx spi_flash
(
// Outputs
.SO (spi_flash_miso_i),
// Inputs
.CSB (spi_flash_ss_o),
.SCK (spi_flash_sclk_o),
.SI (spi_flash_mosi_o),
.WPB (spi_flash_w_n_o)
//.HOLDB (spi_flash_hold_n_o)
);
`endif // `ifdef USE_SPI_FLASH
 
initial
begin
$display("\nStarting RTL simulation of ml501 board %s test\n", `TEST_NAME_STRING);
`ifdef USE_SDRAM
$display("Using SDRAM - loading application from SPI flash memory\n");
`endif
 
`ifdef VCD
 
`ifdef ML501_MEMORY_DDR2
// #81263000; // DDR2 calibration completed
`endif
$display("VCD in %s\n", {`TEST_RESULTS_DIR,`TEST_NAME_STRING,".vcd"});
$dumpfile({`TEST_RESULTS_DIR,`TEST_NAME_STRING,".vcd"});
 
`ifdef VCD_DEPTH
$dumpvars(`VCD_DEPTH);
`else
$dumpvars(0);
`endif
`endif
end
 
`ifndef POST_SYNTHESIS_SIM
// Instantiate the monitor
or1200_monitor monitor();
`endif
// If we're using UART for printf output, include the
// UART decoder
`ifdef UART_PRINTF
// Define the UART's txt line for it to listen to
`define UART_TX_LINE uart0_stx_o
`define UART_BAUDRATE 115200
`include "uart_decoder.v"
`endif
endmodule // orpsoc_testbench
 
// Local Variables:
// verilog-library-directories:("." "../rtl" "../../../../bench/verilog")
// End:
/openrisc/trunk/orpsocv2/boards/xilinx/ml501/bench/WireDelay.v
0,0 → 1,123
//*****************************************************************************
// 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 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 : wiredly.v
// /___/ /\ Date Last Modified : $Date: 2008/12/23 14:26:00 $
// \ \ / \ Date Created : Thu Feb 21 2008
// \___\/\___\
//
// Device : Virtex-5
// Design Name : DDR2
// Description: This module provide
// the definition of a zero ohm component (A, B).
//
// The applications of this component include:
// . Normal operation of a jumper wire (data flowing in both directions)
//
// The component consists of 2 ports:
// . Port A: One side of the pass-through switch
// . Port B: The other side of the pass-through switch
 
// The model is sensitive to transactions on all ports. Once a
// transaction is detected, all other transactions are ignored
// for that simulation time (i.e. further transactions in that
// delta time are ignored).
//
// Model Limitations and Restrictions:
// Signals asserted on the ports of the error injector should not have
// transactions occuring in multiple delta times because the model
// is sensitive to transactions on port A, B ONLY ONCE during
// a simulation time. Thus, once fired, a process will
// not refire if there are multiple transactions occuring in delta times.
// This condition may occur in gate level simulations with
// ZERO delays because transactions may occur in multiple delta times.
//*****************************************************************************
 
`timescale 1ns / 1ps
 
module WireDelay # (
parameter Delay_g = 0,
parameter Delay_rd = 0
)
(
inout A,
inout B,
input reset
);
 
reg A_r;
reg B_r;
reg line_en;
 
assign A = A_r;
assign B = B_r;
 
always @(*) begin
if (!reset) begin
A_r <= 1'bz;
B_r <= 1'bz;
line_en <= 1'b0;
end else begin
if (line_en) begin
A_r <= #Delay_rd B;
B_r <= 1'bz;
end else begin
B_r <= #Delay_g A;
A_r <= 1'bz;
end
end
end
 
always @(A or B) begin
if (!reset) begin
line_en <= 1'b0;
end else if (A !== A_r) begin
line_en <= 1'b0;
end else if (B_r !== B) begin
line_en <= 1'b1;
end else begin
line_en <= line_en;
end
end
endmodule
/openrisc/trunk/orpsocv2/boards/xilinx/ml501/bench/ddr2_model_parameters.vh
0,0 → 1,385
/****************************************************************************************
*
* Disclaimer This software code and all associated documentation, comments or other
* of Warranty: information (collectively "Software") is provided "AS IS" without
* warranty of any kind. MICRON TECHNOLOGY, INC. ("MTI") EXPRESSLY
* DISCLAIMS ALL WARRANTIES EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
* TO, NONINFRINGEMENT OF THIRD PARTY RIGHTS, AND ANY IMPLIED WARRANTIES
* OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE. MTI DOES NOT
* WARRANT THAT THE SOFTWARE WILL MEET YOUR REQUIREMENTS, OR THAT THE
* OPERATION OF THE SOFTWARE WILL BE UNINTERRUPTED OR ERROR-FREE.
* FURTHERMORE, MTI DOES NOT MAKE ANY REPRESENTATIONS REGARDING THE USE OR
* THE RESULTS OF THE USE OF THE SOFTWARE IN TERMS OF ITS CORRECTNESS,
* ACCURACY, RELIABILITY, OR OTHERWISE. THE ENTIRE RISK ARISING OUT OF USE
* OR PERFORMANCE OF THE SOFTWARE REMAINS WITH YOU. IN NO EVENT SHALL MTI,
* ITS AFFILIATED COMPANIES OR THEIR SUPPLIERS BE LIABLE FOR ANY DIRECT,
* INDIRECT, CONSEQUENTIAL, INCIDENTAL, OR SPECIAL DAMAGES (INCLUDING,
* WITHOUT LIMITATION, DAMAGES FOR LOSS OF PROFITS, BUSINESS INTERRUPTION,
* OR LOSS OF INFORMATION) ARISING OUT OF YOUR USE OF OR INABILITY TO USE
* THE SOFTWARE, EVEN IF MTI HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGES. Because some jurisdictions prohibit the exclusion or
* limitation of liability for consequential or incidental damages, the
* above limitation may not apply to you.
*
* Copyright 2003 Micron Technology, Inc. All rights reserved.
*
****************************************************************************************/
 
// Parameters current with 512Mb datasheet rev N
 
// Timing parameters based on Speed Grade
 
// SYMBOL UNITS DESCRIPTION
 
 
`ifdef sg37E
parameter TCK_MIN = 3750; // tCK ps Minimum Clock Cycle Time
parameter TJIT_PER = 125; // tJIT(per) ps Period JItter
parameter TJIT_DUTY = 125; // tJIT(duty) ps Half Period Jitter
parameter TJIT_CC = 250; // tJIT(cc) ps Cycle to Cycle jitter
parameter TERR_2PER = 175; // tERR(nper) ps Accumulated Error (2-cycle)
parameter TERR_3PER = 225; // tERR(nper) ps Accumulated Error (3-cycle)
parameter TERR_4PER = 250; // tERR(nper) ps Accumulated Error (4-cycle)
parameter TERR_5PER = 250; // tERR(nper) ps Accumulated Error (5-cycle)
parameter TERR_N1PER = 350; // tERR(nper) ps Accumulated Error (6-10-cycle)
parameter TERR_N2PER = 450; // tERR(nper) ps Accumulated Error (11-50-cycle)
parameter TQHS = 400; // tQHS ps Data hold skew factor
parameter TAC = 500; // tAC ps DQ output access time from CK/CK#
parameter TDS = 100; // tDS ps DQ and DM input setup time relative to DQS
parameter TDH = 225; // tDH ps DQ and DM input hold time relative to DQS
parameter TDQSCK = 450; // tDQSCK ps DQS output access time from CK/CK#
parameter TDQSQ = 300; // tDQSQ ps DQS-DQ skew, DQS to last DQ valid, per group, per access
parameter TIS = 250; // tIS ps Input Setup Time
parameter TIH = 375; // tIH ps Input Hold Time
parameter TRC = 55000; // tRC ps Active to Active/Auto Refresh command time
parameter TRCD = 15000; // tRCD ps Active to Read/Write command time
parameter TWTR = 7500; // tWTR ps Write to Read command delay
parameter TRP = 15000; // tRP ps Precharge command period
parameter TRPA = 15000; // tRPA ps Precharge All period
parameter TXARDS = 6; // tXARDS tCK Exit low power active power down to a read command
parameter TXARD = 2; // tXARD tCK Exit active power down to a read command
parameter TXP = 2; // tXP tCK Exit power down to a non-read command
parameter TANPD = 3; // tANPD tCK ODT to power-down entry latency
parameter TAXPD = 8; // tAXPD tCK ODT power-down exit latency
parameter CL_TIME = 15000; // CL ps Minimum CAS Latency
`else // ------ ----- -----------
`ifdef sg187E
parameter TCK_MIN = 1875; // tCK ps Minimum Clock Cycle Time
parameter TJIT_PER = 90; // tJIT(per) ps Period JItter
parameter TJIT_DUTY = 75; // tJIT(duty) ps Half Period Jitter
parameter TJIT_CC = 180; // tJIT(cc) ps Cycle to Cycle jitter
parameter TERR_2PER = 132; // tERR(nper) ps Accumulated Error (2-cycle)
parameter TERR_3PER = 157; // tERR(nper) ps Accumulated Error (3-cycle)
parameter TERR_4PER = 175; // tERR(nper) ps Accumulated Error (4-cycle)
parameter TERR_5PER = 188; // tERR(nper) ps Accumulated Error (5-cycle)
parameter TERR_N1PER = 250; // tERR(nper) ps Accumulated Error (6-10-cycle)
parameter TERR_N2PER = 425; // tERR(nper) ps Accumulated Error (11-50-cycle)
parameter TQHS = 250; // tQHS ps Data hold skew factor
parameter TAC = 350; // tAC ps DQ output access time from CK/CK#
parameter TDS = 0; // tDS ps DQ and DM input setup time relative to DQS
parameter TDH = 75; // tDH ps DQ and DM input hold time relative to DQS
parameter TDQSCK = 300; // tDQSCK ps DQS output access time from CK/CK#
parameter TDQSQ = 175; // tDQSQ ps DQS-DQ skew, DQS to last DQ valid, per group, per access
parameter TIS = 125; // tIS ps Input Setup Time
parameter TIH = 200; // tIH ps Input Hold Time
parameter TRC = 54000; // tRC ps Active to Active/Auto Refresh command time
parameter TRCD = 13125; // tRCD ps Active to Read/Write command time
parameter TWTR = 7500; // tWTR ps Write to Read command delay
parameter TRP = 13125; // tRP ps Precharge command period
parameter TRPA = 13125; // tRPA ps Precharge All period
parameter TXARDS = 10; // tXARDS tCK Exit low power active power down to a read command
parameter TXARD = 3; // tXARD tCK Exit active power down to a read command
parameter TXP = 3; // tXP tCK Exit power down to a non-read command
parameter TANPD = 4; // tANPD tCK ODT to power-down entry latency
parameter TAXPD = 11; // tAXPD tCK ODT power-down exit latency
parameter CL_TIME = 13125; // CL ps Minimum CAS Latency
`else `ifdef sg25E
parameter TCK_MIN = 2500; // tCK ps Minimum Clock Cycle Time
parameter TJIT_PER = 100; // tJIT(per) ps Period JItter
parameter TJIT_DUTY = 100; // tJIT(duty) ps Half Period Jitter
parameter TJIT_CC = 200; // tJIT(cc) ps Cycle to Cycle jitter
parameter TERR_2PER = 150; // tERR(nper) ps Accumulated Error (2-cycle)
parameter TERR_3PER = 175; // tERR(nper) ps Accumulated Error (3-cycle)
parameter TERR_4PER = 200; // tERR(nper) ps Accumulated Error (4-cycle)
parameter TERR_5PER = 200; // tERR(nper) ps Accumulated Error (5-cycle)
parameter TERR_N1PER = 300; // tERR(nper) ps Accumulated Error (6-10-cycle)
parameter TERR_N2PER = 450; // tERR(nper) ps Accumulated Error (11-50-cycle)
parameter TQHS = 300; // tQHS ps Data hold skew factor
parameter TAC = 400; // tAC ps DQ output access time from CK/CK#
parameter TDS = 50; // tDS ps DQ and DM input setup time relative to DQS
parameter TDH = 125; // tDH ps DQ and DM input hold time relative to DQS
parameter TDQSCK = 350; // tDQSCK ps DQS output access time from CK/CK#
parameter TDQSQ = 200; // tDQSQ ps DQS-DQ skew, DQS to last DQ valid, per group, per access
parameter TIS = 175; // tIS ps Input Setup Time
parameter TIH = 250; // tIH ps Input Hold Time
parameter TRC = 55000; // tRC ps Active to Active/Auto Refresh command time
parameter TRCD = 12500; // tRCD ps Active to Read/Write command time
parameter TWTR = 7500; // tWTR ps Write to Read command delay
parameter TRP = 12500; // tRP ps Precharge command period
parameter TRPA = 12500; // tRPA ps Precharge All period
parameter TXARDS = 8; // tXARDS tCK Exit low power active power down to a read command
parameter TXARD = 2; // tXARD tCK Exit active power down to a read command
parameter TXP = 2; // tXP tCK Exit power down to a non-read command
parameter TANPD = 3; // tANPD tCK ODT to power-down entry latency
parameter TAXPD = 10; // tAXPD tCK ODT power-down exit latency
parameter CL_TIME = 12500; // CL ps Minimum CAS Latency
`else `ifdef sg25
parameter TCK_MIN = 2500; // tCK ps Minimum Clock Cycle Time
parameter TJIT_PER = 100; // tJIT(per) ps Period JItter
parameter TJIT_DUTY = 100; // tJIT(duty) ps Half Period Jitter
parameter TJIT_CC = 200; // tJIT(cc) ps Cycle to Cycle jitter
parameter TERR_2PER = 150; // tERR(nper) ps Accumulated Error (2-cycle)
parameter TERR_3PER = 175; // tERR(nper) ps Accumulated Error (3-cycle)
parameter TERR_4PER = 200; // tERR(nper) ps Accumulated Error (4-cycle)
parameter TERR_5PER = 200; // tERR(nper) ps Accumulated Error (5-cycle)
parameter TERR_N1PER = 300; // tERR(nper) ps Accumulated Error (6-10-cycle)
parameter TERR_N2PER = 450; // tERR(nper) ps Accumulated Error (11-50-cycle)
parameter TQHS = 300; // tQHS ps Data hold skew factor
parameter TAC = 400; // tAC ps DQ output access time from CK/CK#
parameter TDS = 50; // tDS ps DQ and DM input setup time relative to DQS
parameter TDH = 125; // tDH ps DQ and DM input hold time relative to DQS
parameter TDQSCK = 350; // tDQSCK ps DQS output access time from CK/CK#
parameter TDQSQ = 200; // tDQSQ ps DQS-DQ skew, DQS to last DQ valid, per group, per access
parameter TIS = 175; // tIS ps Input Setup Time
parameter TIH = 250; // tIH ps Input Hold Time
parameter TRC = 55000; // tRC ps Active to Active/Auto Refresh command time
parameter TRCD = 15000; // tRCD ps Active to Read/Write command time
parameter TWTR = 7500; // tWTR ps Write to Read command delay
parameter TRP = 15000; // tRP ps Precharge command period
parameter TRPA = 15000; // tRPA ps Precharge All period
parameter TXARDS = 8; // tXARDS tCK Exit low power active power down to a read command
parameter TXARD = 2; // tXARD tCK Exit active power down to a read command
parameter TXP = 2; // tXP tCK Exit power down to a non-read command
parameter TANPD = 3; // tANPD tCK ODT to power-down entry latency
parameter TAXPD = 10; // tAXPD tCK ODT power-down exit latency
parameter CL_TIME = 15000; // CL ps Minimum CAS Latency
`else `ifdef sg3E
parameter TCK_MIN = 3000; // tCK ps Minimum Clock Cycle Time
parameter TJIT_PER = 125; // tJIT(per) ps Period JItter
parameter TJIT_DUTY = 125; // tJIT(duty) ps Half Period Jitter
parameter TJIT_CC = 250; // tJIT(cc) ps Cycle to Cycle jitter
parameter TERR_2PER = 175; // tERR(nper) ps Accumulated Error (2-cycle)
parameter TERR_3PER = 225; // tERR(nper) ps Accumulated Error (3-cycle)
parameter TERR_4PER = 250; // tERR(nper) ps Accumulated Error (4-cycle)
parameter TERR_5PER = 250; // tERR(nper) ps Accumulated Error (5-cycle)
parameter TERR_N1PER = 350; // tERR(nper) ps Accumulated Error (6-10-cycle)
parameter TERR_N2PER = 450; // tERR(nper) ps Accumulated Error (11-50-cycle)
parameter TQHS = 340; // tQHS ps Data hold skew factor
parameter TAC = 450; // tAC ps DQ output access time from CK/CK#
parameter TDS = 100; // tDS ps DQ and DM input setup time relative to DQS
parameter TDH = 175; // tDH ps DQ and DM input hold time relative to DQS
parameter TDQSCK = 400; // tDQSCK ps DQS output access time from CK/CK#
parameter TDQSQ = 240; // tDQSQ ps DQS-DQ skew, DQS to last DQ valid, per group, per access
parameter TIS = 200; // tIS ps Input Setup Time
parameter TIH = 275; // tIH ps Input Hold Time
parameter TRC = 54000; // tRC ps Active to Active/Auto Refresh command time
parameter TRCD = 12000; // tRCD ps Active to Read/Write command time
parameter TWTR = 7500; // tWTR ps Write to Read command delay
parameter TRP = 12000; // tRP ps Precharge command period
parameter TRPA = 12000; // tRPA ps Precharge All period
parameter TXARDS = 7; // tXARDS tCK Exit low power active power down to a read command
parameter TXARD = 2; // tXARD tCK Exit active power down to a read command
parameter TXP = 2; // tXP tCK Exit power down to a non-read command
parameter TANPD = 3; // tANPD tCK ODT to power-down entry latency
parameter TAXPD = 8; // tAXPD tCK ODT power-down exit latency
parameter CL_TIME = 12000; // CL ps Minimum CAS Latency
`else `ifdef sg3
parameter TCK_MIN = 3000; // tCK ps Minimum Clock Cycle Time
parameter TJIT_PER = 125; // tJIT(per) ps Period JItter
parameter TJIT_DUTY = 125; // tJIT(duty) ps Half Period Jitter
parameter TJIT_CC = 250; // tJIT(cc) ps Cycle to Cycle jitter
parameter TERR_2PER = 175; // tERR(nper) ps Accumulated Error (2-cycle)
parameter TERR_3PER = 225; // tERR(nper) ps Accumulated Error (3-cycle)
parameter TERR_4PER = 250; // tERR(nper) ps Accumulated Error (4-cycle)
parameter TERR_5PER = 250; // tERR(nper) ps Accumulated Error (5-cycle)
parameter TERR_N1PER = 350; // tERR(nper) ps Accumulated Error (6-10-cycle)
parameter TERR_N2PER = 450; // tERR(nper) ps Accumulated Error (11-50-cycle)
parameter TQHS = 340; // tQHS ps Data hold skew factor
parameter TAC = 450; // tAC ps DQ output access time from CK/CK#
parameter TDS = 100; // tDS ps DQ and DM input setup time relative to DQS
parameter TDH = 175; // tDH ps DQ and DM input hold time relative to DQS
parameter TDQSCK = 400; // tDQSCK ps DQS output access time from CK/CK#
parameter TDQSQ = 240; // tDQSQ ps DQS-DQ skew, DQS to last DQ valid, per group, per access
parameter TIS = 200; // tIS ps Input Setup Time
parameter TIH = 275; // tIH ps Input Hold Time
parameter TRC = 55000; // tRC ps Active to Active/Auto Refresh command time
parameter TRCD = 15000; // tRCD ps Active to Read/Write command time
parameter TWTR = 7500; // tWTR ps Write to Read command delay
parameter TRP = 15000; // tRP ps Precharge command period
parameter TRPA = 15000; // tRPA ps Precharge All period
parameter TXARDS = 7; // tXARDS tCK Exit low power active power down to a read command
parameter TXARD = 2; // tXARD tCK Exit active power down to a read command
parameter TXP = 2; // tXP tCK Exit power down to a non-read command
parameter TANPD = 3; // tANPD tCK ODT to power-down entry latency
parameter TAXPD = 8; // tAXPD tCK ODT power-down exit latency
parameter CL_TIME = 15000; // CL ps Minimum CAS Latency
`else `define sg5E
parameter TCK_MIN = 5000; // tCK ps Minimum Clock Cycle Time
parameter TJIT_PER = 125; // tJIT(per) ps Period JItter
parameter TJIT_DUTY = 150; // tJIT(duty) ps Half Period Jitter
parameter TJIT_CC = 250; // tJIT(cc) ps Cycle to Cycle jitter
parameter TERR_2PER = 175; // tERR(nper) ps Accumulated Error (2-cycle)
parameter TERR_3PER = 225; // tERR(nper) ps Accumulated Error (3-cycle)
parameter TERR_4PER = 250; // tERR(nper) ps Accumulated Error (4-cycle)
parameter TERR_5PER = 250; // tERR(nper) ps Accumulated Error (5-cycle)
parameter TERR_N1PER = 350; // tERR(nper) ps Accumulated Error (6-10-cycle)
parameter TERR_N2PER = 450; // tERR(nper) ps Accumulated Error (11-50-cycle)
parameter TQHS = 450; // tQHS ps Data hold skew factor
parameter TAC = 600; // tAC ps DQ output access time from CK/CK#
parameter TDS = 150; // tDS ps DQ and DM input setup time relative to DQS
parameter TDH = 275; // tDH ps DQ and DM input hold time relative to DQS
parameter TDQSCK = 500; // tDQSCK ps DQS output access time from CK/CK#
parameter TDQSQ = 350; // tDQSQ ps DQS-DQ skew, DQS to last DQ valid, per group, per access
parameter TIS = 350; // tIS ps Input Setup Time
parameter TIH = 475; // tIH ps Input Hold Time
parameter TRC = 55000; // tRC ps Active to Active/Auto Refresh command time
parameter TRCD = 15000; // tRCD ps Active to Read/Write command time
parameter TWTR = 10000; // tWTR ps Write to Read command delay
parameter TRP = 15000; // tRP ps Precharge command period
parameter TRPA = 15000; // tRPA ps Precharge All period
parameter TXARDS = 6; // tXARDS tCK Exit low power active power down to a read command
parameter TXARD = 2; // tXARD tCK Exit active power down to a read command
parameter TXP = 2; // tXP tCK Exit power down to a non-read command
parameter TANPD = 3; // tANPD tCK ODT to power-down entry latency
parameter TAXPD = 8; // tAXPD tCK ODT power-down exit latency
parameter CL_TIME = 15000; // CL ps Minimum CAS Latency
`endif `endif `endif `endif `endif `endif
 
`ifdef x16
`ifdef sg187E
parameter TFAW = 45000; // tFAW ps Four Bank Activate window
`else `ifdef sg25E
parameter TFAW = 45000; // tFAW ps Four Bank Activate window
`else `ifdef sg25
parameter TFAW = 45000; // tFAW ps Four Bank Activate window
`else // sg3E, sg3, sg37E, sg5E
parameter TFAW = 50000; // tFAW ps Four Bank Activate window
`endif `endif `endif
`else // x4, x8
`ifdef sg187E
parameter TFAW = 35000; // tFAW ps Four Bank Activate window
`else `ifdef sg25E
parameter TFAW = 35000; // tFAW ps Four Bank Activate window
`else `ifdef sg25
parameter TFAW = 35000; // tFAW ps Four Bank Activate window
`else // sg3E, sg3, sg37E, sg5E
parameter TFAW = 37500; // tFAW ps Four Bank Activate window
`endif `endif `endif
`endif
 
// Timing Parameters
 
// Mode Register
parameter AL_MIN = 0; // AL tCK Minimum Additive Latency
parameter AL_MAX = 6; // AL tCK Maximum Additive Latency
parameter CL_MIN = 3; // CL tCK Minimum CAS Latency
parameter CL_MAX = 7; // CL tCK Maximum CAS Latency
parameter WR_MIN = 2; // WR tCK Minimum Write Recovery
parameter WR_MAX = 8; // WR tCK Maximum Write Recovery
parameter BL_MIN = 4; // BL tCK Minimum Burst Length
parameter BL_MAX = 8; // BL tCK Minimum Burst Length
// Clock
parameter TCK_MAX = 8000; // tCK ps Maximum Clock Cycle Time
parameter TCH_MIN = 0.48; // tCH tCK Minimum Clock High-Level Pulse Width
parameter TCH_MAX = 0.52; // tCH tCK Maximum Clock High-Level Pulse Width
parameter TCL_MIN = 0.48; // tCL tCK Minimum Clock Low-Level Pulse Width
parameter TCL_MAX = 0.52; // tCL tCK Maximum Clock Low-Level Pulse Width
// Data
parameter TLZ = TAC; // tLZ ps Data-out low-impedance window from CK/CK#
parameter THZ = TAC; // tHZ ps Data-out high impedance window from CK/CK#
parameter TDIPW = 0.35; // tDIPW tCK DQ and DM input Pulse Width
// Data Strobe
parameter TDQSH = 0.35; // tDQSH tCK DQS input High Pulse Width
parameter TDQSL = 0.35; // tDQSL tCK DQS input Low Pulse Width
parameter TDSS = 0.20; // tDSS tCK DQS falling edge to CLK rising (setup time)
parameter TDSH = 0.20; // tDSH tCK DQS falling edge from CLK rising (hold time)
parameter TWPRE = 0.35; // tWPRE tCK DQS Write Preamble
parameter TWPST = 0.40; // tWPST tCK DQS Write Postamble
parameter TDQSS = 0.25; // tDQSS tCK Rising clock edge to DQS/DQS# latching transition
// Command and Address
parameter TIPW = 0.6; // tIPW tCK Control and Address input Pulse Width
parameter TCCD = 2; // tCCD tCK Cas to Cas command delay
parameter TRAS_MIN = 40000; // tRAS ps Minimum Active to Precharge command time
parameter TRAS_MAX =70000000; // tRAS ps Maximum Active to Precharge command time
parameter TRTP = 7500; // tRTP ps Read to Precharge command delay
parameter TWR = 15000; // tWR ps Write recovery time
parameter TMRD = 2; // tMRD tCK Load Mode Register command cycle time
parameter TDLLK = 200; // tDLLK tCK DLL locking time
// Refresh
parameter TRFC_MIN = 105000; // tRFC ps Refresh to Refresh Command interval minimum value
parameter TRFC_MAX =70000000; // tRFC ps Refresh to Refresh Command Interval maximum value
// Self Refresh
parameter TXSNR = TRFC_MIN + 10000; // tXSNR ps Exit self refesh to a non-read command
parameter TXSRD = 200; // tXSRD tCK Exit self refresh to a read command
parameter TISXR = TIS; // tISXR ps CKE setup time during self refresh exit.
// ODT
parameter TAOND = 2; // tAOND tCK ODT turn-on delay
parameter TAOFD = 2.5; // tAOFD tCK ODT turn-off delay
parameter TAONPD = 2000; // tAONPD ps ODT turn-on (precharge power-down mode)
parameter TAOFPD = 2000; // tAOFPD ps ODT turn-off (precharge power-down mode)
parameter TMOD = 12000; // tMOD ps ODT enable in EMR to ODT pin transition
// Power Down
parameter TCKE = 3; // tCKE tCK CKE minimum high or low pulse width
 
// Size Parameters based on Part Width
 
`ifdef x4
parameter ADDR_BITS = 14; // Address Bits
parameter ROW_BITS = 14; // Number of Address bits
parameter COL_BITS = 11; // Number of Column bits
parameter DM_BITS = 1; // Number of Data Mask bits
parameter DQ_BITS = 4; // Number of Data bits
parameter DQS_BITS = 1; // Number of Dqs bits
parameter TRRD = 7500; // tRRD Active bank a to Active bank b command time
`else `ifdef x8
parameter ADDR_BITS = 14; // Address Bits
parameter ROW_BITS = 14; // Number of Address bits
parameter COL_BITS = 10; // Number of Column bits
parameter DM_BITS = 1; // Number of Data Mask bits
parameter DQ_BITS = 8; // Number of Data bits
parameter DQS_BITS = 1; // Number of Dqs bits
parameter TRRD = 7500; // tRRD Active bank a to Active bank b command time
`else `define x16
parameter ADDR_BITS = 13; // Address Bits
parameter ROW_BITS = 13; // Number of Address bits
parameter COL_BITS = 10; // Number of Column bits
parameter DM_BITS = 2; // Number of Data Mask bits
parameter DQ_BITS = 16; // Number of Data bits
parameter DQS_BITS = 2; // Number of Dqs bits
parameter TRRD = 10000; // tRRD Active bank a to Active bank b command time
`endif `endif
 
`ifdef QUAD_RANK
`define DUAL_RANK // also define DUAL_RANK
parameter CS_BITS = 4; // Number of Chip Select Bits
parameter RANKS = 4; // Number of Chip Select Bits
`else `ifdef DUAL_RANK
parameter CS_BITS = 2; // Number of Chip Select Bits
parameter RANKS = 2; // Number of Chip Select Bits
`else
parameter CS_BITS = 2; // Number of Chip Select Bits
parameter RANKS = 1; // Number of Chip Select Bits
`endif `endif
 
// Size Parameters
parameter BA_BITS = 2; // Set this parmaeter to control how many Bank Address bits
parameter MEM_BITS = 10; // Number of write data bursts can be stored in memory. The default is 2^10=1024.
parameter AP = 10; // the address bit that controls auto-precharge and precharge-all
parameter BL_BITS = 3; // the number of bits required to count to MAX_BL
parameter BO_BITS = 2; // the number of Burst Order Bits
 
// Simulation parameters
parameter STOP_ON_ERROR = 1; // If set to 1, the model will halt on command sequence/major errors
parameter DEBUG = 0; // Turn on Debug messages
parameter BUS_DELAY = 0; // delay in nanoseconds
parameter RANDOM_OUT_DELAY = 0; // If set to 1, the model will put a random amount of delay on DQ/DQS during reads
parameter RANDOM_SEED = 711689044; //seed value for random generator.
 
parameter RDQSEN_PRE = 2; // DQS driving time prior to first read strobe
parameter RDQSEN_PST = 1; // DQS driving time after last read strobe
parameter RDQS_PRE = 2; // DQS low time prior to first read strobe
parameter RDQS_PST = 1; // DQS low time after last valid read strobe
parameter RDQEN_PRE = 0; // DQ/DM driving time prior to first read data
parameter RDQEN_PST = 0; // DQ/DM driving time after last read data
parameter WDQS_PRE = 1; // DQS half clock periods prior to first write strobe
parameter WDQS_PST = 1; // DQS half clock periods after last valid write strobe
/openrisc/trunk/orpsocv2/boards/xilinx/ml501/bench/ml501_testbench_defines.v
0,0 → 1,60
//////////////////////////////////////////////////////////////////////
//// ////
//// ORPSoC on Xilinx ml501 Testbench Defines ////
//// ////
//// Description ////
//// ORPSoC testbench defines file ////
//// ////
//// To Do: ////
//// - ////
//// ////
//// Author(s): ////
//// - jb, jb@orsoc.se ////
//// ////
//// ////
//////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2009 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 ////
//// ////
//////////////////////////////////////////////////////////////////////
 
// 100MHz board clock
// Is an FPGA-targetted sim for Xilinx stuff, meaning we'll be including
// glbl.v, meaning timescale will be 1ps/1ps, so clock period must be in ps
`define CLOCK_PERIOD 10_000
`define CLOCK_RATE 100_000_000
 
// Period for 125MHz clock is 8ns
`define ETH_CLK_PERIOD 8
 
// The ORPSoC tests makefile should generate the test_define.v file in
// the sim/run directory.
`ifdef TEST_DEFINE_FILE
`include "test_define.v"
`else
`define TEST_NAME_STRING "unspecified-test"
`define TEST_RESULTS_DIR "./"
`endif
 
`undef UART_LOG_TX
/openrisc/trunk/orpsocv2/boards/xilinx/ml501/rtl/ml501_gpio.v
0,0 → 1,125
//////////////////////////////////////////////////////////////////////
//// ////
//// Xilinx ML501 GPIO controller with Wishbone Interface ////
//// ////
//// Description ////
//// Wishbone interface to simple GPIO registers. ////
//// ////
//// 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 ////
//// ////
//////////////////////////////////////////////////////////////////////
module ml501_gpio (adr_i, dat_i, dat_o, sel_i, stb_i, cyc_i, we_i, ack_o, clk, rst, gpio );
parameter gpio_width = 26;
// WB interface
input [2:0] adr_i;
output [31:0] dat_o;
input [31:0] dat_i;
input [3:0] sel_i;
input stb_i;
input cyc_i;
input we_i;
output reg ack_o;
input clk;
input rst;
inout [gpio_width - 1 : 0] gpio;
wire [gpio_width -1 : 0] gpio_i;
reg [31:0] gpio_o, gpio_o_r, gpio_dir;
 
reg [gpio_width - 1 : 0] dat_o_r;
 
assign dat_o[gpio_width-1: 0] = dat_o_r;
assign dat_o[31:gpio_width] = 0;
always @(posedge clk)
if (rst)
gpio_dir <= 0; // All in
else
if (stb_i & cyc_i & we_i & adr_i[2])
begin
if (sel_i[3]) gpio_dir[31:24] <= dat_i[31:24];
if (sel_i[2]) gpio_dir[23:16] <= dat_i[23:16];
if (sel_i[1]) gpio_dir[15:8] <= dat_i[15:8];
if (sel_i[0]) gpio_dir[7:0] <= dat_i[7:0];
end
 
always @(posedge clk)
if (rst)
ack_o <= 0;
else if (stb_i & cyc_i & !ack_o)
ack_o <= 1;
else
ack_o <= 0;
always @(posedge clk)
if (rst)
gpio_o <= 0;
else if (stb_i & cyc_i & we_i & !adr_i[2])
begin
if (sel_i[3]) gpio_o[31:24] <= dat_i[31:24];
if (sel_i[2]) gpio_o[23:16] <= dat_i[23:16];
if (sel_i[1]) gpio_o[15:8] <= dat_i[15:8];
if (sel_i[0]) gpio_o[7:0] <= dat_i[7:0];
end
genvar i;
generate
for (i=0; i<gpio_width; i=i+1) begin: gpio_tribuf_gen
always @(posedge clk)
if (stb_i & cyc_i & !we_i)
if (!adr_i[2])
dat_o_r[i] <= gpio_dir[i] ? gpio_o_r[i] : gpio_i[i];
else
dat_o_r[i] <= gpio_dir[i];
// Xilinx primitive
IOBUF U
(
// Outputs
.O (gpio_i[i]),
// Inouts
.IO (gpio[i]),
// Inputs
.I (gpio_o[i]),
.T (!gpio_dir[i]));
end // block: gpio_tribuf_gen
endgenerate
 
endmodule // ml501_gpio
 
/openrisc/trunk/orpsocv2/boards/xilinx/ml501/rtl/eth_defines.v
0,0 → 1,337
//////////////////////////////////////////////////////////////////////
//// ////
//// eth_defines.v ////
//// ////
//// This file is part of the Ethernet IP core project ////
//// http://www.opencores.org/projects/ethmac/ ////
//// ////
//// Author(s): ////
//// - Igor Mohor (igorM@opencores.org) ////
//// ////
//// All additional information is available in the Readme.txt ////
//// file. ////
//// ////
//////////////////////////////////////////////////////////////////////
//// ////
//// 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 ////
//// ////
//////////////////////////////////////////////////////////////////////
//
// CVS Revision History
//
// $Log: eth_defines.v,v $
// Revision 1.34 2005/02/21 12:48:06 igorm
// Warning fixes.
//
// Revision 1.33 2003/11/12 18:24:58 tadejm
// WISHBONE slave changed and tested from only 32-bit accesss to byte access.
//
// Revision 1.32 2003/10/17 07:46:13 markom
// mbist signals updated according to newest convention
//
// Revision 1.31 2003/08/14 16:42:58 simons
// Artisan ram instance added.
//
// Revision 1.30 2003/06/13 11:55:37 mohor
// Define file in eth_cop.v is changed to eth_defines.v. Some defines were
// moved from tb_eth_defines.v to eth_defines.v.
//
// Revision 1.29 2002/11/19 18:13:49 mohor
// r_MiiMRst is not used for resetting the MIIM module. wb_rst used instead.
//
// Revision 1.28 2002/11/15 14:27:15 mohor
// Since r_Rst bit is not used any more, default value is changed to 0xa000.
//
// Revision 1.27 2002/11/01 18:19:34 mohor
// Defines fixed to use generic RAM by default.
//
// Revision 1.26 2002/10/24 18:53:03 mohor
// fpga define added.
//
// Revision 1.3 2002/10/11 16:57:54 igorm
// eth_defines.v tagged with rel_5 used.
//
// Revision 1.25 2002/10/10 16:47:44 mohor
// Defines changed to have ETH_ prolog.
// ETH_WISHBONE_B# define added.
//
// Revision 1.24 2002/10/10 16:33:11 mohor
// Bist added.
//
// Revision 1.23 2002/09/23 18:22:48 mohor
// Virtual Silicon RAM might be used in the ASIC implementation of the ethernet
// core.
//
// Revision 1.22 2002/09/04 18:36:49 mohor
// Defines for control registers added (ETH_TXCTRL and ETH_RXCTRL).
//
// Revision 1.21 2002/08/16 22:09:47 mohor
// Defines for register width added. mii_rst signal in MIIMODER register
// changed.
//
// Revision 1.20 2002/08/14 19:31:48 mohor
// Register TX_BD_NUM is changed so it contains value of the Tx buffer descriptors. No
// need to multiply or devide any more.
//
// Revision 1.19 2002/07/23 15:28:31 mohor
// Ram , used for BDs changed from generic_spram to eth_spram_256x32.
//
// Revision 1.18 2002/05/03 10:15:50 mohor
// Outputs registered. Reset changed for eth_wishbone module.
//
// Revision 1.17 2002/04/24 08:52:19 mohor
// Compiler directives added. Tx and Rx fifo size incremented. A "late collision"
// bug fixed.
//
// Revision 1.16 2002/03/19 12:53:29 mohor
// Some defines that are used in testbench only were moved to tb_eth_defines.v
// file.
//
// Revision 1.15 2002/02/26 16:11:32 mohor
// Number of interrupts changed
//
// Revision 1.14 2002/02/16 14:03:44 mohor
// Registered trimmed. Unused registers removed.
//
// Revision 1.13 2002/02/16 13:06:33 mohor
// EXTERNAL_DMA used instead of WISHBONE_DMA.
//
// Revision 1.12 2002/02/15 10:58:31 mohor
// Changed that were lost with last update put back to the file.
//
// Revision 1.11 2002/02/14 20:19:41 billditt
// Modified for Address Checking,
// addition of eth_addrcheck.v
//
// Revision 1.10 2002/02/12 17:01:19 mohor
// HASH0 and HASH1 registers added.
 
// Revision 1.9 2002/02/08 16:21:54 mohor
// Rx status is written back to the BD.
//
// Revision 1.8 2002/02/05 16:44:38 mohor
// Both rx and tx part are finished. Tested with wb_clk_i between 10 and 200
// MHz. Statuses, overrun, control frame transmission and reception still need
// to be fixed.
//
// Revision 1.7 2002/01/23 10:28:16 mohor
// Link in the header changed.
//
// Revision 1.6 2001/12/05 15:00:16 mohor
// RX_BD_NUM changed to TX_BD_NUM (holds number of TX descriptors
// instead of the number of RX descriptors).
//
// Revision 1.5 2001/12/05 10:21:37 mohor
// ETH_RX_BD_ADR register deleted. ETH_RX_BD_NUM is used instead.
//
// Revision 1.4 2001/11/13 14:23:56 mohor
// Generic memory model is used. Defines are changed for the same reason.
//
// Revision 1.3 2001/10/18 12:07:11 mohor
// Status signals changed, Adress decoding changed, interrupt controller
// added.
//
// Revision 1.2 2001/09/24 15:02:56 mohor
// Defines changed (All precede with ETH_). Small changes because some
// tools generate warnings when two operands are together. Synchronization
// between two clocks domains in eth_wishbonedma.v is changed (due to ASIC
// demands).
//
// Revision 1.1 2001/08/06 14:44:29 mohor
// A define FPGA added to select between Artisan RAM (for ASIC) and Block Ram (For Virtex).
// Include files fixed to contain no path.
// File names and module names changed ta have a eth_ prologue in the name.
// File eth_timescale.v is used to define timescale
// All pin names on the top module are changed to contain _I, _O or _OE at the end.
// Bidirectional signal MDIO is changed to three signals (Mdc_O, Mdi_I, Mdo_O
// and Mdo_OE. The bidirectional signal must be created on the top level. This
// is done due to the ASIC tools.
//
// Revision 1.1 2001/07/30 21:23:42 mohor
// Directory structure changed. Files checked and joind together.
//
//
//
//
//
 
 
 
//`define ETH_BIST // Bist for usage with Virtual Silicon RAMS
 
`define ETH_MBIST_CTRL_WIDTH 3 // width of MBIST control bus
 
// 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_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_CNT_WIDTH 5
//`define ETH_TX_FIFO_DEPTH 16
// Settings for TX FIFO buffer for a while ethernet packet (1500 bytes)
`define ETH_TX_FIFO_CNT_WIDTH 9
`define ETH_TX_FIFO_DEPTH 375
`define ETH_TX_FIFO_DATA_WIDTH 32
 
// Settings for RX FIFO
`define ETH_RX_FIFO_CNT_WIDTH 5
`define ETH_RX_FIFO_DEPTH 16
`define ETH_RX_FIFO_DATA_WIDTH 32
 
// Burst length
`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
 
// WISHBONE interface is Revision B3 compliant (uncomment when needed)
`define ETH_WISHBONE_B3
/openrisc/trunk/orpsocv2/boards/xilinx/ml501/rtl/ml501_mc.v
0,0 → 1,294
//////////////////////////////////////////////////////////////////////
//// ////
//// Xilinx ML501 Memory controller Wishbone Interface ////
//// ////
//// Description ////
//// Module which can instantiate the different external memory ////
//// control modules, as well as the internal BRAMS. ////
//// ////
//// To Do: ////
//// Fix the addressing (letting internal SRAMs take lowest ////
//// addresses, followed by next biggest memory server, ect) ////
//// ////
//// 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 ////
//// ////
//////////////////////////////////////////////////////////////////////
/* Memory and memory control module for ml501 board */
`include "ml501_defines.v"
module ml501_mc
(
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,
`ifdef ML501_MEMORY_SSRAM
output sram_clk,
input sram_clk_fb,
output [21:1] sram_addr,
inout [31:0] sram_dq_io,
output sram_ce_l,
output sram_oe_l,
output sram_we_l,
output [3:0] sram_bw_l,
output sram_adv_ld_l,
output sram_mode,
`endif // `ifdef ML501_MEMORY_SSRAM
 
`ifdef ML501_MEMORY_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,
 
input ddr2_if_clk,
`endif // `ifdef ML501_MEMORY_DDR2
input clk_200,
input wb_clk,
input wb_rst);
 
`ifdef ML501_MEMORY_STARTUP
parameter startup_size = `ML501_MEMORY_STARTUP_ADDR_SPAN;
`else
parameter startup_size = 0;
`endif
wire [31:0] wbs_strtup_dat_o;
wire [31:0] wbs_strtup_dat_i;
wire [31:0] wbs_strtup_adr_i;
wire [3:0] wbs_strtup_sel_i;
wire wbs_strtup_stb_i;
wire wbs_strtup_cyc_i;
wire wbs_strtup_ack_o;
parameter wbs_strtup_err_o = 1'b0;
 
wire [31:0] wbs_mc_dat_o;
wire [31:0] wbs_mc_dat_i;
wire [31:0] wbs_mc_adr_i;
wire [3:0] wbs_mc_sel_i;
wire [2:0] wbs_mc_cti_i;
wire wbs_mc_stb_i;
wire wbs_mc_cyc_i;
wire wbs_mc_ack_o;
parameter wbs_mc_err_o = 1'b0;
 
wire mem_sel;
 
// In to startup memory
assign wbs_strtup_adr_i = wb_adr_i;
assign wbs_strtup_dat_i = wb_dat_i;
assign wbs_strtup_sel_i = wb_sel_i;
assign wbs_strtup_cyc_i = wb_cyc_i;
assign wbs_strtup_we_i = wb_we_i;
 
// In to larger memory controller
assign wbs_mc_adr_i = wb_adr_i;
assign wbs_mc_dat_i = wb_dat_i;
assign wbs_mc_sel_i = wb_sel_i;
assign wbs_mc_cyc_i = wb_cyc_i;
assign wbs_mc_we_i = wb_we_i;
assign wbs_mc_cti_i = 0;
 
assign mem_sel = ( wb_adr_i >= startup_size);
// Assign signals according to which memory should be used
assign wbs_strtup_stb_i = mem_sel ? 0 : wb_stb_i;
assign wbs_mc_stb_i = mem_sel ? wb_stb_i : 0;
assign wb_ack_o = mem_sel ? wbs_mc_ack_o : wbs_strtup_ack_o;
assign wb_dat_o = mem_sel ? wbs_mc_dat_o : wbs_strtup_dat_o;
 
`ifdef ML501_MEMORY_STARTUP
/* On-chip startup RAM */
ml501_startup ml501_startup0
(
.wb_adr_i(wbs_strtup_adr_i[11:2]),
.wb_stb_i(wbs_strtup_stb_i),
.wb_cyc_i(wbs_strtup_cyc_i),
.wb_we_i(wbs_strtup_we_i),
.wb_sel_i(wbs_strtup_sel_i),
.wb_dat_o(wbs_strtup_dat_o),
.wb_dat_i(wbs_strtup_dat_i),
.wb_ack_o(wbs_strtup_ack_o),
.wb_clk(wb_clk),
.wb_rst(wb_rst)
);
defparam ml501_startup0.mem_span = startup_size;
`else // !`ifdef ML501_MEMORY_STARTUP
assign wbs_strtup_dat_o = 0;
assign wb_strtup_ack_o = 0;
`endif // !`ifdef ML501_MEMORY_STARTUP
`ifdef ML501_MEMORY_ONCHIP
parameter ram_wb_dat_width = 32;
// From board defines
parameter ram_wb_adr_width = `ML501_MEMORY_ONCHIP_ADDRESS_WIDTH;
parameter ram_wb_mem_size = ((`ML501_MEMORY_ONCHIP_SIZE_BYTES)/4);
 
ram_wb
#
(
.dat_width(ram_wb_dat_width),
.adr_width(ram_wb_adr_width),
.mem_size(ram_wb_mem_size)
)
ram_wb0
(
.dat_i(wbs_mc_dat_i),
.dat_o(wbs_mc_dat_o),
.sel_i(wbs_mc_sel_i),
.adr_i(wbs_mc_adr_i[ram_wb_adr_width-1:2]),
.we_i (wbs_mc_we_i),
.cti_i(wbs_mc_cti_i),
.stb_i(wbs_mc_stb_i),
.cyc_i(wbs_mc_cyc_i),
.ack_o(wbs_mc_ack_o),
.clk_i(wb_clk),
.rst_i(wb_rst)
);
`else // !`ifdef ML501_MEMORY_ONCHIP
`ifdef ML501_MEMORY_SSRAM
 
/* ZBT SSRAM controller */
 
ssram_controller ssram_controller0
(
// Outputs
.wb_dat_o (wbs_mc_dat_o),
.wb_ack_o (wbs_mc_ack_o),
.sram_clk (sram_clk),
.sram_addr (sram_addr),
.sram_ce_l (sram_ce_l),
.sram_oe_l (sram_oe_l),
.sram_we_l (sram_we_l),
.sram_bw_l (sram_bw_l),
.sram_adv_ld_l (sram_adv_ld_l),
.sram_mode (sram_mode),
// Inouts
.sram_dq_io (sram_dq_io),
// Inputs
.wb_adr_i (wbs_mc_adr_i),
.wb_stb_i (wbs_mc_stb_i),
.wb_cyc_i (wbs_mc_cyc_i),
.wb_we_i (wbs_mc_we_i),
.wb_sel_i (wbs_mc_sel_i),
.wb_dat_i (wbs_mc_dat_i),
.wb_clk (wb_clk),
.wb_rst (wb_rst),
.clk_200 (clk_200),
.sram_clk_fb (sram_clk_fb));
`else
`ifdef ML501_MEMORY_DDR2
/* DDR2 SDRAM controller */
 
/* ml501_ddr2_wb_if AUTO_TEMPLATE */
 
ml501_ddr2_wb_if ml501_ddr2_wb_if0
(
 
.wb_dat_o (wbs_mc_dat_o[31:0]),
.wb_ack_o (wbs_mc_ack_o),
.wb_adr_i (wbs_mc_adr_i[31:0]),
.wb_stb_i (wbs_mc_stb_i),
.wb_cyc_i (wbs_mc_cyc_i),
.wb_we_i (wbs_mc_we_i),
.wb_sel_i (wbs_mc_sel_i[3:0]),
.wb_dat_i (wbs_mc_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 (clk_200),
.idly_clk_200 (clk_200),
.wb_clk (wb_clk),
.wb_rst (wb_rst));
`else
 
/* No memory controller*/
dummy_slave
# ( .value(32'h00000000))
mc_ds
(
.dat_o(wbs_mc_dat_o),
.stb_i(wbs_mc_stb_i),
.cyc_i(wbs_mc_cyc_i),
.ack_o(wbs_mc_ack_o),
.clk(wb_clk),
.rst(wb_rst)
);
 
always @(posedge wb_clk)
if (wbs_mc_stb_i & wbs_mc_cyc_i & wbs_mc_ack_o)
begin
$display("* Warning - access to non-existent memory location, 0x%x\n",wb_adr_i);
end
`endif
`endif // !`ifdef ML501_MEMORY_SSRAM
`endif // !`ifdef ML501_MEMORY_ONCHIP
endmodule // ml501_mem_ctrl
 
// Local Variables:
// verilog-library-directories:(".")
// verilog-library-extensions:(".v" ".h")
// End:
/openrisc/trunk/orpsocv2/boards/xilinx/ml501/rtl/wb_conbus_defines.v
0,0 → 1,11
`define dw 32 // Data bus Width
`define aw 32 // Address bus Width
`define sw `dw / 8 // Number of Select Lines
`define mbusw `aw + `sw + `dw +4 //address width + byte select width + dat width + cyc + we + stb +cab , input from master interface
`define sbusw 3 // ack + err + rty, input from slave interface
`define mselectw 8 // number of masters
`define sselectw 8 // number of slavers
 
 
// Define the following to enable logic to generate the first few instructions at reset
//`define OR1200_BOOT_LOGIC
/openrisc/trunk/orpsocv2/boards/xilinx/ml501/rtl/ml501_ddr2_wb_if.v
0,0 → 1,488
//////////////////////////////////////////////////////////////////////
//// ////
//// Xilinx ML501 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) ////
//// ////
//// 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 ml501_ddr2_wb_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 idly_clk_200,
input wb_clk,
input wb_rst);
`include "ml501_ddr2_params.vh"
 
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:5] 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 [3:0] do_writeback_ddr2_shifter;
reg [3: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 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:5]) & 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 request address, actually, don't bother, it's useless.
always @(posedge wb_clk)
if (wb_req_new)
wb_req_cache_word_addr <= wb_adr_i[4:2];
// 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:5];
// 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_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:5],2'd0} :
{2'd0,cached_addr,2'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]);
 
// 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[2:0], 1'b0};
else if (!(|ddr2_clk_phase) & do_writeback) // sample WB domain
do_writeback_ddr2_shifter <= 4'h1;
 
 
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[3])
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;
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 [2:0] wb_cache_adr;
assign wb_cache_adr = wb_adr_i[4: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
ml501_ddr2_wb_if_cache cache_mem0
(
// Wishbone side
.clka(wb_clk),
.ena(wb_cache_en),
.wea(wb_cache_sel_we),
.addra(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(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 (wb_rst),
.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_wb_if
// Local Variables:
// verilog-library-directories:("." "ddr2_mig")
// verilog-library-extensions:(".v" ".h")
// End:
/openrisc/trunk/orpsocv2/boards/xilinx/ml501/rtl/ml501_startup.v
0,0 → 1,145
//////////////////////////////////////////////////////////////////////
//// ////
//// Xilinx ML501 Startup Memory ////
//// ////
//// Description ////
//// Describes inferrable memory slave. ////
//// ////
//// 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 ////
//// ////
//////////////////////////////////////////////////////////////////////
 
/* Memory containing memory addresses 0-0x200 */
module ml501_startup
(
input [11:2] 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
);
 
/* Make this memory span up to this value */
parameter mem_span = 12'h800;
parameter mem_span_word_address_width = 9;// log2((mem_span/bytes_per_word)
// synthesis attribute ram_style of mem is block
reg [31:0] mem [0:(mem_span/4)-1] /* synthesis ram_style = no_rw_check */;
reg [mem_span_word_address_width-1:0] adr;
parameter memory_file = "sram.vmem";
 
initial
begin
$readmemh(memory_file, mem);
end
 
wire [31:0] wr_data;
// mux for data to ram, RMW on part sel != 4'hf
assign wr_data[31:24] = wb_sel_i[3] ? wb_dat_i[31:24] : wb_dat_o[31:24];
assign wr_data[23:16] = wb_sel_i[2] ? wb_dat_i[23:16] : wb_dat_o[23:16];
assign wr_data[15: 8] = wb_sel_i[1] ? wb_dat_i[15: 8] : wb_dat_o[15: 8];
assign wr_data[ 7: 0] = wb_sel_i[0] ? wb_dat_i[ 7: 0] : wb_dat_o[ 7: 0];
 
always @(posedge wb_clk or posedge wb_rst)
begin
if (wb_rst)
adr <= 0;
else
if (wb_cyc_i & wb_stb_i)
adr <= wb_adr_i[(mem_span_word_address_width+2)-1:2];
end
 
// Define REG_READS to have registered reads
//`define REG_READS
 
reg [31:0] wb_dat_o_r;
`ifdef REG_READS
// Registered read
assign wb_dat_o = wb_dat_o_r;
`else
// Unregistered read
assign wb_dat_o = mem[adr];
`endif
always @ (posedge wb_clk)
begin
if (wb_we_i & wb_ack_o)
mem[adr] <= wb_dat_i;
`ifdef REG_READS
// Registered read
wb_dat_o_r <= mem[adr];
`endif
end
// ack_o
reg wb_ack_o_r, wb_ack_o_r2;
 
`ifdef REG_READS
// Use the following for registered reads
assign wb_ack_o = wb_ack_o_r2;
`else
// Use the following for UNregistered reads
assign wb_ack_o = wb_ack_o_r;
`endif
always @ (posedge wb_clk or posedge wb_rst)
if (wb_rst)
wb_ack_o_r <= 1'b0;
else
if (!wb_ack_o_r)
begin
if (wb_cyc_i & wb_stb_i
`ifdef REG_READS
& !wb_ack_o_r2
`endif
)
wb_ack_o_r <= 1'b1;
end
else
wb_ack_o_r <= 1'b0;
 
always @ (posedge wb_clk)
wb_ack_o_r2 <= wb_ack_o_r;
endmodule
/openrisc/trunk/orpsocv2/boards/xilinx/ml501/rtl/or1200_defines.v
0,0 → 1,1847
//////////////////////////////////////////////////////////////////////
//// ////
//// OR1200's definitions ////
//// ////
//// This file is part of the OpenRISC 1200 project ////
//// http://www.opencores.org/cores/or1k/ ////
//// ////
//// Description ////
//// Parameters of 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 ////
//// ////
//////////////////////////////////////////////////////////////////////
//
// CVS Revision History
//
// $Log: or1200_defines.v,v $
// Revision 1.45 2006/04/09 01:32:29 lampret
// See OR1200_MAC_SHIFTBY in or1200_defines.v for explanation of the change. Since now no more 28 bits shift for l.macrc insns however for backward compatbility it is possible to set arbitry number of shifts.
//
// Revision 1.44 2005/10/19 11:37:56 jcastillo
// Added support for RAMB16 Xilinx4/Spartan3 primitives
//
// Revision 1.43 2005/01/07 09:23:39 andreje
// l.ff1 and l.cmov instructions added
//
// Revision 1.42 2004/06/08 18:17:36 lampret
// Non-functional changes. Coding style fixes.
//
// Revision 1.41 2004/05/09 20:03:20 lampret
// By default l.cust5 insns are disabled
//
// Revision 1.40 2004/05/09 19:49:04 lampret
// Added some l.cust5 custom instructions as example
//
// Revision 1.39 2004/04/08 11:00:46 simont
// Add support for 512B instruction cache.
//
// Revision 1.38 2004/04/05 08:29:57 lampret
// Merged branch_qmem into main tree.
//
// Revision 1.35.4.6 2004/02/11 01:40:11 lampret
// preliminary HW breakpoints support in debug unit (by default disabled). To enable define OR1200_DU_HWBKPTS.
//
// Revision 1.35.4.5 2004/01/15 06:46:38 markom
// interface to debug changed; no more opselect; stb-ack protocol
//
// Revision 1.35.4.4 2004/01/11 22:45:46 andreje
// Separate instruction and data QMEM decoders, QMEM acknowledge and byte-select added
//
// Revision 1.35.4.3 2003/12/17 13:43:38 simons
// Exception prefix configuration changed.
//
// Revision 1.35.4.2 2003/12/05 00:05:03 lampret
// Static exception prefix.
//
// Revision 1.35.4.1 2003/07/08 15:36:37 lampret
// Added embedded memory QMEM.
//
// Revision 1.35 2003/04/24 00:16:07 lampret
// No functional changes. Added defines to disable implementation of multiplier/MAC
//
// Revision 1.34 2003/04/20 22:23:57 lampret
// No functional change. Only added customization for exception vectors.
//
// Revision 1.33 2003/04/07 20:56:07 lampret
// Fixed OR1200_CLKDIV_x_SUPPORTED defines. Better description.
//
// Revision 1.32 2003/04/07 01:26:57 lampret
// RFRAM defines comments updated. Altera LPM option added.
//
// Revision 1.31 2002/12/08 08:57:56 lampret
// Added optional support for WB B3 specification (xwb_cti_o, xwb_bte_o). Made xwb_cab_o optional.
//
// Revision 1.30 2002/10/28 15:09:22 mohor
// Previous check-in was done by mistake.
//
// Revision 1.29 2002/10/28 15:03:50 mohor
// Signal scanb_sen renamed to scanb_en.
//
// Revision 1.28 2002/10/17 20:04:40 lampret
// Added BIST scan. Special VS RAMs need to be used to implement BIST.
//
// Revision 1.27 2002/09/16 03:13:23 lampret
// Removed obsolete comment.
//
// Revision 1.26 2002/09/08 05:52:16 lampret
// Added optional l.div/l.divu insns. By default they are disabled.
//
// Revision 1.25 2002/09/07 19:16:10 lampret
// If SR[CY] implemented with OR1200_IMPL_ADDC enabled, l.add/l.addi also set SR[CY].
//
// Revision 1.24 2002/09/07 05:42:02 lampret
// Added optional SR[CY]. Added define to enable additional (compare) flag modifiers. Defines are OR1200_IMPL_ADDC and OR1200_ADDITIONAL_FLAG_MODIFIERS.
//
// Revision 1.23 2002/09/04 00:50:34 lampret
// Now most of the configuration registers are updatded automatically based on defines in or1200_defines.v.
//
// Revision 1.22 2002/09/03 22:28:21 lampret
// As per Taylor Su suggestion all case blocks are full case by default and optionally (OR1200_CASE_DEFAULT) can be disabled to increase clock frequncy.
//
// Revision 1.21 2002/08/22 02:18:55 lampret
// Store buffer has been tested and it works. BY default it is still disabled until uClinux confirms correct operation on FPGA board.
//
// Revision 1.20 2002/08/18 21:59:45 lampret
// Disable SB until it is tested
//
// Revision 1.19 2002/08/18 19:53:08 lampret
// Added store buffer.
//
// Revision 1.18 2002/08/15 06:04:11 lampret
// Fixed Xilinx trace buffer address. REported by Taylor Su.
//
// Revision 1.17 2002/08/12 05:31:44 lampret
// Added OR1200_WB_RETRY. Moved WB registered outsputs / samples inputs into lower section.
//
// Revision 1.16 2002/07/14 22:17:17 lampret
// Added simple trace buffer [only for Xilinx Virtex target]. Fixed instruction fetch abort when new exception is recognized.
//
// Revision 1.15 2002/06/08 16:20:21 lampret
// Added defines for enabling generic FF based memory macro for register file.
//
// Revision 1.14 2002/03/29 16:24:06 lampret
// Changed comment about synopsys to _synopsys_ because synthesis was complaining about unknown directives
//
// Revision 1.13 2002/03/29 15:16:55 lampret
// Some of the warnings fixed.
//
// Revision 1.12 2002/03/28 19:25:42 lampret
// Added second type of Virtual Silicon two-port SRAM (for register file). Changed defines for VS STP RAMs.
//
// Revision 1.11 2002/03/28 19:13:17 lampret
// Updated defines.
//
// Revision 1.10 2002/03/14 00:30:24 lampret
// Added alternative for critical path in DU.
//
// Revision 1.9 2002/03/11 01:26:26 lampret
// Fixed async loop. Changed multiplier type for ASIC.
//
// Revision 1.8 2002/02/11 04:33:17 lampret
// Speed optimizations (removed duplicate _cyc_ and _stb_). Fixed D/IMMU cache-inhibit attr.
//
// Revision 1.7 2002/02/01 19:56:54 lampret
// Fixed combinational loops.
//
// Revision 1.6 2002/01/19 14:10:22 lampret
// Fixed OR1200_XILINX_RAM32X1D.
//
// Revision 1.5 2002/01/18 07:56:00 lampret
// No more low/high priority interrupts (PICPR removed). Added tick timer exception. Added exception prefix (SR[EPH]). Fixed single-step bug whenreading NPC.
//
// Revision 1.4 2002/01/14 09:44:12 lampret
// Default ASIC configuration does not sample WB inputs.
//
// Revision 1.3 2002/01/08 00:51:08 lampret
// Fixed typo. OR1200_REGISTERED_OUTPUTS was not defined. Should be.
//
// Revision 1.2 2002/01/03 21:23:03 lampret
// Uncommented OR1200_REGISTERED_OUTPUTS for FPGA target.
//
// Revision 1.1 2002/01/03 08:16:15 lampret
// New prefixes for RTL files, prefixed module names. Updated cache controllers and MMUs.
//
// Revision 1.20 2001/12/04 05:02:36 lampret
// Added OR1200_GENERIC_MULTP2_32X32 and OR1200_ASIC_MULTP2_32X32
//
// Revision 1.19 2001/11/27 19:46:57 lampret
// Now FPGA and ASIC target are separate.
//
// Revision 1.18 2001/11/23 21:42:31 simons
// Program counter divided to PPC and NPC.
//
// Revision 1.17 2001/11/23 08:38:51 lampret
// Changed DSR/DRR behavior and exception detection.
//
// Revision 1.16 2001/11/20 21:30:38 lampret
// Added OR1200_REGISTERED_INPUTS.
//
// Revision 1.15 2001/11/19 14:29:48 simons
// Cashes disabled.
//
// Revision 1.14 2001/11/13 10:02:21 lampret
// Added 'setpc'. Renamed some signals (except_flushpipe into flushpipe etc)
//
// Revision 1.13 2001/11/12 01:45:40 lampret
// Moved flag bit into SR. Changed RF enable from constant enable to dynamic enable for read ports.
//
// Revision 1.12 2001/11/10 03:43:57 lampret
// Fixed exceptions.
//
// Revision 1.11 2001/11/02 18:57:14 lampret
// Modified virtual silicon instantiations.
//
// Revision 1.10 2001/10/21 17:57:16 lampret
// Removed params from generic_XX.v. Added translate_off/on in sprs.v and id.v. Removed spr_addr from dc.v and ic.v. Fixed CR+LF.
//
// Revision 1.9 2001/10/19 23:28:46 lampret
// Fixed some synthesis warnings. Configured with caches and MMUs.
//
// Revision 1.8 2001/10/14 13:12:09 lampret
// MP3 version.
//
// Revision 1.1.1.1 2001/10/06 10:18:36 igorm
// no message
//
// Revision 1.3 2001/08/17 08:01:19 lampret
// IC enable/disable.
//
// Revision 1.2 2001/08/13 03:36:20 lampret
// Added cfg regs. Moved all defines into one defines.v file. More cleanup.
//
// Revision 1.1 2001/08/09 13:39:33 lampret
// Major clean-up.
//
// Revision 1.2 2001/07/22 03:31:54 lampret
// Fixed RAM's oen bug. Cache bypass under development.
//
// Revision 1.1 2001/07/20 00:46:03 lampret
// Development version of RTL. Libraries are missing.
//
//
 
//
// 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
//`define OR1200_ACTEL
 
//
// 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
//
 
//
// 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 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
// instructions and if these two insns are not
// implemented there is not much point having SR[CY].
//
`define OR1200_IMPL_CY
 
//
// 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, multiplier needs to be implemented.
//
`define OR1200_IMPL_DIV
 
//
// 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 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
 
//
// 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_32x32.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
 
//
// 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_FF1 4'd15
//
// MACOPs
//
`define OR1200_MACOP_WIDTH 2
`define OR1200_MACOP_NOP 2'b00
`define OR1200_MACOP_MAC 2'b01
`define OR1200_MACOP_MSB 2'b10
 
//
// 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
 
// 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
 
// FETCHOPs
`define OR1200_FETCHOP_WIDTH 1
`define OR1200_FETCHOP_NOP 1'b0
`define OR1200_FETCHOP_LW 1'b1
 
//
// Register File Write-Back OPs
//
`ifdef OR1200_FPU_IMPLEMENTED
// 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
`else
// Bit 0: register file write enable
// Bits 2-1: write-back mux selects
`define OR1200_RFWBOP_WIDTH 3
`define OR1200_RFWBOP_NOP 3'b000
`define OR1200_RFWBOP_ALU 2'b00
`define OR1200_RFWBOP_LSU 2'b01
`define OR1200_RFWBOP_SPRS 2'b10
`define OR1200_RFWBOP_LR 2'b11
`endif // !`ifdef OR1200_FPU_IMPLEMENTED
 
// 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
 
//
// FPU OPs
//
// MSbit indicates FPU operation valid
//
`ifdef OR1200_FPU_IMPLEMENTED
`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
`endif
 
//
// 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
 
// ALU instructions multicycle field in machine word
`define OR1200_ALUMCYC_POS 9:8
 
//
// 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
`ifdef OR1200_FPU_IMPLEMENTED
`define OR1200_OR32_FLOAT 6'b110010
`endif
/* */
`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_BREAK `OR1200_EXCEPT_WIDTH'hd
`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
`ifdef OR1200_FPU_IMPLEMENTED
`define OR1200_SPR_GROUP_FPU 5'd11
`endif
 
/////////////////////////////////////////////////////
//
// 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
`ifdef OR1200_FPU_IMPLEMENTED
`define OR1200_SPR_FPCSR 11'd20
`endif
`define OR1200_SPR_EPCR 11'd32
`define OR1200_SPR_EEAR 11'd48
`define OR1200_SPR_ESR 11'd64
 
//
// SR bits
//
`define OR1200_SR_WIDTH 16
`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_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, minus one, if HW breakpoints enabled
`define OR1200_DU_DVRDCR_PAIRS 7
 
// Define if you want trace buffer
//`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'h1xx
`define OR1200_DU_TBIM 11'h2xx
`define OR1200_DU_TBAR 11'h3xx
`define OR1200_DU_TBTS 11'h4xx
`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 11:2
`define OR1200_DU_DMR2_WGB 23:12
 
// 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 20
 
// 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_cycstb_i && 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 perform store refill (potential performance penalty)
// `define OR1200_DC_STORE_REFILL
 
//
// 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'h01
`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_RES1_BITS 23:11
`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
`define OR1200_UPR_MP 1'b1 // MAC always present
`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_DU_IMPLEMENTED
`define OR1200_UPR_PMP 1'b1
`else
`define OR1200_UPR_PMP 1'b0
`endif
`ifdef OR1200_DU_IMPLEMENTED
`define OR1200_UPR_PICP 1'b1
`else
`define OR1200_UPR_PICP 1'b0
`endif
`ifdef OR1200_DU_IMPLEMENTED
`define OR1200_UPR_TTP 1'b1
`else
`define OR1200_UPR_TTP 1'b0
`endif
`define OR1200_UPR_RES1 13'h0000
`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
`define OR1200_CPUCFGR_OF32S 1'b0
`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'b1 // Irrelevant
`define OR1200_DCCFGR_CBIRI 1'b1 // Irrelevant
`define OR1200_DCCFGR_CBPRI 1'b0 // Irrelevant
`define OR1200_DCCFGR_CBLRI 1'b0 // Irrelevant
`define OR1200_DCCFGR_CBFRI 1'b1 // 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) // 16 byte cache block
`define OR1200_DCCFGR_CWS 1'b0 // Write-through strategy
`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.
`define OR1200_DCCFGR_CBWBRI 1'b0 // Cache block WB reg not impl.
`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) // 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 2:0
`define OR1200_DCFGR_WPCI_BITS 3
`define OR1200_DCFGR_RES1_BITS 31:4
 
// DCFGR values
`ifdef OR1200_DU_HWBKPTS
`define OR1200_DCFGR_NDP 3'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 3'h0 // Zero DVR/DCR pairs
`define OR1200_DCFGR_WPCI 1'b0 // WP counters not impl.
`endif
`define OR1200_DCFGR_RES1 28'h0000000
/openrisc/trunk/orpsocv2/boards/xilinx/ml501/rtl/ddr2_mig/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
/openrisc/trunk/orpsocv2/boards/xilinx/ml501/rtl/ddr2_mig/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
/openrisc/trunk/orpsocv2/boards/xilinx/ml501/rtl/ddr2_mig/ddr2_ctrl.v
0,0 → 1,1225
//*****************************************************************************
// 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 read flag to the adress FIFO
assign ctrl_af_rden = sm_rden || rd_af_flag_r;
 
// 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((ctrl_af_rden_r) ||
(rd_af_flag_r && (af_valid_r || af_valid_r1)))
rd_af_flag_r <= 1'd0;
else if (~af_valid_r1 || ~af_valid_r)
rd_af_flag_r <= 1'd1;
 
end
 
// 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
 
/openrisc/trunk/orpsocv2/boards/xilinx/ml501/rtl/ddr2_mig/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 FLASE - 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
/openrisc/trunk/orpsocv2/boards/xilinx/ml501/rtl/ddr2_mig/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
/openrisc/trunk/orpsocv2/boards/xilinx/ml501/rtl/ddr2_mig/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
/openrisc/trunk/orpsocv2/boards/xilinx/ml501/rtl/ddr2_mig/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
//*****************************************************************
// 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
 
 
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
/openrisc/trunk/orpsocv2/boards/xilinx/ml501/rtl/ddr2_mig/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
/openrisc/trunk/orpsocv2/boards/xilinx/ml501/rtl/ddr2_mig/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
/openrisc/trunk/orpsocv2/boards/xilinx/ml501/rtl/ddr2_mig/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
/openrisc/trunk/orpsocv2/boards/xilinx/ml501/rtl/ddr2_mig/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
/openrisc/trunk/orpsocv2/boards/xilinx/ml501/rtl/ddr2_mig/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
/openrisc/trunk/orpsocv2/boards/xilinx/ml501/rtl/ddr2_mig/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
/openrisc/trunk/orpsocv2/boards/xilinx/ml501/rtl/ddr2_mig/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
/openrisc/trunk/orpsocv2/boards/xilinx/ml501/rtl/ddr2_mig/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
/openrisc/trunk/orpsocv2/boards/xilinx/ml501/rtl/ddr2_mig/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
/openrisc/trunk/orpsocv2/boards/xilinx/ml501/rtl/ddr2_mig/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
/openrisc/trunk/orpsocv2/boards/xilinx/ml501/rtl/ddr2_mig/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
/openrisc/trunk/orpsocv2/boards/xilinx/ml501/rtl/ddr2_mig/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
/openrisc/trunk/orpsocv2/boards/xilinx/ml501/rtl/ddr2_mig/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
/openrisc/trunk/orpsocv2/boards/xilinx/ml501/rtl/ml501_ddr2_params.vh
0,0 → 1,50
 
// 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
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)
 
/openrisc/trunk/orpsocv2/boards/xilinx/ml501/rtl/dummy_slave.v
0,0 → 1,33
/*
Dummy Slave module
Simply acks back a pre-determined value
*/
 
module dummy_slave
( dat_o, stb_i, cyc_i, ack_o, clk, rst );
 
output [31:0] dat_o;
input stb_i;
input cyc_i;
output ack_o;
input clk;
input rst;
 
reg ack_o;
parameter [31:0] value = 32'hc0000000;
 
assign dat_o = value;
 
always @ (posedge clk or posedge rst)
if (rst)
ack_o <= 1'b0;
else
ack_o <= stb_i & cyc_i & !ack_o;
 
endmodule // dummy_slave
 
 
/openrisc/trunk/orpsocv2/boards/xilinx/ml501/rtl/reset_debounce.v
0,0 → 1,80
//////////////////////////////////////////////////////////////////////
//// ////
//// Reset control/debouncer ////
//// ////
//// Description ////
//// Debounce reset button signal. It is also sensitive to the ////
//// user generated reset and DCM lock signals. ////
//// ////
//// 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 ////
//// ////
//////////////////////////////////////////////////////////////////////
 
module reset_debounce
(
input sys_rst_in,
input usr_rst_in,
input sys_clk_in,
output rst_dcm0,
input dcm0_clk,
input dcm0_locked,
output rst
);
reg [9:0] debounce_count = 10'h000;
wire sys_rst = !(sys_rst_in & usr_rst_in); // Either of these going low triggers reset
reg debounced_rst;
always @(posedge sys_clk_in) begin
if (sys_rst) begin
debounced_rst <= 1'b1;
debounce_count <= 10'h3ff;
end else begin
if (debounce_count > 10'b0000000000) debounce_count <= debounce_count - 1'b1;
if (debounce_count == 10'b0000000001) debounced_rst <= sys_rst;
end
end
assign rst_dcm0 = debounced_rst;
/* Hold reset for a little longer after the dcm locks */
reg [15:0] rst_dcm0_count;
always @(posedge dcm0_clk or posedge debounced_rst)
if (debounced_rst)
rst_dcm0_count <= 16'hffff;
else
rst_dcm0_count <= {rst_dcm0_count[14:0], ~dcm0_locked};
 
assign rst = rst_dcm0_count[15];
 
endmodule // reset_debounce
/openrisc/trunk/orpsocv2/boards/xilinx/ml501/rtl/ssram_controller.v
0,0 → 1,301
//////////////////////////////////////////////////////////////////////
//// ////
//// 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 ssram_controller
(
// 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 // ssram_controller
 
 
// Local Variables:
// verilog-library-directories:(".")
// verilog-library-extensions:(".v" ".h")
// End:
/openrisc/trunk/orpsocv2/boards/xilinx/ml501/rtl/ml501_ddr2_wb_if.v.prev
0,0 → 1,570
/*
* Simple interface to the Xilinx MIG generated DDR2 controller.
*
* The controller is capable of fast streams of accesses, and this
* module aims to simply do the minimum amount to get the controller
* working on the wishbone bus.
*
* This means, each read or write will incur a read of (minimum burst
* x data-width) = 8 words, which will sit in a small bit of distram
* until something else is read, outside of those 8 words.
* Of course, reads will be scrapped and new data will be read over,
* and in the case of writes, it has to be written back to the RAM.
*
* I will try to make this as parametisable as much as possible, allowing
* greater caching, or perhaps greater associativity, so a few spots of
* memory can be cached here at once, but at first it will be a simple
* interface between wishbone and the Xilinx MIG DDR2 interface, implenting
* as simple a interface as possible.
*/
module ml501_ddr2_wb_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 ddr2_cs_n,
output ddr2_odt,
output 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 rst,
input wb_clk,
input wb_rst);
`include "ml501_ddr2_params.v"
 
parameter cache_lines = 1;
parameter bits_per_word = 32;
parameter bytes_per_word = 4;
parameter words_per_line = 8; /* (ddr2 burst * ddr2 data width / bits_per_word) */
parameter bytes_per_line = 32; /* (words_per_line * bytes_per_word) */
parameter cache_byte_address_width = 5; /* log2(bytes_per_line) */
parameter cache_word_address_width = 3; /* log2(words_per_line) */
 
 
wire wb_req;
reg wb_req_r;
 
wire new_wb_req;
reg new_wb_req_r;
 
reg wb_req_addr_hit;
 
// Current line's address
reg [31:cache_byte_address_width] cached_address_line;
reg cached_address_valid;
reg cache_dirty;
// Hopefully this turns into a dual-port RAM
// synthesis attribute ram_style of mem is distributed
reg [31:0] mem [0:words_per_line-1];
wire [31:0] cache_do_wb, cache_do_mig;
// registered address for cache RAM
reg [cache_word_address_width-1:0] cache_addr_wb, cache_addr_mig;
wire cache_we_wb, cache_we_mig;
 
wire [31:0] cache_di_wb;
reg [31:0] cache_di_mig; // Is actually comb.
reg [cache_word_address_width - 1: 0] writeback_counter, writeback_counter_r,writeback_counter_r_r;
reg writeback_doing;
reg writeback_data_we;
 
reg [cache_word_address_width - 1: 0] readfrom_counter, readfrom_counter_r;
reg readfrom_start;
reg readfrom_doing;
reg readfrom_doing_r;
 
// Assemble the 128-bit words here when writing or store them
// here when reading from SDRAM
reg [127:0] app_holding_reg0, app_holding_reg1;
reg app_holding_reg_sel;
// 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;
 
// mux for RMW on wishbone side
assign cache_di_wb[31:24] = wb_sel_i[3] ? wb_dat_i[31:24] : cache_do_wb[31:24];
assign cache_di_wb[23:16] = wb_sel_i[2] ? wb_dat_i[23:16] : cache_do_wb[23:16];
assign cache_di_wb[15: 8] = wb_sel_i[1] ? wb_dat_i[15: 8] : cache_do_wb[15: 8];
assign cache_di_wb[ 7: 0] = wb_sel_i[0] ? wb_dat_i[ 7: 0] : cache_do_wb[ 7: 0];
 
// Cache's Wishbone-side r/w logic
always @(posedge wb_clk)
if (wb_req)
cache_addr_wb <= wb_adr_i[(cache_word_address_width+2)-1:2];
assign cache_do_wb = mem[cache_addr_wb];
assign wb_dat_o = cache_do_wb;
always @(posedge wb_clk)
if (wb_req & wb_we_i & wb_req_addr_hit & wb_ack_o)
mem[cache_addr_wb] <= cache_di_wb;
// 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 new_wb_req = wb_req & !wb_req_r;
always @(posedge wb_clk)
new_wb_req_r <= new_wb_req;
// 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 & (cached_address_line ==
wb_adr_i[31:cache_byte_address_width]) &
cached_address_valid;
always @(posedge wb_clk)
if (wb_rst)
wb_ack_o <= 0;
else
wb_ack_o <= wb_req_addr_hit & !wb_ack_o;
 
always @(posedge wb_clk)
if (readfrom_counter_r == 1) /* Unsure about this */
cached_address_line <= wb_adr_i[31:cache_byte_address_width];
// Cache dirty signal
always @(posedge wb_clk)
if (wb_req & wb_we_i & wb_req_addr_hit & wb_ack_o)
cache_dirty <= 1;
else if (readfrom_counter_r == 1)
cache_dirty <= 0;
always @(posedge wb_clk)
if (wb_rst)
cached_address_valid <= 0;
else if (readfrom_counter_r == 1) /* Unsure about this */
cached_address_valid <= 1;
else if (writeback_counter_r_r == 1)
cached_address_valid <= 0;
/*
* Cache writeback to DDR2
*
* Load the words out of the cache into DDR2 MIG write data fifo.
* On the last, also write in the address.
*
*/
`define WRITEBACK_CONDITION (new_wb_req_r && !wb_req_addr_hit && cached_address_valid && cache_dirty)
// If burst length is 4 and SDRAM DQ is 64-bits, and the ddr2 MIG fifo is
// 128-wide and we're loading from a 128-bit wide ram, then we need to do
// (64 * 4) / 32 = 8 reads from our RAM, and we need to do a write to the
// fifo every (128 / 32) = 4th word we pull out.
`define WRITEBACK_COUNTER_LOAD (7)
// Pulse app_wdf when writeback_counter_r == 4 or 0, but testing 0 is bad
// so we'll test the registered, registered version for 5 and 1 ([1:0] == 1)
`define WRITEBACK_FIFO_WE (writeback_counter_r_r[1:0] == 2'b01)
 
// app_holding_reg0 load control
always @(posedge wb_clk)
if (writeback_counter_r[1:0] == 2'b11)
app_holding_reg0[31:0] <= cache_do_mig;
else if (writeback_counter_r[1:0] == 2'b10)
app_holding_reg0[63:32] <= cache_do_mig;
else if (writeback_counter_r[1:0] == 2'b01)
app_holding_reg0[95:64] <= cache_do_mig;
else if ((writeback_counter_r[1:0] == 2'b00) & `WRITEBACK_CONDITION)
app_holding_reg0[127:96] <= cache_do_mig;
else if ((app_holding_reg_sel == 0) && rd_data_valid)
app_holding_reg0 <= rd_data_fifo_out;
// app_holding_reg0 load control
always @(posedge wb_clk)
if ((app_holding_reg_sel == 1) && rd_data_valid)
app_holding_reg1 <= rd_data_fifo_out;
always @(posedge wb_clk)
writeback_data_we <= (writeback_counter_r_r[1:0] == 2'b01);
// Load for writeback sequence when we've got a miss, valid address
// and dirty cache.
always @(posedge wb_clk)
if (wb_rst)
writeback_counter <= 0;
else if (|writeback_counter)
writeback_counter <= writeback_counter - 1;
else if `WRITEBACK_CONDITION
writeback_counter <= `WRITEBACK_COUNTER_LOAD;
always @(posedge wb_clk)
writeback_counter_r <= writeback_counter;
always @(posedge wb_clk)
writeback_counter_r_r <= writeback_counter_r;
always @(posedge wb_clk)
writeback_doing <= ((|writeback_counter)|(|writeback_counter_r)|(|writeback_counter_r_r));
/*
* Cache read from DDR2
*
* Read will simply put the address onto the bus and await for
* the fifo to start spitting things out.
*
*/
`define READFROM_CONDITION (new_wb_req_r && !wb_req_addr_hit && !cached_address_valid && !(|writeback_counter_r))
always @(posedge wb_clk)
if (wb_rst)
readfrom_doing <= 0;
else if (wb_ack_o)
readfrom_doing <= 0;
else if (`READFROM_CONDITION)
readfrom_doing <= 1;
//assign readfrom_doing = `READFROM_CONDITION;
always @(posedge wb_clk)
readfrom_doing_r <= readfrom_doing;
always @(posedge wb_clk)
readfrom_start <= (!readfrom_doing_r & readfrom_doing);
 
reg readfrom_start_r;
always @(posedge wb_clk)
readfrom_start_r <= readfrom_start;
reg readfrom_counter_go, readfrom_counter_go_r;
 
// Reg to indicate the counter should increment.
// Also used as WE to the MIG side of the RAM
always @(posedge wb_clk)
if (wb_rst)
readfrom_counter_go <= 0;
else
begin
if (app_holding_reg_sel & rd_data_valid)
readfrom_counter_go <= 1;
else if (&readfrom_counter)
readfrom_counter_go <= 0;
end
always @(posedge wb_clk)
readfrom_counter_go_r <= readfrom_counter_go;
// Readfrom counter
// We use this counter to copy in the data from the holding registers
always @(posedge wb_clk)
if (readfrom_counter_go)
readfrom_counter <= readfrom_counter + 1;
else
readfrom_counter <= 0;
always @(posedge wb_clk)
readfrom_counter_r <= readfrom_counter;
always @(posedge wb_clk)
if (wb_rst)
app_holding_reg_sel <= 0;
else if (rd_data_valid)
app_holding_reg_sel <= ~app_holding_reg_sel;
 
 
always @(/*AUTOSENSE*/app_holding_reg0 or app_holding_reg1
or readfrom_counter)
case (readfrom_counter)
3'b000 : cache_di_mig <= app_holding_reg0[31:0];
3'b001 : cache_di_mig <= app_holding_reg0[63:32];
3'b010 : cache_di_mig <= app_holding_reg0[95:64];
3'b011 : cache_di_mig <= app_holding_reg0[127:96];
3'b100 : cache_di_mig <= app_holding_reg1[31:0];
3'b101 : cache_di_mig <= app_holding_reg1[63:32];
3'b110 : cache_di_mig <= app_holding_reg1[95:64];
3'b111 : cache_di_mig <= app_holding_reg1[127:96];
default: cache_di_mig <= 0;
endcase // case (readfrom_counter)
//assign cache_di_mig = rd_data_fifo_out;
assign cache_we_mig = readfrom_counter_go;
// Address for MIG side of cache
// Expect it to always go back to 0!
always @(posedge wb_clk)
if (wb_rst)
cache_addr_mig <= 0;
else if (readfrom_start)
cache_addr_mig <= 0;
else if ((|writeback_counter) | readfrom_counter_go)
cache_addr_mig <= cache_addr_mig + 1;
always @(posedge wb_clk)
if (cache_we_mig)
mem[cache_addr_mig] <= cache_di_mig;
assign cache_do_mig = mem[cache_addr_mig];
// Whenever writeback counter is counting down, generate
// the write-enable to the data fifo
assign app_wdf_wren = (writeback_data_we);
assign app_wdf_data = cache_do_mig;
assign app_af_addr = (writeback_doing) ?
{4'd0,cached_address_line} :
{4'd0, wb_adr_i[31:cache_byte_address_width]} ;
assign app_af_wren = ((writeback_data_we & !writeback_counter_r_r[2]) |
(readfrom_start) &
!app_af_afull );
/*readfrom_doing ) &*/
 
assign app_wdf_mask_data = 0;
// CMD, 1 = read, 0 = write
assign app_af_cmd[0] = |readfrom_doing;
assign app_af_cmd[2:1] = 0;
 
 
ml501_ddr2_wb_if_cache cache_mem0
(/*AUTOINST*/
// Outputs
.wb_do (wb_do[31:0]),
.ddr2_do (ddr2_do[127:0]),
// Inputs
.wb_clk (wb_clk),
.wb_addr (wb_addr[2:0]),
.wb_di (wb_di[31:0]),
.wb_we (wb_we),
.wb_sel (wb_sel[3:0]),
.wb_en (),
.ddr2_clk (ddr2_clk),
.ddr2_addr (ddr2_addr),
.ddr2_di (ddr2_di[127:0]),
.ddr2_we (ddr2_we));
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 (clk200),
.sys_rst_n (sys_rst_out),
.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 (wb_clk),
//.rst0_tb (wb_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_wb_if
// Local Variables:
// verilog-library-directories:("." "ddr2_mig")
// verilog-library-extensions:(".v" ".h")
// End:
 
 
module ml501_ddr2_wb_if_cache(
wb_clk,
wb_addr,
wb_di,
wb_do,
wb_we,
wb_sel,
wb_en,
 
ddr2_clk,
ddr2_addr,
ddr2_di,
ddr2_do,
ddr2_we
);
input wb_clk;
input [2:0] wb_addr;
input [31:0] wb_di;
output [31:0] wb_do;
input wb_we;
input [3:0] wb_sel;
input wb_en;
input ddr2_clk;
input ddr2_addr;
input [127:0] ddr2_di;
output [127:0] ddr2_do;
input ddr2_we;
wire [3:0] wb_sel_we;
assign wb_sel_we = {4{wb_we}} & wb_sel;
genvar i;
generate
for (i = 0; i < 4; i = i + 1)
// RAMB36: 32k+4k Parity Paramatizable True Dual-Port BlockRAM
// Virtex-5
// Xilinx HDL Libraries Guide, version 10.1.2
RAMB36 #(
.SIM_MODE("SAFE"), // Simulation: "SAFE" vs. "FAST", see "Synthesis and Simulation Design Guide" for details
.DOA_REG(0), // Optional output registers on A port (0 or 1)
.DOB_REG(0), // Optional output registers on B port (0 or 1)
.INIT_A(36’h000000000), // Initial values on A output port
.INIT_B(36’h000000000), // Initial values on B output port
.RAM_EXTENSION_A("NONE"), // "UPPER", "LOWER" or "NONE" when cascaded
.RAM_EXTENSION_B("NONE"), // "UPPER", "LOWER" or "NONE" when cascaded
.READ_WIDTH_A(9), // Valid values are 1, 2, 4, 9, 18, or 36
.READ_WIDTH_B(36), // Valid values are 1, 2, 4, 9, 18, or 36
.SIM_COLLISION_CHECK("NONE"), // Collision check enable "ALL", "WARNING_ONLY",
// "GENERATE_X_ONLY" or "NONE"
.SRVAL_A(36’h000000000), // Set/Reset value for A port output
.SRVAL_B(36’h000000000), // Set/Reset value for B port output
.WRITE_MODE_A("WRITE_FIRST"), // "WRITE_FIRST", "READ_FIRST", or "NO_CHANGE"
.WRITE_MODE_B("WRITE_FIRST"), // "WRITE_FIRST", "READ_FIRST", or "NO_CHANGE"
.WRITE_WIDTH_A(9), // Valid values are 1, 2, 4, 9, 18, or 36
.WRITE_WIDTH_B(36), // Valid values are 1, 2, 4, 9, 18, or 36
) RAMB36_inst
(
//.CASCADEOUTLATA(CASCADEOUTLATA), // 1-bit cascade A latch output
//.CASCADEOUTLATB(CASCADEOUTLATB), // 1-bit cascade B latch output
//.CASCADEOUTREGA(CASCADEOUTREGA), // 1-bit cascade A register output
//.CASCADEOUTREGB(CASCADEOUTREGB), // 1-bit cascade B register output
.DOA(wb_do[(i+1)*8-1:(i*8)]), // 8-bit A port data output
.DOB(ddr2_do[(i+1)*32-1:i*32]), // 32-bit B port data output
// .DOPA(DOPA), // A port parity data output
// .DOPB(DOPB), // B port parity data output
.ADDRA(wb_addr), // A port address input
.ADDRB(ddr2_addr), // B port address input
.CASCADEINLATA(0), // 1-bit cascade A latch input
.CASCADEINLATB(0), // 1-bit cascade B latch input
.CASCADEINREGA(0), // 1-bit cascade A register input
.CASCADEINREGB(0), // 1-bit cascade B register input
.CLKA(wb_clk), // 1-bit A port clock input
.CLKB(ddr2_clk), // 1-bit B port clock input
.DIA(wb_di[(i+1)*8-1:(i*8)]), // 8-bit A port data input
.DIB(ddr2_di[(i+1)*32-1:i*32]), // 32-bit B port data input
.DIPA(0), // 4-bit A port parity data input
.DIPB(0), // 4-bit B port parity data input
.ENA(wb_en), // 1-bit A port enable input
.ENB(1), // 1-bit B port enable input
.REGCEA(0), // 1-bit A port register enable input
.REGCEB(0), // 1-bit B port register enable input
.SSRA(0), // 1-bit A port set/reset input
.SSRB(0), // 1-bit B port set/reset input
.WEA(wb_sel_we[i]), // 4-bit A port write enable input
.WEB(ddr2_we) // 4-bit B port write enable input
);
endgenerate
endmodule // ml501_ddr2_wb_if_cache
 
/openrisc/trunk/orpsocv2/boards/xilinx/ml501/rtl/ml501_defines.v
0,0 → 1,64
///////////////////////////////////////////////////////////////////////////
// ML501 ORPSoCv2 build defines
///////////////////////////////////////////////////////////////////////////
//
// Uncomment the `defines to enable them
//
// Note the synthesis scripts may need to be altered (mainly the UCF for
// place and route) depending on the configuration.
//
///////////////////////////////////////////////////////////////////////////
 
///////////////////////////////////////////////////////////////////////////
// Memory
///////////////////////////////////////////////////////////////////////////
//
// Memory configuration options:
//
// On-Chip startup/low memory RAM is optional
// The main memory controllers are mutually exclusive (ie. only one enabled at a time)
//
// Main memory options (select only of the following):
//
// On-Chip Xilinx RAMBs (~64KByte, resource used depending)
// ZBT SSRAM (1MByte, 200Mhz)
// DDR2 SDRAM (256MByte, 266Mhz)
// It is recommended the startup memory is used with only the ZBT SSRAM or DDR2
//
// See the RTL file, boards/xilinx/ml501/rtl/ml501_mc.v, for specifics
//
///////////////////////////////////////////////////////////////////////////
 
// Use on-chip memory as a boot-ROM
`define ML501_MEMORY_STARTUP
`ifdef ML501_MEMORY_STARTUP
// Define the size of the onchip memory
`define ML501_MEMORY_STARTUP_ADDR_SPAN 12'h800
`endif
 
// Main memory configuration
 
// On-chip SRAM (Xilinx RAMB36s)
//`define ML501_MEMORY_ONCHIP
`ifdef ML501_MEMORY_ONCHIP
// 64KByte = 16 on-chip RAMs (4KByte per RAMB36) of the xc5vlx50's 48 BlockRAMs
`define ML501_MEMORY_ONCHIP_SIZE_BYTES (64*1024)
`define ML501_MEMORY_ONCHIP_ADDRESS_WIDTH 16
`endif
 
// Use the ZBT SSRAM controller
//`define ML501_MEMORY_SSRAM
`ifdef ML501_MEMORY_SSRAM
`define tsramtrace #750 /* 1500ps roundtrip */
`endif
 
// Use the DDR2 SDRAM controller
`define ML501_MEMORY_DDR2
 
///////////////////////////////////////////////////////////////////////////
// Peripherals
///////////////////////////////////////////////////////////////////////////
 
// Include the OpenCores Ethernet MAC
`define USE_ETHERNET
 
/openrisc/trunk/orpsocv2/boards/xilinx/ml501/rtl/wb_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
/openrisc/trunk/orpsocv2/boards/xilinx/ml501/rtl/ml501.v
0,0 → 1,993
//////////////////////////////////////////////////////////////////////
//// ////
//// ORPSoC on Xilinx ML501 ////
//// ////
//// Description ////
//// ORPSoC on Xilinx ML501 board toplevel file ////
//// ////
//// To Do: ////
//// Check to see if system works with both SSRAM and DDR2 RAM ////
//// are enabled. ////
//// Add ethernet MAC controller. ////
//// ////
//// 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 ////
//// ////
//////////////////////////////////////////////////////////////////////
 
// ml501 board toplevel RTL
`timescale 1ps/1ps
`include "ml501_defines.v"
module ml501
(
// Clocks and reset
input sys_clk_in_p, // 200Mhz diff. pair
input sys_clk_in_n,
input sys_clk_in, // 100Mhz user clock
input sys_rst_in,
output usr_rst_out, // User controlled reset signal
input usr_rst_in,
 
`ifdef ML501_MEMORY_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 ML501_MEMORY_SSRAM
 
`ifdef ML501_MEMORY_DDR2
// DDR2 SDRAM
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 ML501_MEMORY_DDR2
`ifdef USE_ETHERNET
input phy_tx_clk,
output [3:0] phy_tx_data,
output phy_tx_en,
output phy_tx_er,
input phy_rx_clk,
input [3:0] phy_rx_data,
input phy_dv,
input phy_rx_er,
input phy_col,
input phy_crs,
output phy_smi_clk,
inout phy_smi_data,
 
output phy_rst_n,
`endif // `ifdef USE_ETHERNET
// JTAG debug
input dbg_tdi_pad_i,
input dbg_tck_pad_i,
input dbg_tms_pad_i,
output dbg_tdo_pad_o,
// Uart
input uart0_srx_pad_i,
output uart0_stx_pad_o,
 
// GPIO
inout [25:0] gpio
)
;
 
wire wb_rst;
wire wb_clk;
wire sys_clk_in_200;
wire clk_200;
wire [30:0] pic_ints;
wire uart0_irq;
wire eth0_int_o;
parameter [31:0] wbm_or12_i_dat_o = 32'h0;
wire [31:0] wbm_or12_i_adr_o;
wire [3:0] wbm_or12_i_sel_o;
wire wbm_or12_i_we_o;
wire [1:0] wbm_or12_i_bte_o;
wire [2:0] wbm_or12_i_cti_o;
wire wbm_or12_i_stb_o;
wire wbm_or12_i_cyc_o;
wire [31:0] wbm_or12_i_dat_i;
wire wbm_or12_i_ack_i;
wire wbm_or12_i_err_i;
wire wbm_or12_i_rty_i;
wire [31:0] wbm_or12_debug_dat_o;
wire [31:0] wbm_or12_debug_adr_o;
wire [3:0] wbm_or12_debug_sel_o;
wire wbm_or12_debug_we_o;
wire [1:0] wbm_or12_debug_bte_o;
wire [2:0] wbm_or12_debug_cti_o;
wire wbm_or12_debug_stb_o;
wire wbm_or12_debug_cyc_o;
wire [31:0] wbm_or12_debug_dat_i;
wire wbm_or12_debug_ack_i;
wire wbm_or12_debug_err_i;
wire wbm_or12_debug_rty_i;
wire [31:0] wbm_or12_d_dat_o;
wire [31:0] wbm_or12_d_adr_o;
wire [3:0] wbm_or12_d_sel_o;
wire wbm_or12_d_we_o;
wire [1:0] wbm_or12_d_bte_o;
wire [2:0] wbm_or12_d_cti_o;
wire wbm_or12_d_stb_o;
wire wbm_or12_d_cyc_o;
wire [31:0] wbm_or12_d_dat_i;
wire wbm_or12_d_ack_i;
wire wbm_or12_d_err_i;
wire wbm_or12_d_rty_i;
wire [31:0] wbm_eth1_dat_o;
wire [31:0] wbm_eth1_adr_o;
wire [3:0] wbm_eth1_sel_o;
wire wbm_eth1_we_o;
wire [1:0] wbm_eth1_bte_o;
wire [2:0] wbm_eth1_cti_o;
wire wbm_eth1_stb_o;
wire wbm_eth1_cyc_o;
wire [31:0] wbm_eth1_dat_i;
wire wbm_eth1_ack_i;
wire wbm_eth1_err_i;
wire wbm_eth1_rty_i;
wire [31:0] wbs_eth1_cfg_dat_o;
wire [31:0] wbs_eth1_cfg_dat_i;
wire [31:0] wbs_eth1_cfg_adr_i;
wire [3:0] wbs_eth1_cfg_sel_i;
wire [1:0] wbs_eth1_cfg_bte_i;
wire [2:0] wbs_eth1_cfg_cti_i;
wire wbs_eth1_cfg_stb_i;
wire wbs_eth1_cfg_cyc_i;
wire wbs_eth1_cfg_ack_o;
wire wbs_eth1_cfg_err_o;
parameter wbs_eth1_cfg_rty_o = 1'b0;
wire [31:0] wbs_mc_m_dat_o;
wire [31:0] wbs_mc_m_dat_i;
wire [31:0] wbs_mc_m_adr_i;
wire [3:0] wbs_mc_m_sel_i;
wire [1:0] wbs_mc_m_bte_i;
wire [2:0] wbs_mc_m_cti_i;
wire wbs_mc_m_stb_i;
wire wbs_mc_m_cyc_i;
wire wbs_mc_m_ack_o;
wire wbs_mc_m_err_o;
parameter wbs_mc_m_rty_o = 1'b0;
wire [31:0] wbs_spi_flash_dat_o;
wire [31:0] wbs_spi_flash_dat_i;
wire [31:0] wbs_spi_flash_adr_i;
wire [3:0] wbs_spi_flash_sel_i;
wire [1:0] wbs_spi_flash_bte_i;
wire [2:0] wbs_spi_flash_cti_i;
wire wbs_spi_flash_stb_i;
wire wbs_spi_flash_cyc_i;
wire wbs_spi_flash_ack_o;
parameter wbs_spi_flash_err_o = 1'b0;
parameter wbs_spi_flash_rty_o = 1'b0;
wire [31:0] wbs_uart0_dat_o;
wire [31:0] wbs_uart0_dat_i;
wire [31:0] wbs_uart0_adr_i;
wire [3:0] wbs_uart0_sel_i;
wire [1:0] wbs_uart0_bte_i;
wire [2:0] wbs_uart0_cti_i;
wire wbs_uart0_stb_i;
wire wbs_uart0_cyc_i;
wire wbs_uart0_ack_o;
parameter wbs_uart0_err_o = 1'b0;
parameter wbs_uart0_rty_o = 1'b0;
wire [31:0] wbs_ds1_dat_o;
wire [31:0] wbs_ds1_dat_i;
wire [31:0] wbs_ds1_adr_i;
wire [3:0] wbs_ds1_sel_i;
wire [1:0] wbs_ds1_bte_i;
wire [2:0] wbs_ds1_cti_i;
wire wbs_ds1_stb_i;
wire wbs_ds1_cyc_i;
wire wbs_ds1_ack_o;
parameter wbs_ds1_err_o = 1'b0;
parameter wbs_ds1_rty_o = 1'b0;
wire [31:0] wbs_usrrst_dat_o;
wire [31:0] wbs_usrrst_dat_i;
wire [31:0] wbs_usrrst_adr_i;
wire [3:0] wbs_usrrst_sel_i;
wire [1:0] wbs_usrrst_bte_i;
wire [2:0] wbs_usrrst_cti_i;
wire wbs_usrrst_stb_i;
wire wbs_usrrst_cyc_i;
wire wbs_usrrst_ack_o;
parameter wbs_usrrst_err_o = 1'b0;
parameter wbs_usrrst_rty_o = 1'b0;
wire [31:0] wbs_lfsr_dat_o;
wire [31:0] wbs_lfsr_dat_i;
wire [31:0] wbs_lfsr_adr_i;
wire [3:0] wbs_lfsr_sel_i;
wire [1:0] wbs_lfsr_bte_i;
wire [2:0] wbs_lfsr_cti_i;
wire wbs_lfsr_stb_i;
wire wbs_lfsr_cyc_i;
wire wbs_lfsr_ack_o;
parameter wbs_lfsr_err_o = 1'b0;
parameter wbs_lfsr_rty_o = 1'b0;
wire [31:0] wbs_gpio_dat_o;
wire [31:0] wbs_gpio_dat_i;
wire [31:0] wbs_gpio_adr_i;
wire [3:0] wbs_gpio_sel_i;
wire [1:0] wbs_gpio_bte_i;
wire [2:0] wbs_gpio_cti_i;
wire wbs_gpio_stb_i;
wire wbs_gpio_cyc_i;
wire wbs_gpio_ack_o;
parameter wbs_gpio_err_o = 1'b0;
parameter wbs_gpio_rty_o = 1'b0;
 
wire eth_clk;
wire [1:1] eth_int;
 
/* DCM0 wires */
wire dcm0_clk0_prebufg, dcm0_clk0;
wire dcm0_clkfx_prebufg, dcm0_clkfx;
wire dcm0_clkdv_prebufg, dcm0_clkdv;
wire dcm0_rst, dcm0_locked;
 
 
wb_conbus_top
#(.s0_addr_w(4), .s0_addr(4'h0), // MC
.s1_addr_w(4), .s1_addr(4'h8), // GPIO
.s27_addr_w(8),
.s2_addr(8'h92), // ETH Slave
.s3_addr(8'hb0), // SPI
.s4_addr(8'h90), // UART
.s5_addr(8'hc0), // DS1
.s6_addr(8'he0), // User Reset
.s7_addr(8'h1f)) // LFSR
wb_conbus
(
// Master 0
// Inputs
.m0_dat_i (wbm_or12_i_dat_o),
.m0_adr_i (wbm_or12_i_adr_o),
.m0_sel_i (wbm_or12_i_sel_o),
.m0_we_i (wbm_or12_i_we_o),
.m0_cyc_i (wbm_or12_i_cyc_o),
.m0_stb_i (wbm_or12_i_stb_o),
.m0_cab_i (1'b0),
// Outputs
.m0_dat_o (wbm_or12_i_dat_i),
.m0_ack_o (wbm_or12_i_ack_i),
.m0_err_o (wbm_or12_i_err_i),
.m0_rty_o (wbm_or12_i_rty_i),
 
// Master 1
// Inputs
.m1_dat_i (wbm_or12_debug_dat_o),
.m1_adr_i (wbm_or12_debug_adr_o),
.m1_sel_i (wbm_or12_debug_sel_o),
.m1_we_i (wbm_or12_debug_we_o),
.m1_cyc_i (wbm_or12_debug_cyc_o),
.m1_stb_i (wbm_or12_debug_stb_o),
.m1_cab_i (1'b0),
// Outputs
.m1_dat_o (wbm_or12_debug_dat_i),
.m1_ack_o (wbm_or12_debug_ack_i),
.m1_err_o (wbm_or12_debug_err_i),
.m1_rty_o (wbm_or12_debug_rty_i),
 
// Master 2
// Inputs
.m2_dat_i (wbm_or12_d_dat_o),
.m2_adr_i (wbm_or12_d_adr_o),
.m2_sel_i (wbm_or12_d_sel_o),
.m2_we_i (wbm_or12_d_we_o),
.m2_cyc_i (wbm_or12_d_cyc_o),
.m2_stb_i (wbm_or12_d_stb_o),
.m2_cab_i (1'b0),
// Outputs
.m2_dat_o (wbm_or12_d_dat_i),
.m2_ack_o (wbm_or12_d_ack_i),
.m2_err_o (wbm_or12_d_err_i),
.m2_rty_o (wbm_or12_d_rty_i),
 
// Master 3
// Inputs
.m3_dat_i (wbm_eth1_dat_o),
.m3_adr_i (wbm_eth1_adr_o),
.m3_sel_i (wbm_eth1_sel_o),
.m3_we_i (wbm_eth1_we_o),
.m3_cyc_i (wbm_eth1_cyc_o),
.m3_stb_i (wbm_eth1_stb_o),
.m3_cab_i (1'b0),
// Outputs
.m3_dat_o (wbm_eth1_dat_i),
.m3_ack_o (wbm_eth1_ack_i),
.m3_err_o (wbm_eth1_err_i),
.m3_rty_o (wbm_eth1_rty_i),
// Master 4
// Inputs
.m4_dat_i (0),
.m4_adr_i (0),
.m4_sel_i (4'h0),
.m4_we_i (1'b0),
.m4_cyc_i (1'b0),
.m4_stb_i (1'b0),
.m4_cab_i (1'b0),
// Outputs
//.m4_dat_o (),
//.m4_ack_o (),
//.m4_err_o (),
//.m4_rty_o (),
// Master 5
// Inputs
.m5_dat_i (0),
.m5_adr_i (0),
.m5_sel_i (4'h0),
.m5_we_i (1'b0),
.m5_cyc_i (1'b0),
.m5_stb_i (1'b0),
.m5_cab_i (1'b0),
// Outputs
//.m5_dat_o (),
//.m5_ack_o (),
//.m5_err_o (),
//.m5_rty_o (),
 
// Master 6
// Inputs
.m6_dat_i (0),
.m6_adr_i (0),
.m6_sel_i (4'h0),
.m6_we_i (1'b0),
.m6_cyc_i (1'b0),
.m6_stb_i (1'b0),
.m6_cab_i (1'b0),
// Outputs
//.m6_dat_o (),
//.m6_ack_o (),
//.m6_err_o (),
//.m6_rty_o (),
 
// Master 7
// Inputs
.m7_dat_i (0),
.m7_adr_i (0),
.m7_sel_i (4'h0),
.m7_we_i (1'b0),
.m7_cyc_i (1'b0),
.m7_stb_i (1'b0),
.m7_cab_i (1'b0),
// Outputs
//.m7_dat_o (),
//.m7_ack_o (),
//.m7_err_o (),
//.m7_rty_o (),
 
 
// Slave 0
// Inputs
.s0_dat_i (wbs_mc_m_dat_o),
.s0_ack_i (wbs_mc_m_ack_o),
.s0_err_i (wbs_mc_m_err_o),
.s0_rty_i (wbs_mc_m_rty_o),
// Outputs
.s0_dat_o (wbs_mc_m_dat_i),
.s0_adr_o (wbs_mc_m_adr_i),
.s0_sel_o (wbs_mc_m_sel_i),
.s0_we_o (wbs_mc_m_we_i),
.s0_cyc_o (wbs_mc_m_cyc_i),
.s0_stb_o (wbs_mc_m_stb_i),
//.s0_cab_o (),
 
// Slave 1
// Inputs
.s1_dat_i (wbs_gpio_dat_o),
.s1_ack_i (wbs_gpio_ack_o),
.s1_err_i (wbs_gpio_err_o),
.s1_rty_i (wbs_gpio_rty_o),
// Outputs
.s1_dat_o (wbs_gpio_dat_i),
.s1_adr_o (wbs_gpio_adr_i),
.s1_sel_o (wbs_gpio_sel_i),
.s1_we_o (wbs_gpio_we_i),
.s1_cyc_o (wbs_gpio_cyc_i),
.s1_stb_o (wbs_gpio_stb_i),
//.s1_cab_o (),
 
// Slave 2
// Inputs
.s2_dat_i (wbs_eth1_cfg_dat_o),
.s2_ack_i (wbs_eth1_cfg_ack_o),
.s2_err_i (wbs_eth1_cfg_err_o),
.s2_rty_i (wbs_eth1_cfg_rty_o),
// Outputs
.s2_dat_o (wbs_eth1_cfg_dat_i),
.s2_adr_o (wbs_eth1_cfg_adr_i),
.s2_sel_o (wbs_eth1_cfg_sel_i),
.s2_we_o (wbs_eth1_cfg_we_i),
.s2_cyc_o (wbs_eth1_cfg_cyc_i),
.s2_stb_o (wbs_eth1_cfg_stb_i),
//.s2_cab_o (),
 
// Slave 3
// Inputs
.s3_dat_i (wbs_spi_flash_dat_o),
.s3_ack_i (wbs_spi_flash_ack_o),
.s3_err_i (wbs_spi_flash_err_o),
.s3_rty_i (wbs_spi_flash_rty_o),
// Outputs
.s3_dat_o (wbs_spi_flash_dat_i),
.s3_adr_o (wbs_spi_flash_adr_i),
.s3_sel_o (wbs_spi_flash_sel_i),
.s3_we_o (wbs_spi_flash_we_i),
.s3_cyc_o (wbs_spi_flash_cyc_i),
.s3_stb_o (wbs_spi_flash_stb_i),
//.s3_cab_o (),
 
// Slave 4
// Inputs
.s4_dat_i (wbs_uart0_dat_o),
.s4_ack_i (wbs_uart0_ack_o),
.s4_err_i (wbs_uart0_err_o),
.s4_rty_i (wbs_uart0_rty_o),
// Outputs
.s4_dat_o (wbs_uart0_dat_i),
.s4_adr_o (wbs_uart0_adr_i),
.s4_sel_o (wbs_uart0_sel_i),
.s4_we_o (wbs_uart0_we_i),
.s4_cyc_o (wbs_uart0_cyc_i),
.s4_stb_o (wbs_uart0_stb_i),
//.s4_cab_o (),
 
// Slave 5
// Inputs
.s5_dat_i (wbs_ds1_dat_o),
.s5_ack_i (wbs_ds1_ack_o),
.s5_err_i (1'b0),
.s5_rty_i (1'b0),
// Outputs
.s5_dat_o (wbs_ds1_dat_i),
.s5_adr_o (wbs_ds1_adr_i),
.s5_sel_o (wbs_ds1_sel_i),
.s5_we_o (wbs_ds1_we_i),
.s5_cyc_o (wbs_ds1_cyc_i),
.s5_stb_o (wbs_ds1_stb_i),
.s5_cab_o (),
// Slave 6
// Inputs
.s6_dat_i (wbs_usrrst_dat_o),
.s6_ack_i (wbs_usrrst_ack_o),
.s6_err_i (1'b0),
.s6_rty_i (1'b0),
// Outputs
.s6_dat_o (wbs_usrrst_dat_i),
.s6_adr_o (wbs_usrrst_adr_i),
.s6_sel_o (wbs_usrrst_sel_i),
.s6_we_o (wbs_usrrst_we_i),
.s6_cyc_o (wbs_usrrst_cyc_i),
.s6_stb_o (wbs_usrrst_stb_i),
.s6_cab_o (),
 
// Slave 7
// Inputs
.s7_dat_i (wbs_lfsr_dat_o),
.s7_ack_i (wbs_lfsr_ack_o),
.s7_err_i (1'b0),
.s7_rty_i (1'b0),
// Outputs
.s7_dat_o (wbs_lfsr_dat_i),
.s7_adr_o (wbs_lfsr_adr_i),
.s7_sel_o (wbs_lfsr_sel_i),
.s7_we_o (wbs_lfsr_we_i),
.s7_cyc_o (wbs_lfsr_cyc_i),
.s7_stb_o (wbs_lfsr_stb_i),
.s7_cab_o (),
// Inputs
.clk_i (wb_clk),
.rst_i (wb_rst));
 
// Tie all cycle type identifiers (CTI) and burst type extension (BTE) signals low
// Not supported by this arbiter.
assign wbs_eth1_cfg_bte_i = 0;
assign wbs_eth1_cfg_cti_i = 0;
 
assign wbs_gpio_bte_i = 0;
assign wbs_gpio_cti_i = 0;
assign wbs_spi_flash_bte_i = 0;
assign wbs_spi_flash_cti_i = 0;
assign wbs_mc_m_bte_i = 0;
assign wbs_mc_m_cti_i = 0;
assign wbs_uart0_bte_i = 0;
assign wbs_uart0_cti_i = 0;
assign wbs_ds1_bte_i = 0;
assign wbs_ds1_cti_i = 0;
assign wbs_usrrst_bte_i = 0;
assign wbs_usrrst_cti_i = 0;
assign wbs_lfsr_bte_i = 0;
assign wbs_lfsr_cti_i = 0;
 
// Programmable interrupt controller lines (aka. IRQ lines)
assign pic_ints[30] = 1'b0;
assign pic_ints[29] = 1'b0;
assign pic_ints[28] = 1'b0;
assign pic_ints[27] = 1'b0;
assign pic_ints[26] = 1'b0;
assign pic_ints[25] = 1'b0;
assign pic_ints[24] = 1'b0;
assign pic_ints[23] = 1'b0;
assign pic_ints[22] = 1'b0;
assign pic_ints[21] = 1'b0;
assign pic_ints[20] = 1'b0;
assign pic_ints[19] = 1'b0;
assign pic_ints[18] = 1'b0;
assign pic_ints[17] = 1'b0;
assign pic_ints[16] = 1'b0;
assign pic_ints[15] = 1'b0;
assign pic_ints[14] = 1'b0;
assign pic_ints[13] = 1'b0;
assign pic_ints[12] = 1'b0;
assign pic_ints[11] = 1'b0;
assign pic_ints[10] = 1'b0;
assign pic_ints[9] = 1'b0;
assign pic_ints[8] = 1'b0;
assign pic_ints[7] = 1'b0;
assign pic_ints[6] = 1'b0;
assign pic_ints[5] = 1'b0;
assign pic_ints[4] = eth_int[1]; /* IRQ4, just like in Linux. Added jb 090716 */
assign pic_ints[3] = 1'b0;
assign pic_ints[2] = uart0_irq;
assign pic_ints[1] = 1'b0;
assign pic_ints[0] = 1'b0;
or1k_top i_or1k
(
.clk_i (wb_clk),
.rst_i (wb_rst),
.pic_ints_i (pic_ints[19:0]),
.iwb_clk_i (wb_clk),
.iwb_rst_i (wb_rst),
.iwb_ack_i (wbm_or12_i_ack_i),
.iwb_err_i (wbm_or12_i_err_i),
.iwb_rty_i (wbm_or12_i_rty_i),
.iwb_dat_i (wbm_or12_i_dat_i),
.iwb_cyc_o (wbm_or12_i_cyc_o),
.iwb_adr_o (wbm_or12_i_adr_o),
.iwb_stb_o (wbm_or12_i_stb_o),
.iwb_we_o (wbm_or12_i_we_o ),
.iwb_sel_o (wbm_or12_i_sel_o),
.iwb_cti_o (wbm_or12_i_cti_o),
.iwb_bte_o (wbm_or12_i_bte_o),
.dwb_clk_i (wb_clk),
.dwb_rst_i (wb_rst),
.dwb_ack_i (wbm_or12_d_ack_i),
.dwb_err_i (wbm_or12_d_err_i),
.dwb_rty_i (wbm_or12_d_rty_i),
.dwb_dat_i (wbm_or12_d_dat_i),
.dwb_cyc_o (wbm_or12_d_cyc_o),
.dwb_adr_o (wbm_or12_d_adr_o),
.dwb_stb_o (wbm_or12_d_stb_o),
.dwb_we_o (wbm_or12_d_we_o),
.dwb_sel_o (wbm_or12_d_sel_o),
.dwb_dat_o (wbm_or12_d_dat_o),
.dwb_cti_o (wbm_or12_d_cti_o),
.dwb_bte_o (wbm_or12_d_bte_o),
.dbgwb_clk_i (wb_clk),
.dbgwb_rst_i (wb_rst),
.dbgwb_ack_i (wbm_or12_debug_ack_i),
.dbgwb_err_i (wbm_or12_debug_err_i),
.dbgwb_dat_i (wbm_or12_debug_dat_i),
.dbgwb_cyc_o (wbm_or12_debug_cyc_o),
.dbgwb_adr_o (wbm_or12_debug_adr_o),
.dbgwb_stb_o (wbm_or12_debug_stb_o),
.dbgwb_we_o (wbm_or12_debug_we_o),
.dbgwb_sel_o (wbm_or12_debug_sel_o),
.dbgwb_dat_o (wbm_or12_debug_dat_o),
.dbgwb_cti_o (wbm_or12_debug_cti_o),
.dbgwb_bte_o (wbm_or12_debug_bte_o),
.tms_pad_i (dbg_tms_pad_i),
.tck_pad_i (dbg_tck),
.tdi_pad_i (dbg_tdi_pad_i),
.tdo_pad_o (dbg_tdo_pad_o),
.tdo_padoe_o ( )
);
 
`ifdef USE_SPI_FLASH
wire spi_flash_mosi, spi_flash_miso, spi_flash_sclk;
wire [1:0] spi_flash_ss;
spi_flash_top #
(
.divider(0),
.divider_len(2)
)
spi_flash_top0
(
.wb_clk_i(wb_clk),
.wb_rst_i(wb_rst),
.wb_adr_i(wbs_spi_flash_adr_i[4:2]),
.wb_dat_i(wbs_spi_flash_dat_i),
.wb_dat_o(wbs_spi_flash_dat_o),
.wb_sel_i(wbs_spi_flash_sel_i),
.wb_we_i(wbs_spi_flash_we_i),
.wb_stb_i(wbs_spi_flash_stb_i),
.wb_cyc_i(wbs_spi_flash_cyc_i),
.wb_ack_o(wbs_spi_flash_ack_o),
.mosi_pad_o(spi_flash_mosi),
.miso_pad_i(spi_flash_miso),
.sclk_pad_o(spi_flash_sclk),
.ss_pad_o(spi_flash_ss)
);
 
// SPI flash memory signals
assign spi_flash_mosi_pad_o = !spi_flash_ss[0] ? spi_flash_mosi : 1'b1;
assign spi_flash_sclk_pad_o = !spi_flash_ss[0] ? spi_flash_sclk : 1'b1;
assign spi_flash_ss_pad_o = spi_flash_ss[0];
assign spi_flash_w_n_pad_o = 1'b1;
assign spi_flash_hold_n_pad_o = 1'b1;
assign spi_sd_mosi_pad_o = !spi_flash_ss[1] ? spi_flash_mosi : 1'b1;
assign spi_sd_sclk_pad_o = !spi_flash_ss[1] ? spi_flash_sclk : 1'b1;
assign spi_sd_ss_pad_o = spi_flash_ss[1];
assign spi_flash_miso = !spi_flash_ss[0] ? spi_flash_miso_pad_i :
!spi_flash_ss[1] ? spi_sd_miso_pad_i :
1'b0;
`else // !`ifdef USE_SPI_FLASH
 
 
dummy_slave
# ( .value(32'hb0000000))
ds_spi
(
.dat_o(wbs_spi_flash_dat_o),
.stb_i(wbs_spi_flash_stb_i),
.cyc_i(wbs_spi_flash_cyc_i),
.ack_o(wbs_spi_flash_ack_o),
.clk(wb_clk),
.rst(wb_rst)
);
 
`endif // !`ifdef USE_SPI_FLASH
 
/* Memory module */
ml501_mc ml501_mc0
(
.wb_dat_i(wbs_mc_m_dat_i),
.wb_dat_o(wbs_mc_m_dat_o),
.wb_sel_i(wbs_mc_m_sel_i),
.wb_adr_i(wbs_mc_m_adr_i),
.wb_we_i (wbs_mc_m_we_i),
.wb_stb_i(wbs_mc_m_stb_i),
.wb_cyc_i(wbs_mc_m_cyc_i),
.wb_ack_o(wbs_mc_m_ack_o),
`ifdef ML501_MEMORY_SSRAM
.sram_clk(sram_clk),
.sram_addr(sram_flash_addr),
.sram_ce_l(sram_cen),
.sram_oe_l(sram_flash_oe_n),
.sram_we_l(sram_flash_we_n),
.sram_bw_l(sram_bw),
.sram_adv_ld_l(sram_adv_ld_n),
.sram_mode(sram_mode),
.sram_clk_fb(sram_clk_fb),
.sram_dq_io(sram_flash_data),
`endif // `ifdef ML501_MEMORY_SSRAM
 
`ifdef ML501_MEMORY_DDR2
.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(clk_200),
.ddr2_if_clk(dcm0_clkfx),
`endif // `ifdef ML501_MEMORY_DDR2
 
.clk_200(clk_200),
.wb_clk(wb_clk),
.wb_rst(wb_rst)
);
 
assign wbs_mc_m_err_o = 1'b0;
 
uart_top
#( 32, 5)
i_uart_0_top
(
.wb_dat_o (wbs_uart0_dat_o),
.wb_dat_i (wbs_uart0_dat_i),
.wb_sel_i (wbs_uart0_sel_i),
.wb_adr_i (wbs_uart0_adr_i[4:0]),
.wb_we_i (wbs_uart0_we_i),
.wb_stb_i (wbs_uart0_stb_i),
.wb_cyc_i (wbs_uart0_cyc_i),
.wb_ack_o (wbs_uart0_ack_o),
.wb_clk_i (wb_clk),
.wb_rst_i (wb_rst),
.int_o (uart0_irq),
.srx_pad_i (uart0_srx_pad_i),
.stx_pad_o (uart0_stx_pad_o),
.cts_pad_i (1'b0),
.rts_pad_o ( ),
.dtr_pad_o ( ),
.dcd_pad_i (1'b0),
.dsr_pad_i (1'b0),
.ri_pad_i (1'b0)
);
 
`ifdef USE_ETHERNET
 
wire phy_smi_data_i, phy_smi_data_o, phy_smi_data_dir;
eth_top eth_top1
(
.wb_clk_i(wb_clk),
.wb_rst_i(wb_rst),
.wb_dat_i(wbs_eth1_cfg_dat_i),
.wb_dat_o(wbs_eth1_cfg_dat_o),
.wb_adr_i(wbs_eth1_cfg_adr_i[11:2]),
.wb_sel_i(wbs_eth1_cfg_sel_i),
.wb_we_i(wbs_eth1_cfg_we_i),
.wb_cyc_i(wbs_eth1_cfg_cyc_i),
.wb_stb_i(wbs_eth1_cfg_stb_i),
.wb_ack_o(wbs_eth1_cfg_ack_o),
.wb_err_o(wbs_eth1_cfg_err_o),
 
.m_wb_adr_o(wbm_eth1_adr_o),
.m_wb_sel_o(wbm_eth1_sel_o),
.m_wb_we_o(wbm_eth1_we_o),
.m_wb_dat_o(wbm_eth1_dat_o),
.m_wb_dat_i(wbm_eth1_dat_i),
.m_wb_cyc_o(wbm_eth1_cyc_o),
.m_wb_stb_o(wbm_eth1_stb_o),
.m_wb_ack_i(wbm_eth1_ack_i),
.m_wb_err_i(wbm_eth1_err_i),
.m_wb_cti_o(wbm_eth1_cti_o),
.m_wb_bte_o(wbm_eth1_bte_o),
.mtx_clk_pad_i(phy_tx_clk),
.mtxd_pad_o(phy_tx_data),
.mtxen_pad_o(phy_tx_en),
.mtxerr_pad_o(phy_tx_er),
.mrx_clk_pad_i(phy_rx_clk),
.mrxd_pad_i(phy_rx_data),
.mrxdv_pad_i(phy_dv),
.mrxerr_pad_i(phy_rx_er),
.mcoll_pad_i(phy_col),
.mcrs_pad_i(phy_crs),
.mdc_pad_o(phy_smi_clk),
.md_pad_i(phy_smi_data_i),
.md_pad_o(phy_smi_data_o),
.md_padoe_o(phy_smi_data_dir),
.int_o(eth_int[1])
);
 
// Xilinx primitive
IOBUF iobuf_phy_smi_data
(
// Outputs
.O (phy_smi_data_i),
// Inouts
.IO (phy_smi_data),
// Inputs
.I (phy_smi_data_o),
.T (!phy_smi_data_dir));
 
assign phy_rst_n = !wb_rst;
`else // !`ifdef USE_ETHERNET
// If ethernet core is disabled, still ack anyone who tries
// to access its config port. This allows linux to boot in
// the verilated ORPSoC.
dummy_slave
# ( .value(32'h92000000))
ds_eth1_cfg
(
.dat_o(wbs_eth1_cfg_dat_o),
.stb_i(wbs_eth1_cfg_stb_i),
.cyc_i(wbs_eth1_cfg_cyc_i),
.ack_o(wbs_eth1_cfg_ack_o),
.clk(wb_clk),
.rst(wb_rst)
);
assign wbs_eth1_cfg_err_o = 0;
 
// Tie off ethernet master ctrl signals
assign wbm_eth1_adr_o = 0;
assign wbm_eth1_sel_o = 0;
assign wbm_eth1_we_o = 0;
assign wbm_eth1_dat_o = 0;
assign wbm_eth1_cyc_o = 0;
assign wbm_eth1_stb_o = 0;
assign wbm_eth1_cti_o = 0;
assign wbm_eth1_bte_o = 0;
`endif // `ifdef USE_ETHERNET
ml501_gpio ml501_gpio0
(
// WB
.dat_o (wbs_gpio_dat_o),
.dat_i (wbs_gpio_dat_i),
.ack_o (wbs_gpio_ack_o),
.adr_i (wbs_gpio_adr_i[2:0]),
.sel_i (wbs_gpio_sel_i[3:0]),
.stb_i (wbs_gpio_stb_i),
.cyc_i (wbs_gpio_cyc_i),
.we_i (wbs_gpio_we_i),
.gpio (gpio),
// Inputs
.clk (wb_clk),
.rst (wb_rst));
 
defparam ml501_gpio0.gpio_width = 26;
wb_lfsr lfsr0
(
// Outputs
.wb_dat_o (wbs_lfsr_dat_o),
.wb_ack_o (wbs_lfsr_ack_o),
// Inputs
.wb_clk (wb_clk),
.wb_rst (wb_rst),
.wb_adr_i (wbs_lfsr_adr_i[2:0]),
.wb_dat_i (wbs_lfsr_dat_i),
.wb_cyc_i (wbs_lfsr_cyc_i),
.wb_stb_i (wbs_lfsr_stb_i),
.wb_we_i (wbs_lfsr_we_i));
 
dummy_slave
# ( .value(32'hc0000000))
ds1
(
.dat_o(wbs_ds1_dat_o),
.stb_i(wbs_ds1_stb_i),
.cyc_i(wbs_ds1_cyc_i),
.ack_o(wbs_ds1_ack_o),
.clk(wb_clk),
.rst(wb_rst)
);
 
usr_rst usr_rst0
(
// Outputs
.usr_rst_out (usr_rst_out),
// Inputs
.wb_clk (wb_clk),
.wb_rst (wb_rst),
.wb_cyc_i (wbs_usrrst_cyc_i),
.wb_stb_i (wbs_usrrst_stb_i),
.wb_ack_o (wbs_usrrst_ack_o));
assign wbs_usrrst_dat_o = 0;
/* Reset and clock stuff */
reset_debounce reset_debounce0
(
.sys_rst_in(sys_rst_in),
.usr_rst_in(usr_rst_in),
.sys_clk_in(sys_clk_in),
.dcm0_clk(dcm0_clk0),
.dcm0_locked(dcm0_locked),
.rst_dcm0(dcm0_rst),
.rst(wb_rst)
);
/* 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 (dcm0_rst));
// 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));
 
IBUFGDS_LVPECL_25 sys_clk_in_ibufds
(
.O(sys_clk_in_200),
.I(sys_clk_in_p),
.IB(sys_clk_in_n));
 
assign wb_clk = dcm0_clkdv;
assign dbg_tck = dbg_tck_pad_i;
//assign clk_200 = sys_clk_in_200;
assign clk_200 = dcm0_clk0;
endmodule
/openrisc/trunk/orpsocv2/boards/xilinx/ml501/rtl/usr_rst.v
0,0 → 1,61
//////////////////////////////////////////////////////////////////////
//// ////
//// User controllable reset generation ////
//// ////
//// Description ////
//// Pulls a signal low when accessed. This signal should be ////
//// looped back out of the design and back into the reset ////
//// module, resetting the system. ////
//// ////
//// 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 ////
//// ////
//////////////////////////////////////////////////////////////////////
module usr_rst(wb_clk, wb_rst, wb_cyc_i, wb_stb_i, wb_ack_o, usr_rst_out);
input wb_clk, wb_rst, wb_cyc_i, wb_stb_i;
output reg wb_ack_o;
output usr_rst_out;
 
 
always @(posedge wb_clk)
if (wb_rst)
wb_ack_o <= 0;
else if (wb_cyc_i & wb_stb_i & !wb_ack_o)
wb_ack_o <= 1;
else
wb_ack_o <= 0;
// Generate an active low reset pulse when this module is accessed.
// We don't generate ACKs because the thing will be reset anyway...
assign usr_rst_out = !(wb_cyc_i & wb_stb_i & !wb_rst);
 
endmodule // usr_rst
/openrisc/trunk/orpsocv2/boards/xilinx/ml501/rtl/ml501_ddr2_wb_if_cache.v
0,0 → 1,252
/*******************************************************************************
* 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 ml501_ddr2_wb_if_cache.v when simulating
// the core, ml501_ddr2_wb_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 ml501_ddr2_wb_if_cache(
clka,
ena,
wea,
addra,
dina,
douta,
clkb,
enb,
web,
addrb,
dinb,
doutb);
 
 
input clka;
input ena;
input [3 : 0] wea;
input [2 : 0] addra;
input [31 : 0] dina;
output [31 : 0] douta;
input clkb;
input enb;
input [15 : 0] web;
input [0 : 0] addrb;
input [127 : 0] dinb;
output [127 : 0] doutb;
 
// synthesis translate_off
 
BLK_MEM_GEN_V3_1 #(
.C_ADDRA_WIDTH(3),
.C_ADDRB_WIDTH(1),
.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(8),
.C_READ_DEPTH_B(2),
.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("NONE"),
.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(8),
.C_WRITE_DEPTH_B(2),
.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_wb_if_cache is "black_box"
 
endmodule
 
/*
 
module ml501_ddr2_wb_if_cache(
wb_clk,
wb_addr,
wb_di,
wb_do,
wb_we,
wb_sel,
wb_en,
 
ddr2_clk,
ddr2_addr,
ddr2_di,
ddr2_do,
ddr2_we
);
input wb_clk;
input [2:0] wb_addr;
input [31:0] wb_di;
output [31:0] wb_do;
input wb_we;
input [3:0] wb_sel;
input wb_en;
input ddr2_clk;
input ddr2_addr;
input [127:0] ddr2_di;
output [127:0] ddr2_do;
input ddr2_we;
wire [3:0] wb_sel_we;
assign wb_sel_we = {4{wb_we}} & wb_sel;
// Didn't want to work!?
 
genvar i;
generate
for (i = 0; i < 4; i = i + 1) begin: gen_rambs
// RAMB36: 32k+4k Parity Paramatizable True Dual-Port BlockRAM
// Virtex-5
// Xilinx HDL Libraries Guide, version 10.1.2
RAMB36 #(
.SIM_MODE("SAFE"), // Simulation: "SAFE" vs. "FAST", see "Synthesis and Simulation Design Guide" for details
.DOA_REG(0), // Optional output registers on A port (0 or 1)
.DOB_REG(0), // Optional output registers on B port (0 or 1)
.INIT_A(36'h000000000), // Initial values on A output port
.INIT_B(36'h000000000), // Initial values on B output port
.RAM_EXTENSION_A("NONE"), // "UPPER", "LOWER" or "NONE" when cascaded
.RAM_EXTENSION_B("NONE"), // "UPPER", "LOWER" or "NONE" when cascaded
.READ_WIDTH_A(9), // Valid values are 1, 2, 4, 9, 18, or 36
.READ_WIDTH_B(36), // Valid values are 1, 2, 4, 9, 18, or 36
.SIM_COLLISION_CHECK("NONE"), // Collision check enable "ALL", "WARNING_ONLY",
// "GENERATE_X_ONLY" or "NONE"
.SRVAL_A(36'h000000000), // Set/Reset value for A port output
.SRVAL_B(36'h000000000), // Set/Reset value for B port output
.WRITE_MODE_A("WRITE_FIRST"), // "WRITE_FIRST", "READ_FIRST", or "NO_CHANGE"
.WRITE_MODE_B("WRITE_FIRST"), // "WRITE_FIRST", "READ_FIRST", or "NO_CHANGE"
.WRITE_WIDTH_A(9), // Valid values are 1, 2, 4, 9, 18, or 36
.WRITE_WIDTH_B(36) // Valid values are 1, 2, 4, 9, 18, or 36
) ddr2_if_cache0
(
//.CASCADEOUTLATA(CASCADEOUTLATA), // 1-bit cascade A latch output
//.CASCADEOUTLATB(CASCADEOUTLATB), // 1-bit cascade B latch output
//.CASCADEOUTREGA(CASCADEOUTREGA), // 1-bit cascade A register output
//.CASCADEOUTREGB(CASCADEOUTREGB), // 1-bit cascade B register output
.DOA(wb_do[(i+1)*8-1:(i*8)]), // 8-bit A port data output
.DOB(ddr2_do[(i+1)*32-1:i*32]), // 32-bit B port data output
// .DOPA(DOPA), // A port parity data output
// .DOPB(DOPB), // B port parity data output
.ADDRA(wb_addr), // A port address input
.ADDRB(ddr2_addr), // B port address input
.CASCADEINLATA(0), // 1-bit cascade A latch input
.CASCADEINLATB(0), // 1-bit cascade B latch input
.CASCADEINREGA(0), // 1-bit cascade A register input
.CASCADEINREGB(0), // 1-bit cascade B register input
.CLKA(wb_clk), // 1-bit A port clock input
.CLKB(ddr2_clk), // 1-bit B port clock input
.DIA(wb_di[(i+1)*8-1:(i*8)]), // 8-bit A port data input
.DIB(ddr2_di[(i+1)*32-1:i*32]), // 32-bit B port data input
.DIPA(0), // 4-bit A port parity data input
.DIPB(0), // 4-bit B port parity data input
.ENA(wb_en), // 1-bit A port enable input
.ENB(~wb_en), // 1-bit B port enable input
.REGCEA(0), // 1-bit A port register enable input
.REGCEB(0), // 1-bit B port register enable input
.SSRA(0), // 1-bit A port set/reset input
.SSRB(0), // 1-bit B port set/reset input
.WEA(wb_sel_we[i]), // 4-bit A port write enable input
.WEB(ddr2_we) // 4-bit B port write enable input
);
end // for (i = 0; i < 4; i = i + 1)
endgenerate
*/
/openrisc/trunk/orpsocv2/boards/xilinx/ml501/rtl/uart_defines.v
0,0 → 1,253
//////////////////////////////////////////////////////////////////////
//// ////
//// 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: uart_defines.v,v $
// Revision 1.14 2003/09/12 07:26:58 dries
// adjusted comment + define
//
// 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
//
//
 
// Uncomment to get synchronous read memories. Note read on neg edge
//`define SYNC_RAM
 
// 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
 
 
 
 
 
 
 
/openrisc/trunk/orpsocv2/boards/xilinx/ml501/par/ml501_xst.ucf
0,0 → 1,931
######################################################################
#
# UCF file for ML501 PAR
#
######################################################################
 
#------------------------------------------------------------------------------
# ZBT SSRAM controller multi-cycle path constraints (ssram_controller)
#------------------------------------------------------------------------------
 
# Define the two clock domains as timespecs
#NET dcm0_clkdv TNM_NET="wb_clk";
#TIMESPEC "TS_wb_clk" = PERIOD "wb_clk" 20 ns HIGH 10;
#NET dcm0_clk0 TNM_NET = "ssram_clk200";
#TIMESPEC "TS_ssram_clk200" = PERIOD "ssram_clk200" "TS_wb_clk" / 4;
 
# Now define their relationship - logic should be configured so that there's
# 1 WB cycle at all times before anything is sampled across domains
#TIMESPEC "TS_wb_clk_ssram_clk200" = from "wb_clk" TO "ssram_clk200" 15 ns;
#TIMESPEC "TS_ssram_clk200_wb_clk" = from "ssram_clk200" TO "wb_clk" 15 ns;
 
#------------------------------------------------------------------------------
# Pins used
#------------------------------------------------------------------------------
 
# 100MHz fixed freq clock.
NET sys_clk_in LOC = AD8;
NET sys_clk_in IOSTANDARD = LVCMOS33;
NET "sys_clk_in" TNM_NET = "sys_clk_in";
TIMESPEC "TS_sys_clk_in" = PERIOD "sys_clk_in" 10 ns HIGH 50.00%;
 
NET sys_clk_in_p LOC = E16;
NET sys_clk_in_n LOC = E17;
NET sys_clk_in_p IOSTANDARD = LVDS_25;
NET sys_clk_in_n IOSTANDARD = LVDS_25;
INST *sys_clk_in_ibufds DIFF_TERM=TRUE;
 
NET sys_rst_in LOC = T23 | IOSTANDARD = LVDCI_33;
NET sys_rst_in PULLUP;
NET sys_rst_in TIG;
 
 
#------------------------------------------------------------------------------
# User Reset pins (hook up so user can reset system from processor)
#------------------------------------------------------------------------------
 
NET usr_rst_out LOC = P20 | IOSTANDARD = LVCMOS25; # HDR2_62
NET usr_rst_out PULLUP;
NET usr_rst_out TIG;
NET usr_rst_in LOC = P21 | IOSTANDARD = LVCMOS25; # HDR2_64
NET usr_rst_in PULLUP;
NET usr_rst_in TIG;
 
#------------------------------------------------------------------------------
# All pins for ML501
#------------------------------------------------------------------------------
 
#NET "sys_clk_s" TNM_NET = "sys_clk";
#TIMESPEC "TSSYSCLK" = PERIOD "sys_clk" 10 ns HIGH 50 %;
#NET "sys_clk_in_200" TNM_NET = "sys_clk_in_200";
#TIMESPEC "TSSYSCLK200" = PERIOD "sys_clk_in_200" 5 ns HIGH 50 %;
 
#NET sys_clk_in_p LOC = E16;
#NET sys_clk_in_n LOC = E17;
#NET sys_clk_in_p IOSTANDARD = LVDS_25;
#NET sys_clk_in_n IOSTANDARD = LVDS_25;
#INST *sys_clk_in_ibufds DIFF_TERM=TRUE;
 
#NET sys_rst_pin LOC = T23 | IOSTANDARD = LVCMOS33 | PULLUP;
 
#NET Interrupt TIG;
 
# Reset timing ignore - treat as async paths
#NET sys_rst_s TIG;
#NET opb_v20_0_OPB_Rst TIG;
#NET lmb_v10_1_OPB_Rst TIG;
#NET lmb_v10_0_OPB_Rst TIG;
#NET opb_v20_0_Debug_SYS_Rst TIG;
#NET plb_v34_0_PLB_Rst TIG;
#NET dcm_locked TIG;
 
#------------------------------------------------------------------------------
# OpenCores JTAG Debug signals and User UART on EXP Header pins
#------------------------------------------------------------------------------
 
#NET uart0_srx_pad_i LOC = K20; # HDR1_12
NET uart0_srx_pad_i LOC = F25; # HDR2_2
NET uart0_srx_pad_i TIG;
NET uart0_srx_pad_i PULLUP;
NET uart0_srx_pad_i IOSTANDARD = LVCMOS25;
 
#NET uart0_stx_pad_o LOC = M22; # HDR1_10
NET uart0_stx_pad_o LOC = F24; # HDR2_4
NET uart0_stx_pad_o TIG;
NET uart0_stx_pad_o PULLUP;
NET uart0_stx_pad_o IOSTANDARD = LVCMOS25;
 
NET dbg_tdo_pad_o LOC = E26; # HDR2_6
NET dbg_tdi_pad_i LOC = E25; # HDR2_8
NET dbg_tms_pad_i LOC = G22; # HDR2_10
NET dbg_tck_pad_i LOC = G21; # HDR2_12
 
NET dbg_tdo_pad_o TIG; NET dbg_tdo_pad_o PULLUP; NET dbg_tdo_pad_o IOSTANDARD = LVCMOS25;
NET dbg_tdi_pad_i TIG; NET dbg_tdi_pad_i PULLUP; NET dbg_tdi_pad_i IOSTANDARD = LVCMOS25;
NET dbg_tms_pad_i TIG; NET dbg_tms_pad_i PULLUP; NET dbg_tms_pad_i IOSTANDARD = LVCMOS25;
NET dbg_tck_pad_i TIG; NET dbg_tck_pad_i PULLUP; NET dbg_tck_pad_i IOSTANDARD = LVCMOS25;
# Overide the following mapping error:
# ERROR:Place:645 - A clock IOB clock component is not placed at an optimal clock
# IOB site.
NET "dbg_tck_pad_i" CLOCK_DEDICATED_ROUTE = FALSE;
 
#////////////////////////////////////////////////////////////////////////////
#// Buttons, LEDs, Piezo, and DIP Switches
#////////////////////////////////////////////////////////////////////////////
 
# GPLED
NET gpio<0> LOC = E11; #GPLED7 (Rightmost - LSB)
NET gpio<1> LOC = E10; #GPLED6
NET gpio<2> LOC = E15; #GPLED5
NET gpio<3> LOC = D15; #GPLED4
NET gpio<4> LOC = F12; #GPLED3
NET gpio<5> LOC = E12; #GPLED2
NET gpio<6> LOC = D14; #GPLED1
NET gpio<7> LOC = E13; #GPLED0 (Leftmost - MSB)
 
NET gpio<0> IOSTANDARD = LVCMOS25;
NET gpio<1> IOSTANDARD = LVCMOS25;
NET gpio<2> IOSTANDARD = LVCMOS25;
NET gpio<3> IOSTANDARD = LVCMOS25;
NET gpio<4> IOSTANDARD = LVCMOS25;
NET gpio<5> IOSTANDARD = LVCMOS25;
NET gpio<6> IOSTANDARD = LVCMOS25;
NET gpio<7> IOSTANDARD = LVCMOS25;
 
# North-East-South-West-Center LEDs
NET gpio<8> LOC = T22; # C LED
NET gpio<9> LOC = AA18; # W LED
NET gpio<10> LOC = AA8; # S LED
NET gpio<11> LOC = Y18; # E LED
NET gpio<12> LOC = Y8; # N LED
NET gpio<8> IOSTANDARD = LVCMOS33;
NET gpio<9> IOSTANDARD = LVCMOS33;
NET gpio<10> IOSTANDARD = LVCMOS33;
NET gpio<11> IOSTANDARD = LVCMOS33;
NET gpio<12> IOSTANDARD = LVCMOS33;
 
# North-East-South-West-Center Buttons
NET gpio<13> LOC = B21; # C Button
NET gpio<14> LOC = C21; # W Button
NET gpio<15> LOC = B22; # S Button
NET gpio<16> LOC = A23; # E Button
NET gpio<17> LOC = A22; # N Button
NET gpio<13> IOSTANDARD = LVCMOS33;
NET gpio<14> IOSTANDARD = LVCMOS33;
NET gpio<15> IOSTANDARD = LVCMOS33;
NET gpio<16> IOSTANDARD = LVCMOS33;
NET gpio<17> IOSTANDARD = LVCMOS33;
 
# Dip Switches 1-8
NET gpio<18> LOC = T7; # DIP SW 8
NET gpio<19> LOC = U7; # DIP SW 7
NET gpio<20> LOC = U5; # DIP SW 6
NET gpio<21> LOC = U6; # DIP SW 5
NET gpio<22> LOC = T5; # DIP SW 4
NET gpio<23> LOC = T4; # DIP SW 3
NET gpio<24> LOC = V3; # DIP SW 2
NET gpio<25> LOC = U4; # DIP SW 1
NET gpio<18> IOSTANDARD = LVCMOS18;
NET gpio<19> IOSTANDARD = LVCMOS18;
NET gpio<20> IOSTANDARD = LVCMOS18;
NET gpio<21> IOSTANDARD = LVCMOS18;
NET gpio<22> IOSTANDARD = LVCMOS18;
NET gpio<23> IOSTANDARD = LVCMOS18;
NET gpio<24> IOSTANDARD = LVCMOS18;
NET gpio<25> IOSTANDARD = LVCMOS18;
 
#SMA Connectors
#NET gpio<22> LOC = F10; # SMA_IN_N
#NET gpio<23> LOC = F9; # SMA_IN_P
#NET gpio<24> LOC = F19; # SMA_OUT_N
#NET gpio<25> LOC = E18; # SMA_OUT_P
#NET gpio<26> LOC = AD8; # USERCLK
#NET gpio<22> IOSTANDARD = LVCMOS25;
#NET gpio<23> IOSTANDARD = LVCMOS25;
#NET gpio<24> IOSTANDARD = LVCMOS25;
#NET gpio<25> IOSTANDARD = LVCMOS25;
#NET gpio<26> IOSTANDARD = LVCMOS33;
 
NET "gpio<*>" PULLDOWN;
NET "gpio<*>" TIG;
NET "gpio<*>" SLEW = SLOW;
NET "gpio<*>" DRIVE = 2;
 
#NET "gpio<22>" SLEW = FAST;
#NET "gpio<22>" DRIVE = 12;
#NET "gpio<23>" SLEW = FAST;
#NET "gpio<23>" DRIVE = 12;
#NET "gpio<24>" SLEW = FAST;
#NET "gpio<24>" DRIVE = 12;
#NET "gpio<25>" SLEW = FAST;
#NET "gpio<25>" DRIVE = 12;
 
## #NET "gpio2_d_out<*>" TIG;
## #NET "gpio2_t_out<*>" TIG;
## NET "gpio2_in<*>" TIG;
 
## NET "piezo" LOC = V1;
## NET "piezo" IOSTANDARD = LVCMOS18;
## NET "piezo" TIG;
 
## #------------------------------------------------------------------------------
## # IO Pad Location Constraints / Properties for PS/2 Ports
## #------------------------------------------------------------------------------
 
## #Keyboard
## NET ps2_keyb_clk LOC = J1;
## NET ps2_keyb_clk SLEW = SLOW;
## NET ps2_keyb_clk DRIVE = 2;
## NET ps2_keyb_clk IOSTANDARD = LVCMOS18;
## NET ps2_keyb_clk TIG;
## NET ps2_keyb_data LOC = H2;
## NET ps2_keyb_data SLEW = SLOW;
## NET ps2_keyb_data DRIVE = 2;
## NET ps2_keyb_data IOSTANDARD = LVCMOS18;
## NET ps2_keyb_data TIG;
 
## #Mouse
## NET ps2_mouse_clk LOC = L2;
## NET ps2_mouse_clk SLEW = SLOW;
## NET ps2_mouse_clk DRIVE = 2;
## NET ps2_mouse_clk IOSTANDARD = LVCMOS18;
## NET ps2_mouse_clk TIG;
## NET ps2_mouse_data LOC = K1;
## NET ps2_mouse_data SLEW = SLOW;
## NET ps2_mouse_data DRIVE = 2;
## NET ps2_mouse_data IOSTANDARD = LVCMOS18;
## NET ps2_mouse_data TIG;
 
## #------------------------------------------------------------------------------
## # IO Pad Location Constraints / Properties for IIC Controller
## #------------------------------------------------------------------------------
 
## NET iic_scl LOC = R20;
## NET iic_sda LOC = T20;
## NET iic_scl SLEW = SLOW;
## NET iic_scl DRIVE = 6;
## NET iic_scl TIG;
## NET iic_scl IOSTANDARD = LVCMOS33;
## NET iic_sda SLEW = SLOW;
## NET iic_sda DRIVE = 6;
## NET iic_sda TIG;
## NET iic_sda IOSTANDARD = LVCMOS33;
 
## NET ddr2_iic_scl LOC = Y7;
## NET ddr2_iic_sda LOC = AA7;
## NET ddr2_iic_scl SLEW = SLOW;
## NET ddr2_iic_scl DRIVE = 6;
## NET ddr2_iic_scl TIG;
## NET ddr2_iic_scl IOSTANDARD = LVCMOS18;
## NET ddr2_iic_sda SLEW = SLOW;
## NET ddr2_iic_sda DRIVE = 6;
## NET ddr2_iic_sda TIG;
## NET ddr2_iic_sda IOSTANDARD = LVCMOS18;
 
## #------------------------------------------------------------------------------
## # IO Pad Location Constraints / Properties for System ACE MPU / USB
## #------------------------------------------------------------------------------
 
## NET sysace_clk_in LOC = AB12;
## NET sysace_clk_in IOSTANDARD = LVCMOS33;
## NET sysace_clk_in TNM_NET = "sysace_clk_in";
## # Leave 1 ns margin
## TIMESPEC "TSSYSACE" = PERIOD "sysace_clk_in" 29 ns;
 
## NET sace_usb_a<0> LOC = N6;
## NET sace_usb_a<1> LOC = E5;
## NET sace_usb_a<2> LOC = F5;
## NET sace_usb_a<3> LOC = F4;
## NET sace_usb_a<4> LOC = J5;
## NET sace_usb_a<5> LOC = E7;
## NET sace_usb_a<6> LOC = G7;
## NET sace_usb_a<*> IOSTANDARD = LVCMOS33;
## NET sace_usb_a<*> SLEW = FAST;
## NET sace_usb_a<*> DRIVE = 8;
## NET sace_mpce LOC = F7;
## NET sace_mpce IOSTANDARD = LVCMOS33;
## NET sace_mpce SLEW = FAST;
## NET sace_mpce DRIVE = 8;
## NET sace_usb_d<0> LOC = M6;
## NET sace_usb_d<1> LOC = K5;
## NET sace_usb_d<2> LOC = L3;
## NET sace_usb_d<3> LOC = L4;
## NET sace_usb_d<4> LOC = L7;
## NET sace_usb_d<5> LOC = L5;
## NET sace_usb_d<6> LOC = H6;
## NET sace_usb_d<7> LOC = G5;
## NET sace_usb_d<8> LOC = M7;
## NET sace_usb_d<9> LOC = H7;
## NET sace_usb_d<10> LOC = J6;
## NET sace_usb_d<11> LOC = G4;
## NET sace_usb_d<12> LOC = K7;
## NET sace_usb_d<13> LOC = J4;
## NET sace_usb_d<14> LOC = H4;
## NET sace_usb_d<15> LOC = K6;
## NET sace_usb_d<*> IOSTANDARD = LVCMOS33;
## NET sace_usb_d<*> SLEW = FAST;
## NET sace_usb_d<*> DRIVE = 8;
## NET sace_usb_d<*> PULLDOWN;
## NET sace_usb_oen LOC = E6;
## NET sace_usb_oen IOSTANDARD = LVCMOS33;
## NET sace_usb_oen SLEW = FAST;
## NET sace_usb_oen DRIVE = 8;
## NET sace_usb_wen LOC = M5;
## NET sace_usb_wen IOSTANDARD = LVCMOS33;
## NET sace_usb_wen SLEW = FAST;
## NET sace_usb_wen DRIVE = 8;
## NET sysace_mpirq LOC = G6;
## NET sysace_mpirq IOSTANDARD = LVCMOS33;
## NET sysace_mpirq TIG;
## NET sysace_mpirq PULLDOWN;
 
## NET usb_csn LOC = N3;
## NET usb_csn IOSTANDARD = LVCMOS33;
## NET usb_csn SLEW = FAST;
## NET usb_csn DRIVE = 8;
## NET usb_hpi_reset_n LOC = P3;
## NET usb_hpi_reset_n IOSTANDARD = LVCMOS33;
## NET usb_hpi_reset_n TIG;
## NET usb_hpi_int LOC = M4;
## NET usb_hpi_int IOSTANDARD = LVCMOS33;
## NET usb_hpi_int TIG;
## NET usb_hpi_int PULLDOWN;
 
## ////////////////////////////////////////////////////////////////////////////
## // Misc Board Signals
## ////////////////////////////////////////////////////////////////////////////
 
## NET plb_error LOC = N4; # Bus Error 1
## NET plb_error IOSTANDARD = LVCMOS33;
## NET plb_error TIG;
## NET opb_error LOC = P5; # Bus Error 2
## NET opb_error IOSTANDARD = LVCMOS33;
## NET opb_error TIG;
 
## #------------------------------------------------------------------------------
## # IO Pad Location Constraints / Properties for Expansion Header GPIO
## #------------------------------------------------------------------------------
 
## NET gpio_exp_hdr1<31> LOC = AB26; # HDR1_64
## NET gpio_exp_hdr1<30> LOC = AC26; # HDR1_62
## NET gpio_exp_hdr1<29> LOC = AA25; # HDR1_60
## NET gpio_exp_hdr1<28> LOC = P26; # HDR1_58
## NET gpio_exp_hdr1<27> LOC = Y26; # HDR1_56
## NET gpio_exp_hdr1<26> LOC = Y25; # HDR1_54
## NET gpio_exp_hdr1<25> LOC = W26; # HDR1_52
## NET gpio_exp_hdr1<24> LOC = W25; # HDR1_50
## NET gpio_exp_hdr1<23> LOC = U25; # HDR1_48
## NET gpio_exp_hdr1<22> LOC = U24; # HDR1_46
## NET gpio_exp_hdr1<21> LOC = T25; # HDR1_44
## NET gpio_exp_hdr1<20> LOC = T24; # HDR1_42
## NET gpio_exp_hdr1<19> LOC = P24; # HDR1_40
## NET gpio_exp_hdr1<18> LOC = P25; # HDR1_38
## NET gpio_exp_hdr1<17> LOC = N26; # HDR1_36
## NET gpio_exp_hdr1<16> LOC = AB25; # HDR1_34
## NET gpio_exp_hdr1<15> LOC = M24; # HDR1_32
## NET gpio_exp_hdr1<14> LOC = N24; # HDR1_30
## NET gpio_exp_hdr1<13> LOC = M25; # HDR1_28
## NET gpio_exp_hdr1<12> LOC = M26; # HDR1_26
## NET gpio_exp_hdr1<11> LOC = K25; # HDR1_24
## NET gpio_exp_hdr1<10> LOC = K26; # HDR1_22
## NET gpio_exp_hdr1<9> LOC = L24; # HDR1_20
## NET gpio_exp_hdr1<8> LOC = L25; # HDR1_18
## NET gpio_exp_hdr1<7> LOC = M21; # HDR1_16
## NET gpio_exp_hdr1<6> LOC = K21; # HDR1_14
## NET gpio_exp_hdr1<5> LOC = K20; # HDR1_12
## NET gpio_exp_hdr1<4> LOC = M22; # HDR1_10
## NET gpio_exp_hdr1<3> LOC = H23; # HDR1_8
## NET gpio_exp_hdr1<2> LOC = J21; # HDR1_6
## NET gpio_exp_hdr1<1> LOC = J23; # HDR1_4
## NET gpio_exp_hdr1<0> LOC = J20; # HDR1_2
#NET gpio_exp_hdr1<*> TIG;
#NET gpio_exp_hdr1<*> PULLDOWN;
#NET gpio_exp_hdr1<*> IOSTANDARD = LVCMOS25;
 
## NET gpio_exp_hdr2<31> LOC = P21; # HDR2_64
## NET gpio_exp_hdr2<30> LOC = P20; # HDR2_62
## NET gpio_exp_hdr2<29> LOC = H24; # HDR2_60
## NET gpio_exp_hdr2<28> LOC = J24; # HDR2_58
## NET gpio_exp_hdr2<27> LOC = M20; # HDR2_56
## NET gpio_exp_hdr2<26> LOC = M19; # HDR2_54
## NET gpio_exp_hdr2<25> LOC = G24; # HDR2_52
## NET gpio_exp_hdr2<24> LOC = G25; # HDR2_50
## NET gpio_exp_hdr2<23> LOC = P23; # HDR2_48
## NET gpio_exp_hdr2<22> LOC = N23; # HDR2_46
## NET gpio_exp_hdr2<21> LOC = L20; # HDR2_44
## NET gpio_exp_hdr2<20> LOC = L19; # HDR2_42
## NET gpio_exp_hdr2<19> LOC = G26; # HDR2_40
## NET gpio_exp_hdr2<18> LOC = H26; # HDR2_38
## NET gpio_exp_hdr2<17> LOC = K23; # HDR2_36
## NET gpio_exp_hdr2<16> LOC = K22; # HDR2_34
## NET gpio_exp_hdr2<15> LOC = V26; # HDR2_32
## NET gpio_exp_hdr2<14> LOC = U26; # HDR2_30
## NET gpio_exp_hdr2<13> LOC = N22; # HDR2_28
## NET gpio_exp_hdr2<12> LOC = N21; # HDR2_26
## NET gpio_exp_hdr2<11> LOC = R22; # HDR2_24
## NET gpio_exp_hdr2<10> LOC = R23; # HDR2_22
## NET gpio_exp_hdr2<9> LOC = J25; # HDR2_20
## NET gpio_exp_hdr2<8> LOC = J26; # HDR2_18
## NET gpio_exp_hdr2<7> LOC = P19; # HDR2_16
## NET gpio_exp_hdr2<6> LOC = N19; # HDR2_14
## NET gpio_exp_hdr2<5> LOC = G21; # HDR2_12
## NET gpio_exp_hdr2<4> LOC = G22; # HDR2_10
## NET gpio_exp_hdr2<3> LOC = E25; # HDR2_8
## NET gpio_exp_hdr2<2> LOC = E26; # HDR2_6
## NET gpio_exp_hdr2<1> LOC = F24; # HDR2_4
## NET gpio_exp_hdr2<0> LOC = F25; # HDR2_2
## NET gpio_exp_hdr2<*> TIG;
## NET gpio_exp_hdr2<*> PULLDOWN;
## NET gpio_exp_hdr2<*> IOSTANDARD = LVCMOS25;
 
## #------------------------------------------------------------------------------
## # IO Pad Location Constraints / Properties for Character LCD GPIO
## #------------------------------------------------------------------------------
 
## NET gpio_char_lcd<6> LOC = P6; # LCD_E
## NET gpio_char_lcd<5> LOC = R7; # LCD_RS
## NET gpio_char_lcd<4> LOC = R5; # LCD_RW
## NET gpio_char_lcd<3> LOC = P4; # LCD_DB7
## NET gpio_char_lcd<2> LOC = R3; # LCD_DB6
## NET gpio_char_lcd<1> LOC = T3; # LCD_DB5
## NET gpio_char_lcd<0> LOC = R6; # LCD_DB4
## NET gpio_char_lcd<*> IOSTANDARD = LVCMOS33;
## NET gpio_char_lcd<*> TIG;
## NET gpio_char_lcd<*> PULLDOWN;
 
## #------------------------------------------------------------------------------
## # IO Pad Location Constraints / Properties for DDR Controllers
## #------------------------------------------------------------------------------
 
########################################################################
# Controller 0
# Memory Device: DDR2_SDRAM->SODIMMs->MT4HTF3264HY-53E #
# Data Width: 64 #
# Data Mask: 1 #
########################################################################
 
 
NET ddr2_a<0> LOC = Y5; # DDR_A0
NET ddr2_a<1> LOC = Y6; # DDR_A1
NET ddr2_a<2> LOC = W6; # DDR_A2
NET ddr2_a<3> LOC = W5; # DDR_A3
NET ddr2_a<4> LOC = V7; # DDR_A4
NET ddr2_a<5> LOC = V6; # DDR_A5
NET ddr2_a<6> LOC = Y3; # DDR_A6
NET ddr2_a<7> LOC = W3; # DDR_A7
NET ddr2_a<8> LOC = W4; # DDR_A8
NET ddr2_a<9> LOC = V4; # DDR_A9
NET ddr2_a<10> LOC = AD3; # DDR_A10
NET ddr2_a<11> LOC = AD4; # DDR_A11
NET ddr2_a<12> LOC = AC3; # DDR_A12
NET ddr2_ba<0> LOC = AB5; # DDR_BA0
NET ddr2_ba<1> LOC = AB6; # DDR_BA1
NET ddr2_cas_n LOC = AE3; # DDR_CAS_N
NET ddr2_cke<0> LOC = AA3; # DDR_CKE
NET ddr2_cke<1> LOC = AB4; # DDR_CKE
NET ddr2_cs_n<0> LOC = AF3; # DDR_CS_N
NET ddr2_cs_n<1> LOC = AD6; # DDR_CS_N
NET ddr2_ras_n LOC = AC6; # DDR_RAS_N
NET ddr2_we_n LOC = AB7; # DDR_WE_N
NET ddr2_ck<0> LOC = E2; # DDR_CK0_P
NET ddr2_ck_n<0> LOC = E1; # DDR_CK0_N
NET ddr2_ck<1> LOC = P1; # DDR_CK1_P
NET ddr2_ck_n<1> LOC = R1; # DDR_CK1_N
NET ddr2_odt<0> LOC =AE6; # DDR_ODT0
NET ddr2_odt<1> LOC =AE5; # DDR_ODT1
 
NET ddr2_dm<0> LOC = B9; # DDR_DM0
NET ddr2_dm<1> LOC = A8; # DDR_DM1
NET ddr2_dm<2> LOC = C4; # DDR_DM2
NET ddr2_dm<3> LOC = F2; # DDR_DM3
NET ddr2_dm<4> LOC = AB1; # DDR_DM4
NET ddr2_dm<5> LOC = AF24; # DDR_DM5
NET ddr2_dm<6> LOC = AF22; # DDR_DM6
NET ddr2_dm<7> LOC = AF8; # DDR_DM7
 
NET ddr2_dqs<0> LOC = B7; # DDR_DQS0
NET ddr2_dqs_n<0> LOC = A7; # DDR_DQSN0
NET ddr2_dqs<1> LOC = D5; # DDR_DQS1
NET ddr2_dqs_n<1> LOC = D6; # DDR_DQSN1
NET ddr2_dqs<2> LOC = C6; # DDR_DQS2
NET ddr2_dqs_n<2> LOC = C7; # DDR_DQSN2
NET ddr2_dqs<3> LOC = M1; # DDR_DQS3
NET ddr2_dqs_n<3> LOC = N1; # DDR_DQSN3
NET ddr2_dqs<4> LOC = T2; # DDR_DQS4
NET ddr2_dqs_n<4> LOC = R2; # DDR_DQSN4
NET ddr2_dqs<5> LOC = AF18; # DDR_DQS5
NET ddr2_dqs_n<5> LOC = AE18; # DDR_DQSN5
NET ddr2_dqs<6> LOC = AF19; # DDR_DQS6
NET ddr2_dqs_n<6> LOC = AF20; # DDR_DQSN6
NET ddr2_dqs<7> LOC = AF17; # DDR_DQS7
NET ddr2_dqs_n<7> LOC = AE17; # DDR_DQSN7
 
NET ddr2_dq<0> LOC = C11; # DDR_D0
NET ddr2_dq<1> LOC = C13; # DDR_D1
NET ddr2_dq<2> LOC = A12; # DDR_D2
NET ddr2_dq<3> LOC = C9; # DDR_D3
NET ddr2_dq<4> LOC = D10; # DDR_D4
NET ddr2_dq<5> LOC = C12; # DDR_D5
NET ddr2_dq<6> LOC = B12; # DDR_D6
NET ddr2_dq<7> LOC = A13; # DDR_D7
NET ddr2_dq<8> LOC = A10; # DDR_D8
NET ddr2_dq<9> LOC = A9; # DDR_D9
NET ddr2_dq<10> LOC = B5; # DDR_D10
NET ddr2_dq<11> LOC = D3; # DDR_D11
NET ddr2_dq<12> LOC = B10; # DDR_D12
NET ddr2_dq<13> LOC = B11; # DDR_D13
NET ddr2_dq<14> LOC = B6; # DDR_D14
NET ddr2_dq<15> LOC = B4; # DDR_D15
NET ddr2_dq<16> LOC = C2; # DDR_D16
NET ddr2_dq<17> LOC = A2; # DDR_D17
NET ddr2_dq<18> LOC = D1; # DDR_D18
NET ddr2_dq<19> LOC = B1; # DDR_D19
NET ddr2_dq<20> LOC = C3; # DDR_D20
NET ddr2_dq<21> LOC = A3; # DDR_D21
NET ddr2_dq<22> LOC = C1; # DDR_D22
NET ddr2_dq<23> LOC = B2; # DDR_D23
NET ddr2_dq<24> LOC = F3; # DDR_D24
NET ddr2_dq<25> LOC = G1; # DDR_D25
NET ddr2_dq<26> LOC = G2; # DDR_D26
NET ddr2_dq<27> LOC = H3; # DDR_D27
NET ddr2_dq<28> LOC = E3; # DDR_D28
NET ddr2_dq<29> LOC = H1; # DDR_D29
NET ddr2_dq<30> LOC = K3; # DDR_D30
NET ddr2_dq<31> LOC = J3; # DDR_D31
 
NET ddr2_dq<32> LOC = Y1; # DDR_D32
NET ddr2_dq<33> LOC = Y2; # DDR_D33
NET ddr2_dq<34> LOC = AC1; # DDR_D34
NET ddr2_dq<35> LOC = AD1; # DDR_D35
NET ddr2_dq<36> LOC = AA2; # DDR_D36
NET ddr2_dq<37> LOC = AB2; # DDR_D37
NET ddr2_dq<38> LOC = AC2; # DDR_D38
NET ddr2_dq<39> LOC = AE1; # DDR_D39
NET ddr2_dq<40> LOC = AD23; # DDR_D40
NET ddr2_dq<41> LOC = AD26; # DDR_D41
NET ddr2_dq<42> LOC = AF25; # DDR_D42
NET ddr2_dq<43> LOC = AD25; # DDR_D43
NET ddr2_dq<44> LOC = AD24; # DDR_D44
NET ddr2_dq<45> LOC = AE26; # DDR_D45
NET ddr2_dq<46> LOC = AE25; # DDR_D46
NET ddr2_dq<47> LOC = AF23; # DDR_D47
NET ddr2_dq<48> LOC = AD20; # DDR_D48
NET ddr2_dq<49> LOC = AE20; # DDR_D49
NET ddr2_dq<50> LOC = AF14; # DDR_D50
NET ddr2_dq<51> LOC = AF12; # DDR_D51
NET ddr2_dq<52> LOC = AD21; # DDR_D52
NET ddr2_dq<53> LOC = AE21; # DDR_D53
NET ddr2_dq<54> LOC = AF13; # DDR_D54
NET ddr2_dq<55> LOC = AE12; # DDR_D55
NET ddr2_dq<56> LOC = AE11; # DDR_D56
NET ddr2_dq<57> LOC = AE10; # DDR_D57
NET ddr2_dq<58> LOC = AF7; # DDR_D58
NET ddr2_dq<59> LOC = AE7; # DDR_D59
NET ddr2_dq<60> LOC = AF10; # DDR_D60
NET ddr2_dq<61> LOC = AF9; # DDR_D61
NET ddr2_dq<62> LOC = AE8; # DDR_D62
NET ddr2_dq<63> LOC = AD9; # DDR_D63
 
NET ddr2_a<*> IOSTANDARD = SSTL18_II;
NET ddr2_ba<*> IOSTANDARD = SSTL18_II;
NET ddr2_cke<*> IOSTANDARD = SSTL18_II;
NET ddr2_cas_n IOSTANDARD = SSTL18_II;
NET ddr2_cs_n<*> IOSTANDARD = SSTL18_II;
NET ddr2_ras_n IOSTANDARD = SSTL18_II;
NET ddr2_we_n IOSTANDARD = SSTL18_II;
NET ddr2_odt<*> IOSTANDARD = SSTL18_II;
 
NET ddr2_dm<*> IOSTANDARD = SSTL18_II_DCI;
NET ddr2_dq<*> IOSTANDARD = SSTL18_II_DCI;
 
NET ddr2_ck<*> IOSTANDARD = DIFF_SSTL18_II;
NET ddr2_ck_n<*> IOSTANDARD = DIFF_SSTL18_II;
NET ddr2_dqs<*> IOSTANDARD = DIFF_SSTL18_II_DCI;
NET ddr2_dqs_n<*> IOSTANDARD = DIFF_SSTL18_II_DCI;
 
## NET "ddr2_cal_clk" TNM_NET = "ddr2_cal_clk";
## NET "ddr2_dev_clk_*" TNM_NET = "ddr2_dev_clk";
## TIMESPEC "TSCAL_DEV" = FROM "ddr2_cal_clk" TO "ddr2_dev_clk" TIG;
## TIMESPEC "TSDEV_CAL" = FROM "ddr2_dev_clk" TO "ddr2_cal_clk" TIG;
###############################################################################
# Define multicycle paths - these paths may take longer because additional
# time allowed for logic to settle in calibration/initialization FSM
###############################################################################
 
# MIG 2.1: Eliminate Timegroup definitions for CLK0, and CLK90. Instead trace
# multicycle paths from originating flip-flop to ANY destination
# flip-flop (or in some cases, it can also be a BRAM)
# MUX Select for either rising/falling CLK0 for 2nd stage read capture
INST "*/u_phy_calib/gen_rd_data_sel*.u_ff_rd_data_sel" TNM = "TNM_RD_DATA_SEL";
TIMESPEC "TS_MC_RD_DATA_SEL" = FROM "TNM_RD_DATA_SEL" TO FFS
"TS_SYS_CLK" * 4;
# MUX select for read data - optional delay on data to account for byte skews
INST "*/u_usr_rd/gen_rden_sel_mux*.u_ff_rden_sel_mux" TNM = "TNM_RDEN_SEL_MUX";
TIMESPEC "TS_MC_RDEN_SEL_MUX" = FROM "TNM_RDEN_SEL_MUX" TO FFS
"TS_SYS_CLK" * 4;
# Calibration/Initialization complete status flag (for PHY logic only) - can
# be used to drive both flip-flops and BRAMs
INST "*/u_phy_init/u_ff_phy_init_data_sel" TNM = "TNM_PHY_INIT_DATA_SEL";
TIMESPEC "TS_MC_PHY_INIT_DATA_SEL_0" = FROM "TNM_PHY_INIT_DATA_SEL" TO FFS
"TS_SYS_CLK" * 4;
TIMESPEC "TS_MC_PHY_INIT_DATA_SEL_90" = FROM "TNM_PHY_INIT_DATA_SEL" TO RAMS
"TS_SYS_CLK" * 4;
# Select (address) bits for SRL32 shift registers used in stage3/stage4
# calibration
INST "*/u_phy_calib/gen_gate_dly*.u_ff_gate_dly" TNM = "TNM_GATE_DLY";
TIMESPEC "TS_MC_GATE_DLY" = FROM "TNM_GATE_DLY" TO FFS "TS_SYS_CLK" * 4;
 
INST "*/u_phy_calib/gen_rden_dly*.u_ff_rden_dly" TNM = "TNM_RDEN_DLY";
TIMESPEC "TS_MC_RDEN_DLY" = FROM "TNM_RDEN_DLY" TO FFS "TS_SYS_CLK" * 4;
 
INST "*/u_phy_calib/gen_cal_rden_dly*.u_ff_cal_rden_dly"
TNM = "TNM_CAL_RDEN_DLY";
TIMESPEC "TS_MC_CAL_RDEN_DLY" = FROM "TNM_CAL_RDEN_DLY" TO FFS
"TS_SYS_CLK" * 4;
 
 
###############################################################################
# DQS Read Post amble Glitch Squelch circuit related constraints
###############################################################################
 
###############################################################################
# LOC placement of DQS-squelch related IDDR and IDELAY elements
# Each circuit can be located at any of the following locations:
# 1. Unused "N"-side of DQS differential pair I/O
# 2. DM data mask (output only, input side is free for use)
# 3. Any output-only site
###############################################################################
 
#INST "*/gen_dqs[0].u_iob_dqs/u_iddr_dq_ce" LOC = "ILOGIC_X0Y182";
#INST "*/gen_dqs[0].u_iob_dqs/u_iodelay_dq_ce" LOC = "IODELAY_X0Y182";
#INST "*/gen_dqs[1].u_iob_dqs/u_iddr_dq_ce" LOC = "ILOGIC_X0Y180";
#INST "*/gen_dqs[1].u_iob_dqs/u_iodelay_dq_ce" LOC = "IODELAY_X0Y180";
#INST "*/gen_dqs[2].u_iob_dqs/u_iddr_dq_ce" LOC = "ILOGIC_X0Y178";
#INST "*/gen_dqs[2].u_iob_dqs/u_iodelay_dq_ce" LOC = "IODELAY_X0Y178";
#INST "*/gen_dqs[3].u_iob_dqs/u_iddr_dq_ce" LOC = "ILOGIC_X0Y142";
#INST "*/gen_dqs[3].u_iob_dqs/u_iodelay_dq_ce" LOC = "IODELAY_X0Y142";
#INST "*/gen_dqs[4].u_iob_dqs/u_iddr_dq_ce" LOC = "ILOGIC_X0Y140";
#INST "*/gen_dqs[4].u_iob_dqs/u_iodelay_dq_ce" LOC = "IODELAY_X0Y140";
#INST "*/gen_dqs[5].u_iob_dqs/u_iddr_dq_ce" LOC = "ILOGIC_X0Y138";
#INST "*/gen_dqs[5].u_iob_dqs/u_iodelay_dq_ce" LOC = "IODELAY_X0Y138";
#INST "*/gen_dqs[6].u_iob_dqs/u_iddr_dq_ce" LOC = "ILOGIC_X0Y102";
#INST "*/gen_dqs[6].u_iob_dqs/u_iodelay_dq_ce" LOC = "IODELAY_X0Y102";
#INST "*/gen_dqs[7].u_iob_dqs/u_iddr_dq_ce" LOC = "ILOGIC_X0Y100";
#INST "*/gen_dqs[7].u_iob_dqs/u_iodelay_dq_ce" LOC = "IODELAY_X0Y100";
 
###############################################################################
# LOC and timing constraints for flop driving DQS CE enable signal
# from fabric logic. Even though the absolute delay on this path is
# calibrated out (when synchronizing this output to DQS), the delay
# should still be kept as low as possible to reduce post-calibration
# voltage/temp variations - these are roughly proportional to the
# absolute delay of the path
###############################################################################
INST "*/u_phy_calib/gen_gate[0].u_en_dqs_ff" LOC = SLICE_X0Y91;
INST "*/u_phy_calib/gen_gate[1].u_en_dqs_ff" LOC = SLICE_X0Y90;
INST "*/u_phy_calib/gen_gate[2].u_en_dqs_ff" LOC = SLICE_X0Y89;
INST "*/u_phy_calib/gen_gate[3].u_en_dqs_ff" LOC = SLICE_X0Y71;
INST "*/u_phy_calib/gen_gate[4].u_en_dqs_ff" LOC = SLICE_X0Y70;
INST "*/u_phy_calib/gen_gate[5].u_en_dqs_ff" LOC = SLICE_X0Y69;
INST "*/u_phy_calib/gen_gate[6].u_en_dqs_ff" LOC = SLICE_X0Y51;
INST "*/u_phy_calib/gen_gate[7].u_en_dqs_ff" LOC = SLICE_X0Y50;
 
# Control for DQS gate - from fabric flop. Prevent "runaway" delay -
# two parts to this path: (1) from fabric flop to IDELAY, (2) from
# IDELAY to asynchronous reset of IDDR that drives the DQ CE's
# This can be relaxed by the user for lower frequencies:
# 300MHz = 850ps, 267MHz = 900ps. At 200MHz = 950ps.
# In general PAR should be able to route this
# within 900ps over all speed grades.
NET "*/u_phy_io/en_dqs*" MAXDELAY = 900 ps;
NET "*/u_phy_io/gen_dqs*.u_iob_dqs/en_dqs_sync" MAXDELAY = 850 ps;
 
###############################################################################
# Define multicycle paths - these paths may take longer because additional
# time allowed for logic to settle in calibration/initialization FSM
###############################################################################
## DDR2 clock domain nets
NET "*/ml501_ddr2_wb_if0/ddr2_read_done" TNM_NET = "DDR2_READ_DONE_GRP";
NET "*/ml501_ddr2_wb_if0/ddr2_write_done" TNM_NET = "DDR2_WRITE_DONE_GRP";
NET "*/ml501_ddr2_wb_if0/do_writeback_ddr2_shifter*" TNM_NET = "DDR2_WRITEBACK_SHIFTER";
 
TIMEGRP "DDR2_MC_REGS" = "DDR2_READ_DONE_GRP" "DDR2_WRITE_DONE_GRP" "DDR2_WRITEBACK_SHIFTER";
## System bus (wishbone) domain nets
NET "*/ml501_ddr2_wb_if0/do_writeback*" TNM_NET = "WB_DO_WRITEBACK";
NET "*/ml501_ddr2_wb_if0/do_readfrom*" TNM_NET = "WB_DO_READFROM";
 
TIMEGRP "WB_MC_REGS" = "WB_DO_WRITEBACK" "WB_DO_READFROM";
 
# Path constraints - if bus clock is 50Mhz they have 20ns
TIMESPEC TS_ddr2_controller_mc_paths = FROM "WB_MC_REGS" to "DDR2_MC_REGS" 20ns;
TIMESPEC TS_ddr2_controller_mc_paths2 = FROM "DDR2_MC_REGS" to "WB_MC_REGS" 20ns;
 
###############################################################################
# "Half-cycle" path constraint from IDDR to CE pin for all DQ IDDR's
# for DQS Read Post amble Glitch Squelch circuit
###############################################################################
 
# Max delay from output of IDDR to CE input of DQ IDDRs = tRPST + some slack
# where slack account for rise-time of DQS on board. For now assume slack =
# 0.400ns (based on initial SPICE simulations, assumes use of ODT), so
# time = 0.4*Tcyc + 0.40ns = 1.6ns @333MHz
INST "*/gen_dqs[*].u_iob_dqs/u_iddr_dq_ce" TNM = "TNM_DQ_CE_IDDR";
INST "*/gen_dq[*].u_iob_dq/gen_stg2_*.u_iddr_dq" TNM = "TNM_DQS_FLOPS";
TIMESPEC "TS_DQ_CE" = FROM "TNM_DQ_CE_IDDR" TO "TNM_DQS_FLOPS" 2.4 ns;
 
 
## #------------------------------------------------------------------------------
## # IO Pad Location Constraints / Properties for UART
## #------------------------------------------------------------------------------
 
## NET uart_RX LOC = AC7;
## NET uart_RX IOSTANDARD = LVCMOS33;
## NET uart_RX TIG;
## NET uart_TX LOC = AD14;
## NET uart_TX IOSTANDARD = LVCMOS33;
## NET uart_TX TIG;
 
## #------------------------------------------------------------------------------
## # IO Pad Location Constraints / Properties for SRAM
## #------------------------------------------------------------------------------
 
#NET sram_clk LOC = U22;
#NET sram_clk_fb LOC = AD15;
#NET sram_clk_fb IOSTANDARD = LVCMOS33;
#NET sram_clk IOSTANDARD = LVDCI_33;
 
#NET sram_clk_fb FEEDBACK = 1500ps NET sram_clk;
 
##NET sram_flash_addr<23> LOC = Y10;
##NET sram_flash_addr<22> LOC = Y11;
#NET sram_flash_addr<21> LOC = AA17;
#NET sram_flash_addr<20> LOC = AB17;
#NET sram_flash_addr<19> LOC = G14;
#NET sram_flash_addr<18> LOC = F13;
#NET sram_flash_addr<17> LOC = H14;
#NET sram_flash_addr<16> LOC = H13;
#NET sram_flash_addr<15> LOC = F15;
#NET sram_flash_addr<14> LOC = G15;
#NET sram_flash_addr<13> LOC = G12;
#NET sram_flash_addr<12> LOC = H12;
#NET sram_flash_addr<11> LOC = G16;
#NET sram_flash_addr<10> LOC = H16;
#NET sram_flash_addr<9> LOC = H11;
#NET sram_flash_addr<8> LOC = G11;
#NET sram_flash_addr<7> LOC = H17;
#NET sram_flash_addr<6> LOC = G17;
#NET sram_flash_addr<5> LOC = G10;
#NET sram_flash_addr<4> LOC = G9;
#NET sram_flash_addr<3> LOC = G19;
#NET sram_flash_addr<2> LOC = H18;
#NET sram_flash_addr<1> LOC = H9;
##NET sram_flash_addr<0> LOC = H8;
#NET sram_flash_addr<*> IOSTANDARD = LVCMOS33;
#NET sram_flash_addr<*> SLEW = FAST;
#NET sram_flash_addr<*> DRIVE = 8;
 
#NET sram_flash_data<31> LOC = AD18 | IOSTANDARD = LVCMOS33 | DRIVE = 12 | SLEW = FAST;
#NET sram_flash_data<30> LOC = AC18 | IOSTANDARD = LVCMOS33 | DRIVE = 12 | SLEW = FAST;
#NET sram_flash_data<29> LOC = AB10 | IOSTANDARD = LVCMOS33 | DRIVE = 12 | SLEW = FAST;
#NET sram_flash_data<28> LOC = AB9 | IOSTANDARD = LVCMOS33 | DRIVE = 12 | SLEW = FAST;
#NET sram_flash_data<27> LOC = AC17 | IOSTANDARD = LVCMOS33 | DRIVE = 12 | SLEW = FAST;
#NET sram_flash_data<26> LOC = AC16 | IOSTANDARD = LVCMOS33 | DRIVE = 12 | SLEW = FAST;
#NET sram_flash_data<25> LOC = AC8 | IOSTANDARD = LVCMOS33 | DRIVE = 12 | SLEW = FAST;
#NET sram_flash_data<24> LOC = AC9 | IOSTANDARD = LVCMOS33 | DRIVE = 12 | SLEW = FAST;
#NET sram_flash_data<23> LOC = Y12 | IOSTANDARD = LVCMOS33 | DRIVE = 12 | SLEW = FAST;
#NET sram_flash_data<22> LOC = Y13 | IOSTANDARD = LVCMOS33 | DRIVE = 12 | SLEW = FAST;
#NET sram_flash_data<21> LOC = AA15 | IOSTANDARD = LVCMOS33 | DRIVE = 12 | SLEW = FAST;
#NET sram_flash_data<20> LOC = AB14 | IOSTANDARD = LVCMOS33 | DRIVE = 12 | SLEW = FAST;
#NET sram_flash_data<19> LOC = AA12 | IOSTANDARD = LVCMOS33 | DRIVE = 12 | SLEW = FAST;
#NET sram_flash_data<18> LOC = AB11 | IOSTANDARD = LVCMOS33 | DRIVE = 12 | SLEW = FAST;
#NET sram_flash_data<17> LOC = AA13 | IOSTANDARD = LVCMOS33 | DRIVE = 12 | SLEW = FAST;
#NET sram_flash_data<16> LOC = AA14 | IOSTANDARD = LVCMOS33 | DRIVE = 12 | SLEW = FAST;
 
#NET sram_flash_data<15> LOC = AC24 | IOSTANDARD = LVDCI_33;
#NET sram_flash_data<14> LOC = AB22 | IOSTANDARD = LVDCI_33;
#NET sram_flash_data<13> LOC = AA22 | IOSTANDARD = LVDCI_33;
#NET sram_flash_data<12> LOC = AC21 | IOSTANDARD = LVDCI_33;
#NET sram_flash_data<11> LOC = AB21 | IOSTANDARD = LVDCI_33;
#NET sram_flash_data<10> LOC = W21 | IOSTANDARD = LVDCI_33;
#NET sram_flash_data<9> LOC = W20 | IOSTANDARD = LVDCI_33;
#NET sram_flash_data<8> LOC = U19 | IOSTANDARD = LVDCI_33;
#NET sram_flash_data<7> LOC = U20 | IOSTANDARD = LVDCI_33;
#NET sram_flash_data<6> LOC = V19 | IOSTANDARD = LVDCI_33;
#NET sram_flash_data<5> LOC = W19 | IOSTANDARD = LVDCI_33;
#NET sram_flash_data<4> LOC = Y21 | IOSTANDARD = LVDCI_33;
#NET sram_flash_data<3> LOC = Y20 | IOSTANDARD = LVDCI_33;
#NET sram_flash_data<2> LOC = AD19 | IOSTANDARD = LVDCI_33;
#NET sram_flash_data<1> LOC = AC19 | IOSTANDARD = LVDCI_33;
#NET sram_flash_data<0> LOC = AB20 | IOSTANDARD = LVDCI_33;
 
#NET sram_flash_data<*> PULLDOWN;
 
#NET sram_cen LOC = AB24 | IOSTANDARD = LVDCI_33;
#NET sram_flash_oe_n LOC = AC22 | IOSTANDARD = LVDCI_33;
##NET flash_oe_n LOC = AA9 | IOSTANDARD = LVCMOS33 | DRIVE = 12 | SLEW = FAST;
#NET sram_flash_we_n LOC = AB15 | IOSTANDARD = LVCMOS33 | DRIVE = 12 | SLEW = FAST;
#NET sram_bw<3> LOC = W24 | IOSTANDARD = LVDCI_33;
#NET sram_bw<2> LOC = W23 | IOSTANDARD = LVDCI_33;
#NET sram_bw<1> LOC = V24 | IOSTANDARD = LVDCI_33;
#NET sram_bw<0> LOC = V23 | IOSTANDARD = LVDCI_33;
##NET flash_cen LOC = AA10 | IOSTANDARD = LVCMOS33 | DRIVE = 12 | SLEW = FAST;
#NET sram_adv_ld_n LOC = U21 | IOSTANDARD = LVDCI_33;
#NET sram_mode LOC = AC23 | IOSTANDARD = LVDCI_33;
# NET flash_audio_reset_n LOC = AD10 | IOSTANDARD = LVCMOS33;
 
#------------------------------------------------------------------------------
# IO Pad Location Constraints / Properties for TFT VGA LCD Controller
#------------------------------------------------------------------------------
 
#NET dvi_iic_scl LOC = D21;
#NET dvi_iic_sda LOC = D20;
#NET dvi_iic_scl SLEW = SLOW;
#NET dvi_iic_scl DRIVE = 6;
#NET dvi_iic_scl TIG;
#NET dvi_iic_scl IOSTANDARD = LVCMOS33;
#NET dvi_iic_sda SLEW = SLOW;
#NET dvi_iic_sda DRIVE = 6;
#NET dvi_iic_sda TIG;
#NET dvi_iic_sda IOSTANDARD = LVCMOS33;
 
#NET tft_lcd_data<0> LOC = A17;
#NET tft_lcd_data<1> LOC = B17;
#NET tft_lcd_data<2> LOC = C17;
#NET tft_lcd_data<3> LOC = D18;
#NET tft_lcd_data<4> LOC = C16;
#NET tft_lcd_data<5> LOC = D16;
#NET tft_lcd_data<6> LOC = B16;
#NET tft_lcd_data<7> LOC = B15;
#NET tft_lcd_data<8> LOC = A15;
#NET tft_lcd_data<9> LOC = A14;
#NET tft_lcd_data<10> LOC = B14;
#NET tft_lcd_data<11> LOC = C14;
#NET tft_lcd_data<*> IOSTANDARD = LVDCI_33;
 
#NET tft_lcd_clk_p LOC = A20;
#NET tft_lcd_clk_p IOSTANDARD = LVCMOS33 | DRIVE = 24 | SLEW = FAST;
#NET tft_lcd_clk_n LOC = B20;
#NET tft_lcd_clk_n IOSTANDARD = LVCMOS33 | DRIVE = 24 | SLEW = FAST;
 
#NET tft_lcd_hsync LOC = C19;
#NET tft_lcd_hsync IOSTANDARD = LVDCI_33;
#NET tft_lcd_vsync LOC = D19;
#NET tft_lcd_vsync IOSTANDARD = LVDCI_33;
#NET tft_lcd_de LOC = C18;
#NET tft_lcd_de IOSTANDARD = LVDCI_33;
#NET tft_lcd_reset_b LOC = A18;
#NET tft_lcd_reset_b IOSTANDARD = LVCMOS33;
 
## NET "tft_clk" TNM_NET = "tft_clk";
## TIMESPEC "TSPLB_TFT" = FROM "sys_clk" TO "tft_clk" TIG;
## TIMESPEC "TSTFT_PLB" = FROM "tft_clk" TO "sys_clk" TIG;
 
## #------------------------------------------------------------------------------
## # IO Pad Location Constraints / Properties for Ethernet
## #------------------------------------------------------------------------------
 
NET phy_col LOC = G20 | IOSTANDARD = LVCMOS25;
NET phy_crs LOC = H22 | IOSTANDARD = LVCMOS25;
NET phy_dv LOC = J19 | IOSTANDARD = LVCMOS25;
NET phy_rx_clk LOC = F14 | IOSTANDARD = LVCMOS25;
NET phy_rx_data<3> LOC = E22 | IOSTANDARD = LVCMOS25;
NET phy_rx_data<2> LOC = E20 | IOSTANDARD = LVCMOS25;
NET phy_rx_data<1> LOC = E21 | IOSTANDARD = LVCMOS25;
NET phy_rx_data<0> LOC = F20 | IOSTANDARD = LVCMOS25;
 
NET phy_rx_er LOC = H19 | IOSTANDARD = LVCMOS25;
NET phy_tx_clk LOC = D13 | IOSTANDARD = LVCMOS25;
#NET phy_mii_int_n LOC = F17 | IOSTANDARD = LVCMOS25;
NET phy_rst_n LOC = F8 | IOSTANDARD = LVCMOS25; # PHY_RESET pin on phy
NET phy_tx_data<3> LOC = B25 | IOSTANDARD = LVDCI_33;
NET phy_tx_data<2> LOC = C24 | IOSTANDARD = LVDCI_33;
NET phy_tx_data<1> LOC = D24 | IOSTANDARD = LVDCI_33;
NET phy_tx_data<0> LOC = C23 | IOSTANDARD = LVDCI_33;
NET phy_tx_en LOC = B24 | IOSTANDARD = LVDCI_33;
NET phy_tx_er LOC = A24 | IOSTANDARD = LVDCI_33;
 
## PHY Serial Management Interface pins
NET phy_smi_clk LOC = F18 | IOSTANDARD = LVCMOS25;
NET phy_smi_data LOC = E8 | IOSTANDARD = LVCMOS25;
 
## NET phy_mii_int_n PULLUP;
 
## NET phy_mii_int_n TIG;
NET phy_rst_n TIG;
 
## # Timing Constraints (these are recommended in documentation and
## # are unaltered except for the TIG)
NET "phy_rx_clk" TNM_NET = "RXCLK_GRP";
NET "phy_tx_clk" TNM_NET = "TXCLK_GRP";
TIMESPEC "TSTXOUT" = FROM "TXCLK_GRP" TO "PADS" 10 ns;
TIMESPEC "TSRXIN" = FROM "PADS" TO "RXCLK_GRP" 6 ns;
 
NET "phy_rx_data<3>" IOBDELAY=NONE;
NET "phy_rx_data<2>" IOBDELAY=NONE;
NET "phy_rx_data<1>" IOBDELAY=NONE;
NET "phy_rx_data<0>" IOBDELAY=NONE;
NET "phy_dv" IOBDELAY=NONE;
NET "phy_rx_er" IOBDELAY=NONE;
NET "phy_crs" IOBDELAY=NONE;
NET "phy_col" IOBDELAY=NONE;
 
## # Timing ignores (to specify unconstrained paths)
NET "dcm0_clkdv" TNM_NET = "sys_clk"; # Wishbone clock
TIMESPEC "TS_PHYTX_OPB" = FROM "TXCLK_GRP" TO "sys_clk" TIG;
TIMESPEC "TS_OPB_PHYTX" = FROM "sys_clk" TO "TXCLK_GRP" TIG;
TIMESPEC "TS_PHYRX_OPB" = FROM "RXCLK_GRP" TO "sys_clk" TIG;
TIMESPEC "TS_OPB_PHYRX" = FROM "sys_clk" TO "RXCLK_GRP" TIG;
 
## #------------------------------------------------------------------------------
## # IO Pad Location Constraints / Properties for AC97 Sound Controller
## #------------------------------------------------------------------------------
 
## NET ac97_bit_clk LOC = AC13;
## NET ac97_bit_clk IOSTANDARD = LVCMOS33;
## NET ac97_bit_clk PERIOD = 80;
## NET ac97_sdata_in LOC = AC12;
## NET ac97_sdata_in IOSTANDARD = LVCMOS33;
## NET ac97_sdata_out LOC = AC11;
## NET ac97_sdata_out IOSTANDARD = LVCMOS33;
## NET ac97_sync LOC = AD11;
## NET ac97_sync IOSTANDARD = LVCMOS33;
/openrisc/trunk/orpsocv2/boards/xilinx/ml501/par/Makefile
0,0 → 1,75
#
# ORPSoC on ML501 Place And Route Makefile
#
 
# Include file for tools, etc
include ../../../tools.inc
 
BOARD=ml501
PART=xc5vlx50-ff676-1
 
XILINX_FLAGS=-intstyle silent
XILINX_MAP_FLAGS=-logic_opt off
## By default we don't echo the bash commands, but if you want to, for
# debugging purposes, set Q= when calling make
Q ?=@
 
%.ngd: %_xst.ucf ../syn/%.ngc
@echo; echo "\t#### Running NGDBuild ####";
$(Q)( . $(XILINX_SETTINGS_SCRIPT) && \
ngdbuild -p $(PART) -sd ../syn -uc $*_xst.ucf $*.ngc $*.ngd )
 
../syn/%.ngc:
${MAKE} -C ../syn $*.ngc
 
# -pr is pack and the options are <i|o|b>
XILINX_AREA_TARGET = speed
#This target uses Xilinx tools to perform Mapping
%_map.ncd: %.ngd
@echo; echo "\t#### Mapping ####";
$(Q)( . $(XILINX_SETTINGS_SCRIPT) && \
export XIL_MAP_NO_DSP_AUTOREG=1 && \
export XIL_MAP_ALLOW_ANY_DLL_INPUT=1 && \
map -p $(PART) -detail -pr b -cm ${XILINX_AREA_TARGET} \
-timing -ol high -w $(XILINX_FLAGS) -o $*_map.ncd -xe n $*.ngd $*.pcf )
 
#This target uses Xilinx tools to Place & Route the design
%.ncd: %_map.ncd
@echo; echo "\t#### PAR'ing ####";
$(Q)( . $(XILINX_SETTINGS_SCRIPT) && \
par -w -pl high -rl high $(XILINX_FLAGS) $*_map.ncd $*.ncd $*.pcf )
 
#This target uses Xilinx tools to generate a bitstream
%.bit: %.ncd
@echo; echo "\t#### Generating .bit file ####";
$(Q)( . $(XILINX_SETTINGS_SCRIPT) && \
bitgen -w $(XILINX_FLAGS) -g StartUpClk:JtagClk $*.ncd $*.bit )
 
#this target downloads the bitstream to the target fpga
%.download: %.bit %.batch
$(Q)( . ${XILINX_PATH}/settings32.sh && \
impact -batch $*.batch )
 
#This target uses netgen to make a simulation netlist
%.netlist: %.ncd
@echo; echo "\t#### Generating netlist ####";
$(Q)(. $(XILINX_SETTINGS_SCRIPT) && \
netgen -ofmt verilog -sim -dir netlist -pcf $*.pcf $*.ncd)
 
#This one uses TRCE to make a timing report
%.twr: %.ncd
@echo; echo "\t#### Generating timing report ####";
$(Q)(. $(XILINX_SETTINGS_SCRIPT) && \
trce -u 1000 -e 1000 $*.ncd)
 
 
FILES_TO_KEEP=$(BOARD)_xst.ucf $(BOARD).batch Makefile
FILES_TO_KEEP_E=$(shell for file in $(FILES_TO_KEEP); do echo "-e $$file"; done)
FILES_TO_DEL=$(shell ls | grep -v $(FILES_TO_KEEP_E))
 
clean-test:
@echo Would remove: $(FILES_TO_DEL)
clean:
@rm -rfv $(FILES_TO_DEL)
 
.PRECIOUS : %.ncd %.ngd %_map.ncd %.bit ../syn/%.edf ../syn/%.ngc
/openrisc/trunk/orpsocv2/boards/xilinx/ml501/sim/bin/modelsim.scr
0,0 → 1,49
// This file should be processed by the Makefile before being used
+incdir+$BENCH_DIR
+incdir+$BENCH_DIR/vpi/verilog
+incdir+$BACKEND_DIR
+incdir+$BOARD_BENCH_DIR
+incdir+$BOARD_RTL_DIR
+incdir+$BOARD_RTL_DIR/ddr2_mig
+incdir+$RTL_DIR/components/uart16550
+incdir+$RTL_DIR/components/ethernet
+incdir+$RTL_DIR/components/fpu
+incdir+$RTL_DIR/components/or1k_startup
+incdir+$RTL_DIR/components/or1k_top
+incdir+$RTL_DIR/components/or1200r2
+incdir+$RTL_DIR/components/tap
+incdir+$RTL_DIR/components/smii
+incdir+$RTL_DIR/components/debug_if
+incdir+$RTL_DIR/components/wb_sdram_ctrl
+incdir+$RTL_DIR/components/wb_conbus
+incdir+$XILINX_VERILOG_SRC
+incdir+$XILINX_VERILOG_SRC/unisims
+incdir+$XILINX_VERILOG_SRC/XilinxCoreLib
 
-y $BENCH_DIR
-y $BENCH_DIR/vpi/verilog
-y $BACKEND_DIR
-y $BOARD_BENCH_DIR
-y $BOARD_RTL_DIR
-y $BOARD_RTL_DIR/ddr2_mig
-y $RTL_DIR/components/uart16550
-y $RTL_DIR/components/ethernet
-y $RTL_DIR/components/fpu
-y $RTL_DIR/components/or1k_startup
-y $RTL_DIR/components/or1k_top
-y $RTL_DIR/components/or1200r2
-y $RTL_DIR/components/tap
-y $RTL_DIR/components/smii
-y $RTL_DIR/components/debug_if
-y $RTL_DIR/components/wb_sdram_ctrl
-y $RTL_DIR/components/ram_wb
-y $RTL_DIR/components/wb_conbus
-y $XILINX_VERILOG_SRC
-y $XILINX_VERILOG_SRC/unisims
-y $XILINX_VERILOG_SRC/XilinxCoreLib
 
// Modelsim doesn't assume this?!?!?
+libext+.v
 
$BOARD_RTL_DIR/ml501.v
 
/openrisc/trunk/orpsocv2/boards/xilinx/ml501/sim/bin/Makefile
0,0 → 1,161
# Include file for tools, etc (mainly interested in the Xilinx path here)
include ../../../../tools.inc
 
ORPSOC_ROOT=../../../../..
BOARD=ml501
 
CUR_DIR=$(shell pwd)
# The root path of the whole project
PROJECT_ROOT =$(CUR_DIR)/$(ORPSOC_ROOT)
 
SIM_DIR=$(CUR_DIR)/../../sim
 
BOARD_BENCH_DIR=$(CUR_DIR)/../../bench
BOARD_RTL_DIR=$(CUR_DIR)/../../rtl
BOARD_SW_DIR=$(CUR_DIR)/../../sw
BOARD_SYN_DIR=$(CUR_DIR)/../../syn
 
 
# Important!
RTL_TESTBENCH_TOP=ml501_testbench
BENCH_TOP_VERILOG_DIR=$(BOARD_BENCH_DIR)
 
# Extra defines passed to testbench compilation
# Used here for DDR2 model defines
EXTRA_BENCH_DEFINES=+define+sg37E +define+x16
 
#MEMORY_MODELS=$(BENCH_VERILOG_DIR)/cy7c1354.v $(BENCH_VERILOG_DIR)/ddr2_model.v
 
SIMULATOR=vsim
 
RTL_VERILOG_INCLUDE_DIR =$(BOARD_RTL_DIR)
 
 
include $(ORPSOC_ROOT)/sim/bin/Makefile
 
 
ifeq ($(VCD), 1)
VOPT_ARGS=+acc=rnp
endif
 
 
# Here we re-define the modelsim compilation variable, changing include dirs
# so we use the includes/defines from the board's rtl path instead of the
# normal orpsocv2 bench path.
 
 
# Modelsim testench compilation - we change this from the standard makefile
# to change:
# 1) The include directory (should be the board RTL path, not the main RTL path)
# 2) Change the define for the name of the top testbench (board dependent)
# 3) Add the board's testbench paths
# 4) Add the various extra memory models we use (maybe should just use a script for this instead? TODO!)
VSIM_COMPILE_TB = vlog $(BENCH_VERILOG_DIR)/or1200_monitor.v $(BENCH_TOP_VERILOG_DIR)/$(RTL_TESTBENCH_TOP).v
VSIM_COMPILE_TB += +incdir+$(BENCH_VERILOG_DIR) +incdir+$(BENCH_TOP_VERILOG_DIR) +incdir+$(BOARD_RTL_DIR) +incdir+$(XILINX_VERILOG_SRC)
VSIM_COMPILE_TB += +define+TEST_DEFINE_FILE
VSIM_COMPILE_TB += +define+OR1200_TOP=$(RTL_TESTBENCH_TOP).dut.i_or1k.i_or1200_top
VSIM_COMPILE_TB += +define+TESTBENCH_DEFINES=\"$(RTL_TESTBENCH_TOP)_defines.v\"
VSIM_COMPILE_TB += -y $(BENCH_VERILOG_DIR) -y $(BOARD_BENCH_DIR) +libext+.v
VSIM_COMPILE_TB += $(EXTRA_BENCH_DEFINES)
 
VOPT_STEP=vopt -quiet $(VOPT_ARGS) glbl $(RTL_TESTBENCH_TOP) -L $(MGC_ORPSOC_LIB) -o testbench
SIM_COMMANDRUN= $(VSIM_COMPILE_TB); $(VOPT_STEP); $(VSIM) -c -quiet +nowarnTFMPC -L $(MGC_ORPSOC_LIB) -do "run -all; exit" testbench
 
# Re-define the command-file generation rule - we add a few extra things to
# our scripts to tell the simulator where the Xilinx tools, other set of
# includes, etc.
$(SIM_RUN_DIR)/$(GENERATED_COMMANDFILE): $(SIM_BIN_DIR)/$(SIM_COMMANDFILE)
$(Q)sed < $(SIM_BIN_DIR)/$(SIM_COMMANDFILE) > $(SIM_RUN_DIR)/$(GENERATED_COMMANDFILE) \
-e s!\$$BENCH_DIR!$(BENCH_VERILOG_DIR)! \
-e s!\$$RTL_DIR!$(RTL_VERILOG_DIR)! \
-e s!\$$BOARD_BENCH_DIR!$(BOARD_BENCH_DIR)! \
-e s!\$$BOARD_RTL_DIR!$(BOARD_RTL_DIR)! \
-e s!\$$BACKEND_DIR!$(BACKEND_DIR)! \
-e s!\$$XILINX_VERILOG_SRC!$(XILINX_VERILOG_SRC)! \
-e \\!^//.*\$$!d -e \\!^\$$!d ; \
echo "+define+TEST_DEFINE_FILE=\"test_define.v\"" >> $(SIM_RUN_DIR)/$(GENERATED_COMMANDFILE); \
if [ ! -z $$VCD ]; \
then echo "+define+VCD" >> $(SIM_RUN_DIR)/$(GENERATED_COMMANDFILE); \
if [ $(SIMULATOR) = $(NCVERILOG) ]; \
then echo "+access+r" >> $(SIM_RUN_DIR)/$(GENERATED_COMMANDFILE); \
fi; \
fi; \
if [ ! -z $$UART_PRINTF ]; \
then echo "+define+UART_PRINTF" >> $(SIM_RUN_DIR)/$(GENERATED_COMMANDFILE); \
fi; \
if [ $(SIMULATOR) = $(NCVERILOG) ]; \
then echo "+nocopyright" >> $(SIM_RUN_DIR)/$(GENERATED_COMMANDFILE); \
echo "+nowarn+MACRDF" >> $(SIM_RUN_DIR)/$(GENERATED_COMMANDFILE); \
fi
 
 
 
# A new set of tests for software which will run only on this board
 
BOARD_TESTS=boot
 
rtl-board-tests: $(SIM_RUN_DIR)/$(GENERATED_COMMANDFILE) prepare-sw prepare-rtl prepare-dirs
@echo
@echo "Beginning loop that will complete the following tests for $(BOARD) board: $(BOARD_TESTS)"
@echo
$(Q)for TEST in $(BOARD_TESTS); do \
echo "################################################################################"; \
echo; \
echo "\t#### Current test: $$TEST ####"; echo; \
echo "\t#### Compiling software ####"; echo; \
CURRENT_TEST_SW_DIR=$(BOARD_SW_DIR)/`echo $$TEST | cut -d "-" -f 1`; \
$(MAKE) -C $$CURRENT_TEST_SW_DIR clean $$TEST $(TEST_SW_MAKE_OPTS); \
rm -f $(SIM_RUN_DIR)/$(SIM_FLASH_MEM_FILE); \
rm -f $(SIM_RUN_DIR)/$(SIM_SRAM_MEM_FILE); \
ln -s $$CURRENT_TEST_SW_DIR/$$TEST.vmem $(SIM_RUN_DIR)/$(SIM_SRAM_MEM_FILE); \
echo "\`define TEST_NAME_STRING \"$$TEST\"" > $(SIM_RUN_DIR)/test_define.v; \
echo "\`define TEST_RESULTS_DIR \"$(SIM_RESULTS_DIR)/\" " >> $(SIM_RUN_DIR)/test_define.v; \
if [ ! -z $$VCD ]; \
then echo "\`define VCD" >> $(SIM_RUN_DIR)/test_define.v; \
fi; \
if [ ! -z $$UART_PRINTF ]; \
then echo "\`define UART_PRINTF" >> $(SIM_RUN_DIR)/test_define.v; \
fi; \
if [ -z $$NO_SIM_LOGGING ]; then \
echo "\`define OR1200_DISPLAY_ARCH_STATE" >> $(SIM_RUN_DIR)/test_define.v; \
fi; \
echo ; \
echo "\t#### Compiling RTL ####"; \
$(SIM_COMMANDCOMPILE); \
echo; \
echo "\t#### Beginning simulation ####"; \
time -p $(SIM_COMMANDRUN) ; \
if [ $$? -gt 0 ]; then exit $$?; fi; \
TEST_RESULT=`cat $(SIM_RESULTS_DIR)/$$TEST-general.log | grep report | grep $(SIM_SUCCESS_MESSAGE) -c`; \
echo; echo "\t####"; \
if [ $$TEST_RESULT -gt 0 ]; then \
echo "\t#### Test $$TEST PASSED ####";TESTS_PASSED=`expr $$TESTS_PASSED + 1`;\
else echo "\t#### Test $$TEST FAILED ####";\
fi; \
echo "\t####"; echo; \
TESTS_PERFORMED=`expr $$TESTS_PERFORMED + 1`;\
done; \
echo "Test results: "$$TESTS_PASSED" out of "$$TESTS_PERFORMED" tests passed"; echo
 
 
SYN_SIM_COMMANDCOMPILE=if [ ! -e work ]; then vlib work; vlib $(MGC_ORPSOC_LIB); vlog -work $(MGC_ORPSOC_LIB) +libext+.v -y $(XILINX_VERILOG_SRC) +incdir+$(XILINX_VERILOG_SRC) -y $(XILINX_VERILOG_SRC)/unisims +incdir+$(XILINX_VERILOG_SRC)/unisims -y $(XILINX_VERILOG_SRC)/XilinxCoreLib +incdir+$(XILINX_VERILOG_SRC)/XilinxCoreLib $(BOARD_SYN_DIR)/$(BOARD).v $(BOARD_RTL_DIR)/ml501_ddr2_wb_if_cache.v ; fi
syn-board-test: prepare-dirs $(BOARD_SYN_DIR)/$(BOARD).v
$(Q)echo "\`define TEST_NAME_STRING \"ml501-post-synthesis\"" > $(SIM_RUN_DIR)/test_define.v; \
echo "\`define POST_SYNTHESIS_SIM" >> $(SIM_RUN_DIR)/test_define.v; \
 
echo "\`define TEST_RESULTS_DIR \"$(SIM_RESULTS_DIR)/\" " >> $(SIM_RUN_DIR)/test_define.v; \
if [ ! -z $$VCD ]; \
then echo "\`define VCD" >> $(SIM_RUN_DIR)/test_define.v; \
if [ ! -z $$VCD_DEPTH ]; \
then echo "\`define VCD_DEPTH "$(VCD_DEPTH) >> $(SIM_RUN_DIR)/test_define.v; \
fi; \
fi; \
if [ ! -z $$UART_PRINTF ]; \
then echo "\`define UART_PRINTF" >> $(SIM_RUN_DIR)/test_define.v; \
fi; \
echo "\t#### Compiling RTL ####"; \
$(SYN_SIM_COMMANDCOMPILE); \
echo; \
echo "\t#### Beginning simulation ####"; \
time -p $(SIM_COMMANDRUN) ; \
echo
/openrisc/trunk/orpsocv2/boards/xilinx/ml501/sw/boot/boot.ld
0,0 → 1,60
 
MEMORY
{
reset : ORIGIN = 0x00000000, LENGTH = 0x00000108
ram : ORIGIN = 0x0000108, LENGTH = 4K
}
 
SECTIONS
{
.reset :
{
*(.reset)
} > reset
 
 
/*
.vectors :
{
_vec_start = .;
*(.vectors)
_vec_end = .;
} > vectors
*/
.text :
{
*(.text)
} > ram
 
.rodata :
{
*(.rodata)
*(.rodata.*)
} > ram
.icm :
{
_icm_start = .;
*(.icm)
_icm_end = .;
} > ram
 
.data :
{
_dst_beg = .;
*(.data)
_dst_end = .;
} > ram
.bss :
{
*(.bss)
} > ram
.stack (NOLOAD) :
{
*(.stack)
_src_addr = .;
} > ram
 
}
/openrisc/trunk/orpsocv2/boards/xilinx/ml501/sw/boot/boot.c
0,0 → 1,30
// Small app to print a hello world
#include "spr_defs.h"
#include "board.h"
#include "uart.h"
 
void
boot ()
{
char *helloworld = "\n\tHello World from the OpenRISC on Xilinx ML501\n\n";
 
uart_init();
 
int i=0;
while (helloworld[i])
uart_putc(helloworld[i++]);
 
#ifndef SYNTHESIS
/* Report and exit for sim */
asm("l.movhi\tr3, hi(0xdeaddead)\n \
l.ori\tr3,r3, lo(0xdeaddead)\n \
l.nop\t%0\n \
l.nop\t%1": :"K" (NOP_REPORT), "K" (NOP_EXIT));
#endif
// Echo characters back
while (1)
uart_putc(uart_getc());
}
 
/openrisc/trunk/orpsocv2/boards/xilinx/ml501/sw/boot/boot_reset.S
0,0 → 1,110
/* Reset function for ml501 board */
#include "spr_defs.h"
#include "board.h"
 
.section .stack
.space 0x30
_stack:
 
.section .reset, "ax"
 
/* .org 0x100*/
.org 0
_reset_vector:
l.addi r2,r0,0x0
l.addi r3,r0,0x0
l.addi r4,r0,0x0
l.addi r5,r0,0x0
l.addi r6,r0,0x0
l.addi r7,r0,0x0
l.addi r8,r0,0x0
l.addi r9,r0,0x0
l.addi r10,r0,0x0
l.addi r11,r0,0x0
l.addi r12,r0,0x0
l.addi r13,r0,0x0
l.addi r14,r0,0x0
l.addi r15,r0,0x0
l.addi r16,r0,0x0
l.addi r17,r0,0x0
l.addi r18,r0,0x0
l.addi r19,r0,0x0
l.addi r20,r0,0x0
l.addi r21,r0,0x0
l.addi r22,r0,0x0
l.addi r23,r0,0x0
l.addi r24,r0,0x0
l.addi r25,r0,0x0
l.addi r26,r0,0x0
l.addi r27,r0,0x0
l.addi r28,r0,0x0
l.addi r29,r0,0x0
l.addi r30,r0,0x0
l.addi r31,r0,0x0
 
l.movhi r3,hi(_start)
l.ori r3,r3,lo(_start)
l.jr r3
l.nop
 
.org 0x100
/* Jump to 0 .. where the real reset vector is*/
l.jr r0
l.nop
.section .text
 
_start:
 
.if IC | DC
/* Flush IC and/or DC */
l.addi r10,r0,0
l.addi r11,r0,0
l.addi r12,r0,0
.if IC
l.addi r11,r0,IC_SIZE
.endif
.if DC
l.addi r12,r0,DC_SIZE
.endif
l.sfleu r12,r11
l.bf loop
l.nop
l.add r11,r0,r12
loop:
.if IC
l.mtspr r0,r10,SPR_ICBIR
.endif
.if DC
l.mtspr r0,r10,SPR_DCBIR
.endif
l.sfne r10,r11
l.bf loop
l.addi r10,r10,16
 
/* Enable IC and/or DC */
l.addi r10,r0,(SPR_SR_SM)
.if IC
l.ori r10,r10,(SPR_SR_ICE)
.endif
.if DC
l.ori r10,r10,(SPR_SR_DCE)
.endif
l.mtspr r0,r10,SPR_SR
l.nop
l.nop
l.nop
l.nop
l.nop
.endif
 
/* Set stack pointer */
l.movhi r1,hi(_stack)
l.ori r1,r1,lo(_stack)
 
/* Jump to main */
l.movhi r2,hi(_boot)
l.ori r2,r2,lo(_boot)
l.jr r2
l.nop
 
/openrisc/trunk/orpsocv2/boards/xilinx/ml501/sw/boot/Makefile
0,0 → 1,50
PROJECT_ROOT=../../../../..
 
MAIN_SW_DIR=$(PROJECT_ROOT)/sw
 
SUPPORT_SOURCES=uart.c uart.h spr_defs.h support.h
SUPPORT_C_SOURCES=$(shell for src in $(SUPPORT_SOURCES); do echo $$src | grep \.c; done)
 
# Some extra options, if we're going to compile the software for it to be pulled in by the synthesis tool
ifeq ($(SYNTHESIS), 1)
SW_SYNTHESIS_OPTS=-DSYNTHESIS
# Expecting the bootmem to be 0x800 big - if not, change this or it won't get pulled in by synthesis properly!
VMEM_SYNTHESIS_OPTS=-synfmt --pad-to-addr 0x800
endif
 
 
CROSS_PREFIX=or32-elf-
CROSS_CC=$(CROSS_PREFIX)gcc
CROSS_OBJCOPY=$(CROSS_PREFIX)objcopy
 
APP=boot
 
all: clean
 
.PHONY: $(APP)
$(APP): prepare-sw prepare-links $(APP).vmem
 
 
$(APP).vmem: $(APP).bin
$(MAIN_SW_DIR)/utils/bin2vmem $? $(VMEM_SYNTHESIS_OPTS) > $@
 
$(APP).bin: $(APP).or32
$(CROSS_OBJCOPY) -O binary $? $@
 
$(APP).or32: $(APP)_reset.o $(APP).[cS] $(SUPPORT_C_SOURCES)
$(CROSS_CC) $? -nostdlib -mhard-mul -g -I../. -O2 $(SW_SYNTHESIS_OPTS) -T$(APP).ld -o $@
 
$(APP)_reset.o: $(APP)_reset.S
$(CROSS_CC) -c -o $@ $? -I../.
 
prepare-links:
for src in $(SUPPORT_SOURCES); do if [ ! -e $$src ]; then ln -s $(MAIN_SW_DIR)/support/$$src; fi; done
 
unprepare-links:
for src in $(SUPPORT_SOURCES); do if [ -e $$src ]; then unlink $$src; fi; done
 
prepare-sw:
@$(MAKE) -C $(MAIN_SW_DIR)/utils all
 
clean: unprepare-links
@rm -vf *.o *.bin *.or32 *.vmem
/openrisc/trunk/orpsocv2/boards/xilinx/ml501/sw/board.h
0,0 → 1,42
#ifndef _BOARD_H_
#define _BOARD_H_
 
#define MC_ENABLED 0
 
#define IC 1
#define IC_SIZE 8192
#define DC 0
#define DC_SIZE 8192
 
 
//#define IN_CLK 25000000
#define IN_CLK 50000000
 
#define TICKS_PER_SEC 100
 
#define STACK_SIZE 0x10000
 
#define UART_BAUD_RATE 115200
 
#define UART_BASE 0x90000000
#define UART_IRQ 19
 
//#define SPI_BASE 0xa0000000
 
//#define ETH_BASE 0xD0000000
//#define IRQ_ETH_0 (4) /* interrupt source for Ethernet dvice 0 */
 
#define ETH_DATA_BASE 0xa8000000 /* Address for ETH_DATA */
#define BOARD_DEF_IP 0x0a010185
#define BOARD_DEF_MASK 0xff000000
#define BOARD_DEF_GW 0x0a010101
 
#define ETH_MACADDR0 0x00
#define ETH_MACADDR1 0x12
#define ETH_MACADDR2 0x34
#define ETH_MACADDR3 0x56
#define ETH_MACADDR4 0x78
#define ETH_MACADDR5 0x9a
 
 
#endif
/openrisc/trunk/orpsocv2/boards/xilinx/ml501/sw/gpio/gpio.c
0,0 → 1,75
// Small app to print a hello world
#include "spr_defs.h"
#include "board.h"
#include "uart.h"
 
 
#define GPIO_BASE 0x80000000
#define GPIO_DATA (GPIO_BASE)
#define GPIO_DIR (GPIO_BASE | 0x4)
 
 
#ifdef SYNTHESIS
#define LOOP_DELAY 200000
#else
#define LOOP_DELAY 20
#endif
 
void
gpio ()
{
int i,j;
volatile int* gpio_dir = (volatile int*) GPIO_DIR;
volatile int* gpio_data = (volatile int*) GPIO_DATA;
 
// bottom byte to out
*gpio_dir = 0x000000ff;
 
uart_init();
 
while (1) {
i = 0;
while (i <= 7) {
*gpio_data = 1<<i;
i++;
j = LOOP_DELAY;
while (j--)
{
if (uart_check_for_char())
{
uart_putc(uart_getc());
*gpio_data = 0xff;
}
}
}
while (i > 0) {
i--;
*gpio_data = 1<<i;
j = LOOP_DELAY;
while (j--)
{
if (uart_check_for_char())
{
uart_putc(uart_getc());
*gpio_data = 0xff;
}
}
}
/* Report and exit for sim */
asm("l.movhi\tr3, hi(0xdeaddead)\n \
l.ori\tr3,r3, lo(0xdeaddead)\n \
l.nop\t%0\n \
l.nop\t%1": :"K" (NOP_REPORT), "K" (NOP_EXIT));
}
}
 
/openrisc/trunk/orpsocv2/boards/xilinx/ml501/sw/gpio/gpio_reset.S
0,0 → 1,110
/* Reset function for ml501 board */
#include "spr_defs.h"
#include "board.h"
 
.section .stack
.space 0x30
_stack:
 
.section .reset, "ax"
 
/* .org 0x100*/
.org 0
_reset_vector:
l.addi r2,r0,0x0
l.addi r3,r0,0x0
l.addi r4,r0,0x0
l.addi r5,r0,0x0
l.addi r6,r0,0x0
l.addi r7,r0,0x0
l.addi r8,r0,0x0
l.addi r9,r0,0x0
l.addi r10,r0,0x0
l.addi r11,r0,0x0
l.addi r12,r0,0x0
l.addi r13,r0,0x0
l.addi r14,r0,0x0
l.addi r15,r0,0x0
l.addi r16,r0,0x0
l.addi r17,r0,0x0
l.addi r18,r0,0x0
l.addi r19,r0,0x0
l.addi r20,r0,0x0
l.addi r21,r0,0x0
l.addi r22,r0,0x0
l.addi r23,r0,0x0
l.addi r24,r0,0x0
l.addi r25,r0,0x0
l.addi r26,r0,0x0
l.addi r27,r0,0x0
l.addi r28,r0,0x0
l.addi r29,r0,0x0
l.addi r30,r0,0x0
l.addi r31,r0,0x0
 
l.movhi r3,hi(_start)
l.ori r3,r3,lo(_start)
l.jr r3
l.nop
 
.org 0x100
/* Jump to 0 .. where the real reset vector is*/
l.jr r0
l.nop
.section .text
 
_start:
 
.if IC | DC
/* Flush IC and/or DC */
l.addi r10,r0,0
l.addi r11,r0,0
l.addi r12,r0,0
.if IC
l.addi r11,r0,IC_SIZE
.endif
.if DC
l.addi r12,r0,DC_SIZE
.endif
l.sfleu r12,r11
l.bf loop
l.nop
l.add r11,r0,r12
loop:
.if IC
l.mtspr r0,r10,SPR_ICBIR
.endif
.if DC
l.mtspr r0,r10,SPR_DCBIR
.endif
l.sfne r10,r11
l.bf loop
l.addi r10,r10,16
 
/* Enable IC and/or DC */
l.addi r10,r0,(SPR_SR_SM)
.if IC
l.ori r10,r10,(SPR_SR_ICE)
.endif
.if DC
l.ori r10,r10,(SPR_SR_DCE)
.endif
l.mtspr r0,r10,SPR_SR
l.nop
l.nop
l.nop
l.nop
l.nop
.endif
 
/* Set stack pointer */
l.movhi r1,hi(_stack)
l.ori r1,r1,lo(_stack)
 
/* Jump to main */
l.movhi r2,hi(_gpio)
l.ori r2,r2,lo(_gpio)
l.jr r2
l.nop
 
/openrisc/trunk/orpsocv2/boards/xilinx/ml501/sw/gpio/gpio.ld
0,0 → 1,60
 
MEMORY
{
reset : ORIGIN = 0x00000000, LENGTH = 0x00000108
ram : ORIGIN = 0x0000800, LENGTH = 1M
}
 
SECTIONS
{
.reset :
{
*(.reset)
} > reset
 
 
/*
.vectors :
{
_vec_start = .;
*(.vectors)
_vec_end = .;
} > vectors
*/
.text :
{
*(.text)
} > ram
 
.rodata :
{
*(.rodata)
*(.rodata.*)
} > ram
.icm :
{
_icm_start = .;
*(.icm)
_icm_end = .;
} > ram
 
.data :
{
_dst_beg = .;
*(.data)
_dst_end = .;
} > ram
.bss :
{
*(.bss)
} > ram
.stack (NOLOAD) :
{
*(.stack)
_src_addr = .;
} > ram
 
}
/openrisc/trunk/orpsocv2/boards/xilinx/ml501/sw/gpio/Makefile
0,0 → 1,49
PROJECT_ROOT=../../../../..
 
MAIN_SW_DIR=$(PROJECT_ROOT)/sw
 
SUPPORT_SOURCES=uart.c uart.h spr_defs.h support.h
SUPPORT_C_SOURCES=$(shell for src in $(SUPPORT_SOURCES); do echo $$src | grep \.c; done)
 
# Some extra options, if we're going to compile the software for it to be pulled in by the synthesis tool
ifeq ($(SYNTHESIS), 1)
SW_SYNTHESIS_OPTS=-DSYNTHESIS
VMEM_SYNTHESIS_OPTS=-synfmt
endif
 
 
CROSS_PREFIX=or32-elf-
CROSS_CC=$(CROSS_PREFIX)gcc
CROSS_OBJCOPY=$(CROSS_PREFIX)objcopy
 
APP=gpio
 
all: clean
 
.PHONY: $(APP)
$(APP): prepare-sw prepare-links $(APP).vmem
 
 
$(APP).vmem: $(APP).bin
$(MAIN_SW_DIR)/utils/bin2vmem $? $(VMEM_SYNTHESIS_OPTS) > $@
 
$(APP).bin: $(APP).or32
$(CROSS_OBJCOPY) -O binary $? $@
 
$(APP).or32: $(APP)_reset.o $(APP).[cS] $(SUPPORT_C_SOURCES)
$(CROSS_CC) $? -nostdlib -mhard-mul -g -I../. -O2 $(SW_SYNTHESIS_OPTS) -T$(APP).ld -o $@
 
$(APP)_reset.o: $(APP)_reset.S
$(CROSS_CC) -c -o $@ $? -I../.
 
prepare-links:
for src in $(SUPPORT_SOURCES); do if [ ! -e $$src ]; then ln -s $(MAIN_SW_DIR)/support/$$src; fi; done
 
unprepare-links:
for src in $(SUPPORT_SOURCES); do if [ -e $$src ]; then unlink $$src; fi; done
 
prepare-sw:
@$(MAKE) -C $(MAIN_SW_DIR)/utils all
 
clean: unprepare-links
@rm -vf *.o *.bin *.or32 *.vmem
/openrisc/trunk/orpsocv2/boards/xilinx/ml501/sw/memtest/memtest.c
0,0 → 1,166
// Small app to print a hello world
#include "spr_defs.h"
#include "board.h"
#include "uart.h"
 
#ifdef SYNTHESIS
#define print_string(x) i=0; while (x[i]) uart_putc(x[i++]);
#else
#define print_string(x)
#endif
 
#ifndef MEM_TEST_BASE
#define MEM_TEST_BASE 0x2000
#endif
 
#ifdef SYNTHESIS
#define MEM_TEST_LENGTH ((1024*1024*255)/4)
#else
#define MEM_TEST_LENGTH 64
#endif
 
 
#define LFSR_BASE 0x1f000000
#define LFSR_REG (LFSR_BASE + 0)
#define LFSR_CONTROL_REG (LFSR_BASE + 4)
#define LFSR_CONTROL_ENABLE (1 << 0)
#define LFSR_CONTROL_RESET (1 << 1)
 
void lfsr_reset()
{
volatile unsigned int * lfsr_control = (volatile unsigned int*) LFSR_CONTROL_REG;
*lfsr_control = (LFSR_CONTROL_RESET);
}
 
void lfsr_enable()
{
volatile unsigned int * lfsr_control = (volatile unsigned int*) LFSR_CONTROL_REG;
*lfsr_control = (LFSR_CONTROL_ENABLE);
}
 
void lfsr_set(unsigned int val)
{
volatile unsigned int * lfsr_reg = (volatile int*) LFSR_REG;
*lfsr_reg = val ;
}
 
unsigned int lfsr_read()
{
volatile unsigned int * lfsr_reg = (volatile int*) LFSR_REG;
return *lfsr_reg;
}
 
unsigned int lfsr_read_shift()
{
volatile unsigned int * lfsr_reg = (volatile int*) LFSR_REG;
unsigned int lfsr_val = *lfsr_reg;
lfsr_enable();
return lfsr_val;
}
 
 
 
 
void
memtest ()
{
 
#ifdef SYNTHESIS
uart_init();
#endif
 
int i;
volatile unsigned int * extmem = (volatile unsigned int*) MEM_TEST_BASE;
char* starting = "\n\n* Starting memtest *\nClearing memory\n"; print_string(starting);
// Clear memory
for (i=0;i<MEM_TEST_LENGTH;i++)
extmem[i] = 0;
char* cleared = "Memory cleared\nVerifying\n"; print_string(cleared);
char *clear_error = "Error verifying zeroed memory\n";
// Read data
for (i=0;i<MEM_TEST_LENGTH;i++)
{
if (!(extmem[i]==0))
{
/* Report the failed addr and exit for sim */
asm("l.add\tr3, r0, %2\n \
l.nop\t%0\n \
l.nop\t%1": :"K" (NOP_REPORT), "K" (NOP_EXIT), "r" (i));
print_string(clear_error);
while(1);
}
}
char* random_pattern_write = "Filling RAM with random pattern\n"; print_string(random_pattern_write);
lfsr_reset();
// Write data
for (i=0;i<MEM_TEST_LENGTH;i++)
extmem[i] = lfsr_read_shift();
char* reading_random_pattern = "Pattern written\nVerifying and inverting pattern\n"; print_string(reading_random_pattern);
char *random_pattern_error = "Error verifying random pattern\n";
lfsr_reset();
 
// Read data
for (i=0;i<MEM_TEST_LENGTH;i++)
{
if (lfsr_read() != extmem[i])
{
/* Report the failed addr and exit for sim */
asm("l.add\tr3, r0, %2\n \
l.nop\t%0\n \
l.nop\t%1": :"K" (NOP_REPORT), "K" (NOP_EXIT), "r" (i));
print_string(random_pattern_error);
while(1);
}
extmem[i] = ~extmem[i];
lfsr_enable(); // Shift to next value
}
 
char* reading_inverted_pattern = "Random pattern verified\nVerifying inverting pattern\n"; print_string(reading_inverted_pattern);
char *random_invert_pattern_error = "Error verifying inverted random pattern\n";
lfsr_reset();
// Read data
for (i=0;i<MEM_TEST_LENGTH;i++)
{
if ((~lfsr_read()) != extmem[i])
{
/* Report the failed addr and exit for sim */
asm("l.add\tr3, r0, %2\n \
l.nop\t%0\n \
l.nop\t%1": :"K" (NOP_REPORT), "K" (NOP_EXIT), "r" (i));
print_string(random_invert_pattern_error);
while(1);
}
lfsr_enable(); // Shift to next value
}
 
 
char* good = "Memory test OK\n"; print_string(good);
 
#ifdef SYNTHESIS
// Fill memory with each 4-byte cell's number
for (i=0;i<MEM_TEST_LENGTH;i++)
extmem[i] = i;
char* newline = "\n.\n"; print_string(newline);
#endif
 
/* Report and exit for sim */
asm("l.movhi\tr3, hi(0xdeaddead)\n \
l.ori\tr3,r3, lo(0xdeaddead)\n \
l.nop\t%0\n \
l.nop\t%1": :"K" (NOP_REPORT), "K" (NOP_EXIT));
 
while(1);
}
 
/openrisc/trunk/orpsocv2/boards/xilinx/ml501/sw/memtest/memtest_reset.S
0,0 → 1,110
/* Reset function for ml501 board */
#include "spr_defs.h"
#include "board.h"
 
.section .stack
.space 0x30
_stack:
 
.section .reset, "ax"
 
/* .org 0x100*/
.org 0
_reset_vector:
l.addi r2,r0,0x0
l.addi r3,r0,0x0
l.addi r4,r0,0x0
l.addi r5,r0,0x0
l.addi r6,r0,0x0
l.addi r7,r0,0x0
l.addi r8,r0,0x0
l.addi r9,r0,0x0
l.addi r10,r0,0x0
l.addi r11,r0,0x0
l.addi r12,r0,0x0
l.addi r13,r0,0x0
l.addi r14,r0,0x0
l.addi r15,r0,0x0
l.addi r16,r0,0x0
l.addi r17,r0,0x0
l.addi r18,r0,0x0
l.addi r19,r0,0x0
l.addi r20,r0,0x0
l.addi r21,r0,0x0
l.addi r22,r0,0x0
l.addi r23,r0,0x0
l.addi r24,r0,0x0
l.addi r25,r0,0x0
l.addi r26,r0,0x0
l.addi r27,r0,0x0
l.addi r28,r0,0x0
l.addi r29,r0,0x0
l.addi r30,r0,0x0
l.addi r31,r0,0x0
 
l.movhi r3,hi(_start)
l.ori r3,r3,lo(_start)
l.jr r3
l.nop
 
.org 0x100
/* Jump to 0 .. where the real reset vector is*/
l.jr r0
l.nop
.section .text
 
_start:
 
.if IC | DC
/* Flush IC and/or DC */
l.addi r10,r0,0
l.addi r11,r0,0
l.addi r12,r0,0
.if IC
l.addi r11,r0,IC_SIZE
.endif
.if DC
l.addi r12,r0,DC_SIZE
.endif
l.sfleu r12,r11
l.bf loop
l.nop
l.add r11,r0,r12
loop:
.if IC
l.mtspr r0,r10,SPR_ICBIR
.endif
.if DC
l.mtspr r0,r10,SPR_DCBIR
.endif
l.sfne r10,r11
l.bf loop
l.addi r10,r10,16
 
/* Enable IC and/or DC */
l.addi r10,r0,(SPR_SR_SM)
.if IC
l.ori r10,r10,(SPR_SR_ICE)
.endif
.if DC
l.ori r10,r10,(SPR_SR_DCE)
.endif
l.mtspr r0,r10,SPR_SR
l.nop
l.nop
l.nop
l.nop
l.nop
.endif
 
/* Set stack pointer */
l.movhi r1,hi(_stack)
l.ori r1,r1,lo(_stack)
 
/* Jump to main */
l.movhi r2,hi(_memtest)
l.ori r2,r2,lo(_memtest)
l.jr r2
l.nop
 
/openrisc/trunk/orpsocv2/boards/xilinx/ml501/sw/memtest/memtest.ld
0,0 → 1,60
 
MEMORY
{
reset : ORIGIN = 0x00000000, LENGTH = 0x00000108
ram : ORIGIN = 0x0000108, LENGTH = 4K
}
 
SECTIONS
{
.reset :
{
*(.reset)
} > reset
 
 
/*
.vectors :
{
_vec_start = .;
*(.vectors)
_vec_end = .;
} > vectors
*/
.text :
{
*(.text)
} > ram
 
.rodata :
{
*(.rodata)
*(.rodata.*)
} > ram
.icm :
{
_icm_start = .;
*(.icm)
_icm_end = .;
} > ram
 
.data :
{
_dst_beg = .;
*(.data)
_dst_end = .;
} > ram
.bss :
{
*(.bss)
} > ram
.stack (NOLOAD) :
{
*(.stack)
_src_addr = .;
} > ram
 
}
/openrisc/trunk/orpsocv2/boards/xilinx/ml501/sw/memtest/Makefile
0,0 → 1,49
PROJECT_ROOT=../../../../..
 
MAIN_SW_DIR=$(PROJECT_ROOT)/sw
 
SUPPORT_SOURCES=uart.c uart.h spr_defs.h support.h
SUPPORT_C_SOURCES=$(shell for src in $(SUPPORT_SOURCES); do echo $$src | grep \.c; done)
 
# Some extra options, if we're going to compile the software for it to be pulled in by the synthesis tool
ifeq ($(SYNTHESIS), 1)
SW_SYNTHESIS_OPTS=-DSYNTHESIS
VMEM_SYNTHESIS_OPTS=-synfmt
endif
 
 
CROSS_PREFIX=or32-elf-
CROSS_CC=$(CROSS_PREFIX)gcc
CROSS_OBJCOPY=$(CROSS_PREFIX)objcopy
 
APP=memtest
 
all: clean
 
.PHONY: $(APP)
$(APP): prepare-sw prepare-links $(APP).vmem
 
 
$(APP).vmem: $(APP).bin
$(MAIN_SW_DIR)/utils/bin2vmem $? $(VMEM_SYNTHESIS_OPTS) > $@
 
$(APP).bin: $(APP).or32
$(CROSS_OBJCOPY) -O binary $? $@
 
$(APP).or32: $(APP)_reset.o $(APP).[cS] $(SUPPORT_C_SOURCES)
$(CROSS_CC) $? -nostdlib -mhard-mul -g -I../. -O2 $(SW_SYNTHESIS_OPTS) -T$(APP).ld -o $@
 
$(APP)_reset.o: $(APP)_reset.S
$(CROSS_CC) -c -o $@ $? -I../.
 
prepare-links:
for src in $(SUPPORT_SOURCES); do if [ ! -e $$src ]; then ln -s $(MAIN_SW_DIR)/support/$$src; fi; done
 
unprepare-links:
for src in $(SUPPORT_SOURCES); do if [ -e $$src ]; then unlink $$src; fi; done
 
prepare-sw:
@$(MAKE) -C $(MAIN_SW_DIR)/utils all
 
clean: unprepare-links
@rm -vf *.o *.bin *.or32 *.vmem
/openrisc/trunk/orpsocv2/boards/xilinx/ml501/syn/ml501_ddr2_wb_if_cache.ngc
0,0 → 1,3
XILINX-XDB 0.1 STUB 0.1 ASCII
XILINX-XDM V1.5e
$70;44<,[o}e~g`n;"2*776(-30<=>?0123416<89:;<=>?0123456789:;<=>?0123456789:;<=>?0123456789:;<=>?01234567;2;%<<;413:9MKVR\3nbbo2>2683:41<9;21CXZ_UU8gkpre488<6=0>5:36>LHW]]0JHI\NU=37>586=2;>6D@_UU8B@ATE]5;?6=0>5:35>LHW]]0JHI\NL=36>586=2;=6D@_UU8B@ATED5;>6=0>2:35>LHW]]0|io2>5;2=57=62@D[YY4ndepa85<768=0=7AZTQWW>wbflmxnon2?:1<26>552@D[YY4KI@>05?699;18>7GAPTV9@LD;;80;2<=4338JJUSS2mcem1=>:1<27>552F__\XZ5DNC?74<76890??4@UURVP?BHJ59:6=0>5:11>JSSX\^1hb{{a=12>586:291EC^ZT;cg`wg;:3:5=<5;:HLSQQ<CAYK7?7>11097>LHW]]0OE]L33;2=54=32@D[YY4XE@N?7?69981?6D@_UU8TADS;;3:5==5;:HLSQQ<pmh686=0>2:69KPRW]]0OC]O33;2=57=32F__\XZ5DNRA86<76m1>zav:0gd533+698136D@_UU8TAGJ;?3:5=<57:HLSQQ<PMK_7;7>19:CG@WGK494j7LJKR@N?558f3HNO^LB310<b?DBCZHF7=?0n;@FGVDJ;9:4j7LJKR@N?518d3HNO^LB31483:d=FLMXJ@1?:>89B@ATFD5;556OKDSCO878>3HNO^LB33?;8EABUIE6?245NDEPBH93912KOH_OC<7<:?DBCZHF7;374AEFQEI:?601JHI\NL=;==>GCL[K^0=0n;@FGVDS;994j7LJKR@W?548f3HNO^L[313<b?DBCZH_7=>0l;@FGVDS;9=0;2l5NDEPBQ973601JHI\NU=3==>GCL[K^0?06;@FGVDS;;730MIJ]AT>7:<=FLMXJY1;19:CG@WGR4?427LJKR@W?3;?<IMNYMX27>89B@ATF]53556OKDS@O858f3HNO^OB311<b?DBCZKF7=<0n;@FGVGJ;9;4j7LJKRCN?568f3HNO^OB315<`?DBCZKF7=84?>`9B@ATED5;>245NDEPAH97912KOH_LC<3<:?DBCZKF7?374AEFQFI:3601JHI\ML=7==>GCL[HG0;06;@FGVGJ;?730MIJ]BM>;:<=FLMXI@1719:CG@WDR494j7LJKRCW?558f3HNO^O[310<b?DBCZK_7=?0n;@FGVGS;9:4h7LJKRCW?51<76h1JHI\MU=37:<=FLMXIY1?19:CG@WDR4;427LJKRCW?7;?<IMNYNX2;>89B@ATE]5?556OKDS@V838>3HNO^O[37?;8EABUJ\63245NDEPAQ9?9;2KG@>5MU3:8FPUXAGLDh6MNSBCGALHKI]Ko7NO\C@FFMKJF\Kn0OL]LAEGJJWC@Im1HM^MNDDKMV@AEm2IJ_NOKENWWHDRFm2IJ_NOKENWWHDREm2IJ_NOKENWWV@AFm2IJ_NOKENWWV@AE9;1HDHMD_MK@AKUBW]S[I85LLJCO1>EKCH_>7NBDBM78GIME]01HC@CFTUGG51=DG[OTKH@JR@VJKKYNFOE<7N\JAUGG2>BNI5:5;6JFA=33:2=CAH6:=394DHC?57803MCJ0<=17:FJE9736>1OEL2>5?58@LG;9?4<7IGN<05=3>BNI5;32:5KI@>2=;0<L@K7=394DHC?65803MCJ0??17:FJE9456>1OEL2=3?58@LG;:=4<7IGN<37=3>BNI58=2:5KI@>13;1<L@K7>508;EKB87?9>2NBM1<17:FJE957601OEL2<1;2=3>BNI59:2;5KI@>0:3=CAH6?2;5KI@>6:3=CAH6=2;5KI@>4:3=CAH632;5KI@>::3=CAK6;2:5KIC>24;1<L@H7=<08;EKA8449?2NBN1?<>69GMG:6<7=0HDL314<4?AOE48<5;6JFB=34:2=CAK6:4394DH@?5<813MCI0<08;EKA8769?2NBN1<>>69GMG:5:7=0HDL322<4?AOE4;>5;6JFB=06:2=CAK69:394DH@?62803MCI0?617:FJF94>6?1OEO2=>69GMG:48730HDL33083:2=CAK68=384DH@?7;0<L@H78384DH@?1;0<L@H7:384DH@?3;0<L@H74384DH@?=;1<L@ZJ0=08;EKSE979?2NB\L2=>89GMUG;;3:5;6JFP@>0:2=CAYH7<394DHRA84803MC[N1<19:FJTG:4294<7IG_B=1=2>BHI5:5;6J@A=33:2=CGH6:=394DNC?57803MEJ0<=17:FLE9736>1OCL2>5?58@JG;9?4<7IAN<05=3>BHI5;32:5KO@>2=;0<LFK7=394DNC?65803MEJ0??17:FLE9456>1OCL2=3?58@JG;:=4<7IAN<37=3>BHI58=2:5KO@>13;1<LFK7>508;EMB87?9>2NDM1<17:FLE957601OCL2<1;2=3>BHI59:2;5KO@>0:3=CGH6?2;5KO@>6:3=CGH6=2;5KO@>4:3=CGH632;5KO@>::2=CGHUYIJ84DN@?4;1<LFH7==08;EMA8479?2NDN1?=>69GKG:6;7=0HBL315<4?AIE48?5;6J@B=35:2=CGK6:;394DN@?5=803MEI0<716:FLF979?2NDN1<?>69GKG:597=0HBL323<4?AIE4;95;6J@B=07:2=CGK699394DN@?63803MEI0?917:FLF94?6>1OCO2=9?48@JD;:7=0HBL331<:?AIE4:;1<394DN@?74813MEI0>09;EMA81813MEI0809;EMA83813MEI0:09;EMA8=813MEI0408;EMA[WC@?2ND\L2?>69GKUG;97=0HB^N<3<:?AIWI591<394DNRB86803ME[N1>17:FLTG:66>1OC]L32?;8@JVE4:0;2:5KOQ@?7;2<MGKG86KAAT68AKDK<2OENX;4F@NPA4=@;2MEH55FNHVS[56?3@DBX]Q?199JJLRWW9837D@FTQ]37==NF@^[S=:7;HLJPUY7=11BBDZ__14;?LHN\YU;;55FNHVS[5>?3@DBX]Q?999JJLRWW9K37D@FTQ]3F==NF@^[S=M7;HLJPUY7L11BBDZ__1G;?LHN\YU;J:5FNHV\451<AGC_S=?8;HLJPZ65?2CEEYQ?369JJLRX8==0ECG[_174?LHN\V:=;6GAIU]332=NF@^T<594IOKW[5?03@DBXR>N7:KMMQY7J>1BBDZP0B58MKOSW9N<7D@FT^2F3>OIA]U;J:5FNHV\551<AGC_S<?8;HLJPZ75?2CEEYQ>369JJLRX9==0ECG[_074?LHN\V;=;6GAIU]232=NF@^T=594IOKW[4?03@DBXR?N7:KMMQY6J>1BBDZP1B58MKOSW8N<7D@FT^3F3>OIA]U:J:5FNHV\651<AGC_S??8;HLJPZ45?2CEEYQ=369JJLRX:==0ECG[_374?LHN\V8=;6GAIU]132=NF@^T>594IOKW[7?03@DBXR<N7:KMMQY5J>1BBDZP2B58MKOSW;N<7D@FT^0F3>OIA]U9J:5FNHV\751<AGC_S>?8;HLJPZ55?2CEEYQ<369JJLRX;==0ECG[_274?LHN\V9=;6GAIU]032=NF@^T?594IOKW[6?03@DBXR=N7:KMMQY4J>1BBDZP3B58MKOSW:N<7D@FT^1F3>OIA]U8J:5FNHV\051<AGC_S9?8;HLJPZ25?2CEEYQ;369JJLRX<==0ECG[_574?LHN\V>=;6GAIU]732=NF@^T8594IOKW[1?03@DBXR:N7:KMMQY3J>1BBDZP4B58MKOSW=N<7D@FT^6F3>OIA]U?J:5FNHV\151<AGC_S8?8;HLJPZ35?2CEEYQ:369JJLRX===0ECG[_474?LHN\V?=;6GAIU]632=NF@^T9594IOKW[0?03@DBXR;N7:KMMQY2J>1BBDZP5B58MKOSW<N<7D@FT^7F3>OIA]U>J:5FNHV\251<AGC_S;?8;HLJPZ05?2CEEYQ9369JJLRX>==0ECG[_774?LHN\V<=;6GAIU]532=NF@^T:594IOKW[3?03@DBXR8N7:KMMQY1J>1BBDZP6B58MKOSW?N<7D@FT^4F3>OIA]U=J:5FNHV\351<AGC_S:?8;HLJPZ15?2CEEYQ8369JJLRX?==0ECG[_674?LHN\V==;6GAIU]432=NF@^T;594IOKW[2?03@DBXR9N7:KMMQY0J>1BBDZP7B58MKOSW>N<7D@FT^5F3>OIA]U<J;5FNHV\E3=NF@^TN45FNHV\BLJB>2FDMIKK7:NLCLEFDj1Fmga}Vdppmjhd3DcecXjrrklj6=I99>0B<>?4:L2442<F8:986@>0268J463<2D:<8:4N0250>H68>>0B<>74:L24<5<F8;?7C?>059M54733G;:>95A1017?K76<=1E=<;;;O3221=I98=?7C?>859M54?43G;986@>2168J446<2D:>?:4N0000>H6:=>0B<<:4:L2632<F88<86@>2968J44>;2D:?95A1227?K749=1E=><;;O3071=I9:>?7C?<559M56033G;8;95A12:7?K741:1E=9:4N0630>H6<8>0B<:=4:L2062<F8>?86@>4468J421<2D:8::4N06;0>H6<090B<;;;O3641=I9<;?7C?:259M50533G;>895A1477?K72>=1E=89;;O36<1=I9<387C?94:L2252<F8<:86@>6368J404<2D::9:4N0460>H6>?>0B<884:L22=2<F8<2?6@>759M52633G;<=95A1607?K70;=1E=::;;O3411=I9><?7C?8759M52>33G;<5>5A1968J4>7<2D:4<:4N0:10>H60:>0B<6;4:L2<02<F82=86@>8668J4>?<2D:44=4N0;7?K7>8=1E=4?;;O3:61=I909?7C?6459M5<333G;2:95A1857?K7>0=1E=47=;O00?K47<2D9<=:4N3220>H58;>0B?><4:L1412<F;:>86@=0768J760<2D9<5:4N32:7>H59=1E><>;;O0251=I:88?7C<>359M64233G8:995A2047?K46?=1E><6;;O02=6=I:;>0B?<?4:L1642<F;8986@=2268J743<2D9>8:4N3050>H5:>>0B?<74:L16<5<F;9?7C<<059M66733G88>95A2217?K44<=1E>>;;;O0021=I::=?7C<<859M66?43G8?86@=4168J726<2D98?:4N3600>H5<=>0B?::4:L1032<F;><86@=4968J72>;2D9995A2427?K429=1E>8<;;O0671=I:<>?7C<:559M60033G8>;95A24:7?K421:1E>;:4N3430>H5>8>0B?8=4:L1262<F;<?86@=6468J701<2D9:::4N34;0>H5>090B?9;;O0441=I:>;?7C<8259M62533G8<895A2677?K40>=1E>:9;;O04<1=I:>387C<74:L1<52<F;2:86@=8368J7>4<2D949:4N3:60>H50?>0B?684:L1<=2<F;22?6@=959M6<633G82=95A2807?K4>;=1E>4:;;O0:11=I:0<?7C<6759M6<>33G825>5A3168J667<2D8<<:4N2210>H48:>0B>>;4:L0402<F::=86@<0668J66?<2D8<4=4N237?K568=1E?<?;;O1261=I;89?7C=>459M74333G9::95A3057?K560=1E?<7<;O110>H4:9>0B><>4:L0672<F:8886@<2568J642<2D8>;:4N2040>H4:1>0B><63:L071=I;::?7C=<159M76433G98?95A3267?K54==1E?>8;;O1031=I;:2?7C=<929M712<F:>;86@<4068J625<2D88>:4N2670>H4<<>0B>:94:L0022<F:>386@<4818J6333G9><95A3437?K52:=1E?8=<;O157>H4?:1E?5=4N2;1?K243G>;?6@;129M075<F=987C:;3:L716=I<?90B99<;O6;7>H31:1E9==4N430?K35;2D>?>5A5518J0343G?=?6@:729M1=5<F<397C8<;O437>H19:1E:?=4N710?K03;2D=9>5A6718J3143G<3?6@9939M36=I?990B:?<;O517>H0;:1E;9=4N670?K11;2D<;>5A7808J=5<F1;87C6=3:L;76=I0=90B5;<;O:57>H??:1E45=4N9;1?K?43G3;?6@6129M=75<F0987C7;3:L:16=I1?90B49<;O;;7>H>1o1ENRLZSQKM[UTHXZ=0BHZXOSI7?KIIM;1DG<5_4:RBVQg<X@DTNX]FDY`8TLHXJ\YEM@Kn;SCNF60XMQZm7_OB_DZWAKUNGGUJj6\NM^G[P@HTAFDTNn5]E@F\SLBS@VKh7_KND^UJ@QNXJ>1YIJMJAM58V@ADMH_<7_KHCD@O3>TBOJOIY55]EFAOODJ?3[OLOAENU99QABEKCKF37_KHCMIAQ1=TIOO37^OYEECWE45<[@GTOBBCIRKLJZEOMJA37^GB_LMGA3=TG\XHI:5\RWCO[D1<[[\J@RL:;RQQEI3<[ZXJY85\SS@O1>UTZK_?7YW_E4:8Q5)edbUfi`Qheogqeqiu'kgei lsup,vdkkgfzP<P }al,q+s3Xffceey }al-WVPCXLY$XECICE^RQMH51&]N[955Z0.`ooZkbeVmnbh|ntnp,rdjnl'ixx!}alnlku]6U'xja#| v4]mklhn|'xja"Z]UD]GT+UNFNFNS]\FM24-PAV202_;#obd_lgn[bcim{kc!yamkg*fusz&xjaaa`pZ0^*wgj&{%}9R``iokw*wgj']X^IRJ_.RKMCICXX[CF?; [DQ7;?P6(jeaTahcPgdlfvdrhz&|j`dj!crvq+wgjdfe{W>S!r`o-v*p2Wgebbdz!r`o,PWSBWMZ%_D@HLD]SVLK4>'^O\l5ZSDP\EIOF[j1^_H\PVHQJFIC43_IH56XFEV]W]UC03^OJ@1>17:UFEI:66>1\ILB32?;8S@GK4:0;2:5XE@N?7;1<_LK^0=08;VGBQ979?2]NMX2=>89TADS;;3:5;6YJAT>0:2=PMKF7<394WD@O84803^OI@1<17:UFFI:46>1\IOB34?58S@DK4<4<7ZKML=4==>QBJE6<6=08;VGAH919?2]NNX2?>69TAGS;97=0[HLZ<3<4?RCE]595;6YJBT>7:2=PMK_79394WD@V838>3^OIY1950?58S@DR4>4i7Z\FTD]EMWUSk2]YEYKPMNFF[De<_[C_IRC@DD]A`>QUA]OT[DJ[H^Cg?RTN\LU\EIZG_C3g?]OKAGR&TIL/0/3#WQSE(9$:,L]LIH48\VRKAK=0T^ZPGOFa?]YDG[OTECH@6:ZgfZOcn2RodR^}ilTfvvohf8:0TicPM`hlvScu{`ee==5Wdl]Nmkiu^lxxeb`7;`fgvd.7!11jhi|n(0+;?dbczh"9%55ndepb858?3hno~l2>>`9b`atf4;0;255ndepb878?3hno~o&?)`9b`ate490;255ndepa8585k2hggRcjm^efjZp4W8&+Tdbfny"@KWC'Oldn~lz`r!32*42<keaj86mckc58`gosm{x<7igaa)2*3>bnfh":%55kioc+55/?3mcem%?>)99gmkg/9;#37igaa)30-==cagk#=9'7;ekme-72!11oeco'17+;?aoii!;<%55kioc+5=/?3mcem%?6)69gmkg/: 20hd`n(32*<>bnfh"9=$64dhlb,74.02nbbl&=3(:8`lhf ;>"46jfn`*11,><l`dj$?8&8:fjjd.5? 20hd`n(3:*<>bnfh"95$94dhlb,6/?3mcem%=?)99gmkg/;8#<7igaa)6*3>bnfh">%:5kioc+2,1<l`dj$:'8;ekme->.?2nbbl&6)69gmkg;8720hd`n<02=<>bnfh6:=364dhlb844902nbbl2>3?:8`lhf48>546jfn`>21;><l`dj0<818:fjjd:6?720hd`n<0:=<>bnfh6:5394dhlb848?3mcem1<?>99gmkg;:8437igaa=01:==cagk7>>07;ekme943611oeco324<;?aoii58=255kioc?628?3mcem1<7>99gmkg;:04<7igaa=0=<>bnfh68<3o4dhlb867=8720hd`n<23=3>bnfh682:5kioc?0;1<l`dj0808;ekme909?2nbbl28>69gmkg;07=0hd`n<8<4?aoij!:";6jfnc*2-==cagh#=='6;ekmf-778 30hd`m(022-<=cagh#==<&9:fjjg.68:#27igab)330,?<l`di$<>:)89gmkd/99<"56jfnc*242/>3mcen%??8(;8`lhe 8:2%55kio`+54/>3mcen%?>0(;8`lhe 8;:%45kio`+544.12nbbo&>12+:?aoij!;:8$74dhla,472!01oecl'104*=>bnfk":=:'6;ekmf-760 30hd`m(03:-==cagh#=?'6;ekmf-758 30hd`m(002-<=cagh#=?<&9:fjjg.6::#27igab)310,?<l`di$<<:)89gmkd/9;<"56jfnc*262/?3mcen%?<)99gmkd/9=#37igab)36-==cagh#=;'7;ekmf-70!11oecl'19+;?aoij!;2%:5kio`+6,><l`di$?>&8:fjjg.59 20hd`m(30*<>bnfk"9?$64dhla,72.02nbbo&=5(:8`lhe ;<"46jfnc*13,><l`di$?6&8:fjjg.51 =0hd`m(2+;?aoij!9;%55kio`+74/?3mcen%==)99gmkd/;:#37igab)17-==cagh#?8'7;ekmf-51!11oecl'36+;?aoij!93%55kio`+7</03mcen%:&8:fjjg.38 20hd`m(53*<>bnfk"?>$64dhla,15.02nbbo&;4(:8`lhe =?"46jfnc*72,><l`di$99&8:fjjg.30 20hd`m(5;*3>bnfk">%55kio`+15/?3mcen%;>)99gmkd/=;#37igab)70-==cagh#99'7;ekmf-32!11oecl'57+;?aoij!?<%55kio`+1=/?3mcen%;6)69gmkd/> 20hd`m(72*<>bnfk"==$64dhla,34.02nbbo&93(:8`lhe ?>"46jfnc*51,><l`di$;8&8:fjjg.1? 20hd`m(7:*<>bnfk"=5$94dhla,2/?3mcen%9?)99gmkd/?8#37igab)51-==cagh#;>'7;ekmf-13!11oecl'74+;?aoij!==%55kio`+32/?3mcen%97)99gmkd/?0#<7igab):*<>bnfk"3<$64dhla,=7.02nbbo&72(:8`lhe 19"46jfnc*;0,><l`di$5;&8:fjjg.?> 20hd`m(95*<>bnfk"34$64dhla,=?.?2nbbo&6)99gmkd/19#37igab);2-==cagh#5?'7;ekmf-?4!11oecl'95+;?aoij!3>%55kio`+=3/?3mcen%78)99gmkd/11#37igab);:-2=cagh7<374dhla8467601oecl3113==>bnfk6:<?06;ekmf977;730hd`m<027:<=cagh7==;19:fjjg:68?427igab=333;?<l`di0<>7>89gmkd;993546jfnc>24;?<l`di0<??>89gmkd;98;556jfnc>2578>3mcen1?>3?;8`lhe48;?245kio`?543912nbbo2>17<:?aoij5;:;374dhla847?601oecl310;=<>bnfk6:=374dhla8447601oecl3133==>bnfk6:>?06;ekmf975;730hd`m<007:<=cagh7=?;19:fjjg:6:?4i7igab=313?6912nbbo2>26<;?aoij5;9255kio`?568?3mcen1?;>99gmkd;9<437igab=35:==cagh7=:07;ekmf97?611oecl318<4?aoij5;546jfnc>14;><l`di0??18:fjjg:5:720hd`m<31=<>bnfk698364dhla873902nbbo2=6?:8`lhe4;=546jfnc>1<;><l`di0?717:fjjg:5611oecl331<;?aoij59:255kio`?778?3mcen1=<>99gmkd;;=437igab=16:==cagh7?;07;ekmf950611oecl339<;?aoij5922:5kio`?7;><l`di09>18:fjjg:39720hd`m<50=<>bnfk6??364dhla812902nbbo2;5?:8`lhe4=<546jfnc>73;><l`di09618:fjjg:317=0hd`m<5<;?aoij5?;255kio`?148?3mcen1;=>99gmkd;=:437igab=77:==cagh79807;ekmf931611oecl356<;?aoij5?3255kio`?1<803mcen1;18:fjjg:18720hd`m<73=<>bnfk6=>364dhla835902nbbo294?:8`lhe4??546jfnc>52;><l`di0;918:fjjg:10720hd`m<7;=3>bnfk6=255kio`?358?3mcen19>>99gmkd;?;437igab=50:==cagh7;907;ekmf912611oecl377<;?aoij5=<255kio`?3=8?3mcen196>69gmkd;?720hd`m<92=<>bnfk63=364dhla8=4902nbbo273?:8`lhe41>546jfnc>;1;><l`di05818:fjjg:??720hd`m<9:=<>bnfk635394dhla8=8?3mcen17?>99gmkd;18437igab=;1:==cagh75>07;ekmf9?3611oecl394<;?aoij53=255kio`?=28?3mcen177>99gmkd;104<7igab=;=<>bh}}k#<$64dnwwe-7.12ndyyo'11+:?air|h":=$74dnwwe-75!01ocxzn(01*=>bh}}k#=9'6;emvpd.6= 30hb{{a)35-<=cg|~j$<9&9:flqqg/91#27iazt`*2=,><lfm%<&9:flqqg/:9#27iazt`*15,?<lfm%<=)89gkprf ;9"56j`uuc+61/>3me~xl&=5(;8`jssi!8=%45kotvb,71.12ndyyo'29+:?air|h"95$64dnwwe-5.12ndyyo'31+:?air|h"8=$64dnwwe-2.02ndyyo'5(:8`jssi!<"46j`uuc+3,><lfm%6&8:flqqg/1 20hb{{a=2==>bh}}k7==06;emvpd:69730hb{{a=31:<=cg|~j0<=19:flqqg;9=427iazt`>21;?<lfm1?9>89gkprf48=556j`uuc?5=8>3me~xl2>9?:8`jssi5;556j`uuc?658>3me~xl2=1?;8`jssi589245kotvb875912ndyyo325<:?air|h699374dnwwe941601ocxzn<35==>bh}}k7>506;emvpd:51720hb{{a=0==>bh}}k7?=0m;emvpd:493:556j`uuc?748?3me~xl2<>99gkprf4=437iazt`>6:==cg|~j0;07;emvpd:0611ocxzn<9<;?air|h62255kotva,5/?3me~xo&>)89gkpre 8:"m6j`uu`+556.i2ndyyl'113*e>bh}}h#==<&a:flqqd/999"m6j`uu`+552.i2ndyyl'117*e>bh}}h#==8&a:flqqd/99="m6j`uu`+55>.i2ndyyl'11;*=>bh}}h#=<'n;emvpg.699#j7iaztc*254/f3me~xo&>13+b?air|k":=>'n;emvpg.69=#j7iaztc*250/f3me~xo&>17+b?air|k":=:'n;emvpg.691#j7iaztc*25</>3me~xo&>2(c8`jssj!;9<$o4dnwwf-759 k0hb{{b)316,g<lfn%?=3(c8`jssj!;98$o4dnwwf-75= k0hb{{b)312,g<lfn%?=7(;8`jssj!;8%45kotva,42.12ndyyl'14+:?air|k"::$74dnwwf-70!01ocxzm(0:*=>bh}}h#=4'7;emvpg.5!01ocxzm(32*=>bh}}h#><'6;emvpg.5: 30hb{{b)00-<=cg|~i$?:&9:flqqd/:<#27iaztc*12,?<lfn%<8)89gkpre ;2"56j`uu`+6</?3me~xo&<)89gkpre ::"56j`uu`+74/>3me~xo&<2(;8`jssj!98%45kotva,62.12ndyyl'34+:?air|k"8:$74dnwwf-50!01ocxzm(2:*=>bh}}h#?4'7;emvpg.3!01ocxzm(52*=>bh}}h#8<'6;emvpg.3: 30hb{{b)60-<=cg|~i$9:&9:flqqd/<<#27iaztc*72,?<lfn%:8)89gkpre =2"56j`uu`+0</?3me~xo&:)89gkpre <:"56j`uu`+14/>3me~xo&:2(;8`jssj!?8%45kotva,02.12ndyyl'54+:?air|k">:$74dnwwf-30!01ocxzm(4:*=>bh}}h#94'7;emvpg.1!01ocxzm(72*=>bh}}h#:<'6;emvpg.1: 30hb{{b)40-<=cg|~i$;:&9:flqqd/><#27iaztc*52,?<lfn%88)89gkpre ?2"56j`uu`+2</?3me~xo&8)89gkpre >:"56j`uu`+34/>3me~xo&82(;8`jssj!=8%45kotva,22.12ndyyl'74+:?air|k"<:$74dnwwf-10!01ocxzm(6:*=>bh}}h#;4'7;emvpg.?!01ocxzm(92*=>bh}}h#4<'6;emvpg.?: 30hb{{b):0-<=cg|~i$5:&9:flqqd/0<#27iaztc*;2,?<lfn%68)89gkpre 12"56j`uu`+<</?3me~xo&6)89gkpre 0:"56j`uu`+=4/>3me~xo&62(;8`jssj!38%45kotva,<2.12ndyyl'94+:?air|k"2:$74dnwwf-?0!01ocxzm(8:*=>bh}}h#54'7;emvpg:76h1ocxzm<023:d=cg|~i0<>>>`9gkpre48:92l5kotva84646h1ocxzm<027:d=cg|~i0<>:>`9gkpre48:=2l5kotva84606h1ocxzm<02;:d=cg|~i0<>6>89gkpre48:5m6j`uu`?5469i2ndyyl3103=e>bh}}h7=<<1a:flqqd;9895m6j`uu`?5429i2ndyyl3107=e>bh}}h7=<81a:flqqd;98=5m6j`uu`?54>9i2ndyyl310;==>bh}}h7=<0n;emvpg:6:94j7iaztc>2648f3me~xo2>23<b?air|k6:>>0n;emvpg:6:=4j7iaztc>2608f3me~xo2>27<`?air|k6:>:4?>`9gkpre488<245kotva844912ndyyl312<:?air|k6:8374dnwwf972601ocxzm<04==>bh}}h7=:06;emvpg:60730hb{{b=3::==cg|~i0<06;emvpg:58730hb{{b=02:<=cg|~i0?<19:flqqd;::427iaztc>10;?<lfn1<:>89gkpre4;<556j`uu`?628>3me~xo2=8?;8`jssj582255kotva878>3me~xo2<0?;8`jssj59:245kotva864912ndyyl332<:?air|k688374dnwwf952601ocxzm<24==>bh}}h7?:06;emvpg:40730hb{{b=1::==cg|~i0>06;emvpg:38730hb{{b=62:<=cg|~i09<19:flqqd;<:427iaztc>70;?<lfn1::>89gkpre4=<556j`uu`?028>3me~xo2;8?;8`jssj5>2255kotva818>3me~xo2:0?;8`jssj5?:245kotva804912ndyyl352<:?air|k6>8374dnwwf932601ocxzm<44==>bh}}h79:06;emvpg:20730hb{{b=7::==cg|~i0806;emvpg:18730hb{{b=42:<=cg|~i0;<19:flqqd;>:427iaztc>50;?<lfn18:>89gkpre4?<556j`uu`?228>3me~xo298?;8`jssj5<2255kotva838>3me~xo280?;8`jssj5=:245kotva824912ndyyl372<:?air|k6<8374dnwwf912601ocxzm<64==>bh}}h7;:06;emvpg:00730hb{{b=5::==cg|~i0:06;emvpg:?8730hb{{b=:2:<=cg|~i05<19:flqqd;0:427iaztc>;0;?<lfn16:>89gkpre41<556j`uu`?<28>3me~xo278?;8`jssj522255kotva8=8>3me~xo260?;8`jssj53:245kotva8<4912ndyyl392<:?air|k628374dnwwf9?2601ocxzm<84==>bh}}h75:06;emvpg:>0730hb{{b=;::==cg|~i0407;dfjb7h`l:1nbl=4eo`g?lhmmj~ondzjrsf8mklbk}yieyk}r048ii379Vno~?Qxb^ke[fgd`l9:7`b:00]g`w4XkUbjRmncig/fimXelgTkh`Pv2]2(KIIM%DDBH=l5:oo157Xlmx9SzlPig]`efnb$kf`S`kb_fgm[s5X9%qhSeo|_sgdg`d:8%iTdl}Prde`ad;7$jUfi`Q{yqg>6)eXzz~ym`Qm=1.`[wuszhgTm0>#c^pppZr~xl7XUCM#c^jbwZoiblii|20-a\twojW}s{i0?#c^kmmqdX~hf6<!mPrdcg[roc|aUi1<<7,b]qadbX`ndRo233.`[aotikfnSzo}n^`krZehde7; nQfnhv\bljbWgkfi0``_bmf[cokmVfdmikk,b]tvlrbWdeoiRl2WSKWAZ@NZZ^'oRy}iug\ijbbWh7\^DZJ_GKQWQ*dWdsS}gemkmaZusinox1="l_icp[hcjWf|xzPrdep[g;7$jUgcljPiokw[cokm4:'oRfns^ofiZir|ySkhs^c>4)eX{ciRjjpuj\f84+kV}yeykPddrwlZg:0%iTdl}Prrva95*dWakxS}{a<2/gZoia}kTzlb20-a\lduXe|rTcxzuu]qabuXj4:'oRfns^ov|Zir|ySkhs^c>4)eXimnymRyfduj>7)eXimnynRyfduj>5)eXllljyazPd`vb95*dW|ynShml=1.`[dj`g{cd`3>,b]gmvgedlU|m`Pbit\vdh`m4:'oRy}iug\slbs`Vh6=?6#c^uqmqcX`ndRo233.`[wcflVnn|yfPb<0/gZd~|lUxewk28-a\v`gcWmo{xeQn=9.`[vojWjeg`d}foo]`l`el5HFG nQlololjZekc4:'oRyja^uj`qn:<%iTdl}Peo`>5)eX`hyTico21-a\s`dX`nd0?9,bmntjhbf}Uem`k2mm735Zbcz;U|nRgi_bc`l`*dW|ynSow{e^uff87+kVxiRlvtd]tad;6$jUyyQrhmqmqXj4IN nQ}su]svliua}sTm0MJ,b]vw`Ycmok~`yQkauc>4){5l2gg9=?Pdep1[rdXaoUhmnfj_cnh[hcjWnoeS{=P1^zppZ7?3gmhnxgcdb9q`dbczlih$='j;sfb`atbkj6;6=0l;sfb`atbkj6;2;5}efafe3=umninn95}suc7?wusj>1xndzjrs01?qkw'Vil#`b:00]g`w4XkUbjRmncig-jbi13~oj$='9;vgb,4/13~oj$?'9;vgb,6/13~oj0=09;vgb84813~oj0?07;vgb86<76?1|il2<>79tag.7!?1|io&>)69tag.68 =0{hl'10+4?rce 88";6yjb)30-2=pmk":8$94wd`+50/13~oi$?'9;vga,6/13~oi$9'9;vga,0/13~oi$;'9;vga,2/13~oi$5'9;vga,</13~oi0=08;vga8469?2}nn1?>>69tag:6:7=0{hl312<4?rce48>556yjb=36>5803~oi0<;16:uff979>2}nn1<16:uff959>2}nn1:16:uff939>2}nn1816:uff919>2}nn1616:uff9?9uIJ{mk;4@Az6ba<A2=0:w^9=:4ga>6<6;;h?:h4=10afk52?3;0b>;7:49'703=;<;0q^9?:4ga>6<6;;h?:h4=10af?V7f?3?m87>5120a03c=:8;hj6]80;7e0?6=9:8i8;k5203g4>b2n90;6<4>{R51>0ce2:0:??l;6d8154eb3^8>=4?:082>43csZ=968km:28277d3>l09=<mj;%11b?7f02\89;4={t3b=?7<}8kj6=5r$22`>4d<j<l;6=4>5b80>43dsA99h6T92;:x5=<f2891n7?=:48e>1<z,:8<68h?;%160?51;2c>in4?::k6aa<722c=<<4?:%13a?07=2d8<i4?;:k545<72-9;i78?5:l04a<632c>jk4?:%13a?07=2d8<i4=;:k6b`<72-9;i78?5:l04a<432c=<h4?:%13a?06l2d8<i4?;:k54a<72-9;i78>d:l04a<632c=<n4?:%13a?06l2d8<i4=;:k54g<72-9;i78>d:l04a<432c=<l4?:%13a?06l2d8<i4;;:k54<<72-9;i78>d:l04a<232c==;4?:%13a?06l2d8<i49;:k550<72-9;i78>d:l04a<032c==94?:%13a?06l2d8<i47;:k556<72-9;i78>d:l04a<>32c==?4?:%13a?06l2d8<i4n;:k554<72-9;i78>d:l04a<e32c===4?:%13a?06l2d8<i4l;:k54c<72-9;i78>d:l04a<c32c=<54?:%13a?06l2d8<i4j;:k542<72-9;i78>d:l04a<a32c89o4?:%13a?52m2d8<i4?;:k01d<72-9;i7=:e:l04a<632c8944?:%13a?52m2d8<i4=;:k025<72-9;i7=91:l04a<732e?o?4?:%13a?2b92d8<i4?;:m7g4<72-9;i7:j1:l04a<632e?nk4?:%13a?2b92d8<i4=;:m7f`<72-9;i7:j1:l04a<432e?ni4?:%13a?2b92d8<i4;;:m7ff<72-9;i7:j1:l04a<232e?no4?:%13a?2b92d8<i49;:m7fd<72-9;i7:j1:l04a<032e?n44?:%13a?2b92d8<i47;:m7f=<72-9;i7:j1:l04a<>32e?n:4?:%13a?2b92d8<i4n;:m7f3<72-9;i7:j1:l04a<e32e?n94?:%13a?2b92d8<i4l;:m7f6<72-9;i7:j1:l04a<c32e?n?4?:%13a?2b92d8<i4j;:m7f4<72-9;i7:j1:l04a<a32e?n=4?:%13a?2b92d8<i4>0:9l0d`=83.8<h4;e09m75b=9810c9oj:18'75c=<l;0b>>k:008?j2fl3:1(>>j:5g2?k57l3;876a;ab83>!57m3>n=6`<0e820>=h<hh1<7*<0d87a4=i;9n1=854o5a;>5<#;9o18h?4n22g>40<3f>h;7>5$22f>1c63g9;h7?8;:m7g3<72-9;i7:j1:l04a<6021d8n;50;&04`<3m81e?=j51898k1e3290/?=k54d38j66c28k07b:l3;29 66b2=o:7c=?d;3a?>i3k90;6)=?e;6f5>h48m0:o65`4c794?"48l0?i<5a31f95a=<g=kj6=4+31g90`7<f::o6<k4;n6b=?6=,::n69k>;o13`?7a32e><l4?:%13a?3?02d8<i4?;:m64<<72-9;i7;78:l04a<632e><54?:%13a?3?02d8<i4=;:m642<72-9;i7;78:l04a<432e><;4?:%13a?3?02d8<i4;;:m640<72-9;i7;78:l04a<232e><94?:%13a?3?02d8<i49;:m646<72-9;i7;78:l04a<032e><<4?:%13a?3?02d8<i47;:m645<72-9;i7;78:l04a<>32e?jk4?:%13a?3?02d8<i4n;:m7b`<72-9;i7;78:l04a<e32e?ji4?:%13a?3?02d8<i4l;:m7bf<72-9;i7;78:l04a<c32e?jo4?:%13a?3?02d8<i4j;:m7bd<72-9;i7;78:l04a<a32e?j44?:%13a?3?02d8<i4>0:9l0c>=83.8<h4:899m75b=9810c9h9:18'75c==120b>>k:008?j2a=3:1(>>j:4:;?k57l3;876a;f583>!57m3?346`<0e820>=h<o91<7*<0d86<==i;9n1=854o5d1>5<#;9o19564n22g>40<3f>m=7>5$22f>0>?3g9;h7?8;:m7b5<72-9;i7;78:l04a<6021d8hh50;&04`<2011e?=j51898k1cb290/?=k559:8j66c28k07b:jd;29 66b2<237c=?d;3a?>i2>00;6)=?e;7;<>h48m0:o65`57:94?"48l0>455a31f95a=<g<<<6=4+31g91=><f::o6<k4;n752?6=,::n6867;o13`?7a32e>:84?:%13a?3?02d8<i4=0:9l132=83.8<h4:899m75b=:810c88<:18'75c==120b>>k:308?j31:3:1(>>j:4:;?k57l38876a:6083>!57m3?346`<0e810>=h=?:1<7*<0d86<==i;9n1>854o47f>5<#;9o19564n22g>70<3f?>h7>5$22f>0>?3g9;h7<8;:m61f<72-9;i7;78:l04a<5021d98l50;&04`<2011e?=j52898k03f290/?=k559:8j66c2;k07b;:9;29 66b2<237c=?d;0a?>i2=10;6)=?e;7;<>h48m09o65`54594?"48l0>455a31f96a=<g<?=6=4+31g91=><f::o6?k4;n761?6=,::n6867;o13`?4a32e>9>4?:%13a?3?02d8<i4<0:9l104=83.8<h4:899m75b=;810c8;>:18'75c==120b>>k:208?j3283:1(>>j:4:;?k57l39876a:4g83>!57m3?346`<0e800>=h==o1<7*<0d86<==i;9n1?854o46g>5<#;9o19564n22g>60<3f??o7>5$22f>0>?3g9;h7=8;:m60g<72-9;i7;78:l04a<4021d99o50;&04`<2011e?=j53898k02?290/?=k559:8j66c2:k07b;;7;29 66b2<237c=?d;1a?>i2<?0;6)=?e;7;<>h48m08o65`55794?"48l0>455a31f97a=<g<>?6=4+31g91=><f::o6>k4;n777?6=,::n6867;o13`?5a32e>8?4?:%13a?3?02d8<i4;0:9l117=83.8<h4:899m75b=<810c8:?:18'75c==120b>>k:508?j34n3:1(>>j:4:;?k57l3>876a:3e83>!57m3?346`<0e870>=h=:i1<7*<0d86<==i;9n18854o41a>5<#;9o19564n22g>10<3f?8m7>5$22f>0>?3g9;h7:8;:m67<<72-9;i7;78:l04a<3021d9>650;&04`<2011e?=j54898k050290/?=k559:8j66c2=k07b;<6;29 66b2<237c=?d;6a?>i2;<0;6)=?e;7;<>h48m0?o65`52694?"48l0>455a31f90a=<g<996=4+31g91=><f::o69k4;n705?6=,::n6867;o13`?2a32e>?=4?:%13a?3?02d8<i4:0:9l17`=83.8<h4:899m75b==810c8<j:18'75c==120b>>k:408?j35l3:1(>>j:4:;?k57l3?876a:2b83>!57m3?346`<0e860>=h=;h1<7*<0d86<==i;9n19854o40b>5<#;9o19564n22g>00<3f?957>5$22f>0>?3g9;h7;8;:m662<72-9;i7;78:l04a<2021d9?850;&04`<2011e?=j55898k042290/?=k559:8j66c2<k07b;=4;29 66b2<237c=?d;7a?>i2::0;6)=?e;7;<>h48m0>o65`53094?"48l0>455a31f91a=<g<8:6=4+31g91=><f::o68k4;n714?6=,::n6867;o13`?3a32e>=k4?:%13a?3?02d8<i490:9l14c=83.8<h4:899m75b=>810c8?l:18'75c==120b>>k:708?j36j3:1(>>j:4:;?k57l3<876a:1`83>!57m3?346`<0e850>=h=831<7*<0d86<==i;9n1:854o43;>5<#;9o19564n22g>30<3f?:;7>5$22f>0>?3g9;h788;:m653<72-9;i7;78:l04a<1021d9<;50;&04`<2011e?=j56898k073290/?=k559:8j66c2?k07b;>3;29 66b2<237c=?d;4a?>i2980;6)=?e;7;<>h48m0=o65`50294?"48l0>455a31f92a=<g<:m6=4+31g91=><f::o6;k4;n73a?6=,::n6867;o13`?0a32e><i4?:%13a?3?02d8<i480:9l15e=83.8<h4:899m75b=?810c8>m:18'75c==120b>>k:608?j37:3:1(>>j:4:;?k57l3=876a;f683>!57m3?346`<0e840>=h<li1<7*<0d86<==i;9n1;854o47e>5<#;9o19564n22g>20<3f?>87>5$22f>0>?3g9;h798;:m60<<72-9;i7;78:l04a<0021d9>k50;&04`<2011e?=j57898k054290/?=k559:8j66c2>k07b;=8;29 66b2<237c=?d;5a?>i29m0;6)=?e;7;<>h48m0<o65`50094?"48l0>455a31f93a=<g=oi6=4+31g91=><f::o6:k4;n6fe?6=,::n6867;o13`?1a32c8:94?::k020<722c84=4?:%13a?5>n2d8<i4?;:k03c<72-9;i7=6f:l04a<632c8;i4?:%13a?5>n2d8<i4=;:k03f<72-9;i7=6f:l04a<432c8;o4?:%13a?5>n2d8<i4;;:k03d<72-9;i7=6f:l04a<232c8;44?:%13a?5>n2d8<i49;:k03=<72-9;i7=6f:l04a<032c8;:4?:%13a?5>n2d8<i47;:k033<72-9;i7=6f:l04a<>32c8;84?:%13a?5>n2d8<i4n;:k031<72-9;i7=6f:l04a<e32c8;?4?:%13a?5>n2d8<i4l;:k034<72-9;i7=6f:l04a<c32c8;=4?:%13a?5>n2d8<i4j;:k02c<72-9;i7=6f:l04a<a32c8:h4?:%13a?5>n2d8<i4>0:9j73b=83.8<h4<9g9m75b=9810e>8l:18'75c=;0l0b>>k:008?l51j3:1(>>j:2;e?k57l3;876g<6`83>!57m392j6`<0e820>=n;?31<7*<0d80=c=i;9n1=854i2:5>5<#;9o1?4h4n22g>40<3`9397>5$22f>6?a3g9;h7?8;:k0<1<72-9;i7=6f:l04a<6021b?5=50;&04`<41o1e?=j51898m6>5290/?=k538d8j66c28k07d=71;29 66b2:3m7c=?d;3a?>o4?l0;6)=?e;1:b>h48m0:o65f36194?"48l085k5a31f95a=<a:<36=4+31g97<`<f::o6<k4;h153?6=,::n6>7i;o13`?7a32c8o54?:%13a?23>2d8<i4?;:k0g2<72-9;i7:;6:l04a<632c8o;4?:%13a?23>2d8<i4=;:k0g0<72-9;i7:;6:l04a<432c8o94?:%13a?23>2d8<i4;;:k0g6<72-9;i7:;6:l04a<232c8o?4?:%13a?23>2d8<i49;:k0g4<72-9;i7:;6:l04a<032c8nk4?:%13a?23>2d8<i47;:k0f`<72-9;i7:;6:l04a<>32c8ni4?:%13a?23>2d8<i4n;:k0ff<72-9;i7:;6:l04a<e32c8no4?:%13a?23>2d8<i4l;:k0fd<72-9;i7:;6:l04a<c32c8n44?:%13a?23>2d8<i4j;:k0f=<72-9;i7:;6:l04a<a32c8n:4?:%13a?23>2d8<i4>0:9j7g0=83.8<h4;479m75b=9810e>l;:18'75c=<=<0b>>k:008?l5e;3:1(>>j:565?k57l3;876g<b383>!57m3>?:6`<0e820>=n;k;1<7*<0d8703=i;9n1=854i2`3>5<#;9o18984n22g>40<3`9jj7>5$22f>1213g9;h7?8;:k0e`<72-9;i7:;6:l04a<6021b?lj50;&04`<3<?1e?=j51898m6gd290/?=k54548j66c28k07d=nb;29 66b2=>=7c=?d;3a?>o3:>0;6)=?e;672>h48m0:o65f43494?"48l0?8;5a31f95a=<a=8>6=4+31g9010<f::o6<k4;h610?6=,::n69:9;o13`?7a32c?>>4?:%13a?23>2d8<i4=0:9j074=83.8<h4;479m75b=:810e9<>:18'75c=<=<0b>>k:308?l2583:1(>>j:565?k57l38876g;1g83>!57m3>?:6`<0e810>=n<8o1<7*<0d8703=i;9n1>854i53`>5<#;9o18984n22g>70<3`>:n7>5$22f>1213g9;h7<8;:k75d<72-9;i7:;6:l04a<5021b8<750;&04`<3<?1e?=j52898m17?290/?=k54548j66c2;k07d:>7;29 66b2=>=7c=?d;0a?>o39?0;6)=?e;672>h48m09o65f40794?"48l0?8;5a31f96a=<a=;?6=4+31g9010<f::o6?k4;h627?6=,::n69:9;o13`?4a32c?=<4?:%13a?23>2d8<i4<0:9j046=83.8<h4;479m75b=;810e9>i:18'75c=<=<0b>>k:208?l27m3:1(>>j:565?k57l39876g;0e83>!57m3>?:6`<0e800>=n<9i1<7*<0d8703=i;9n1?854i52a>5<#;9o18984n22g>60<3`>;m7>5$22f>1213g9;h7=8;:k74<<72-9;i7:;6:l04a<4021b8=650;&04`<3<?1e?=j53898m161290/?=k54548j66c2:k07d:?5;29 66b2=>=7c=?d;1a?>o38=0;6)=?e;672>h48m08o65f41194?"48l0?8;5a31f97a=<a=:96=4+31g9010<f::o6>k4;h635?6=,::n69:9;o13`?5a32c?<=4?:%13a?23>2d8<i4;0:9j7c`=83.8<h4;479m75b=<810e>hj:18'75c=<=<0b>>k:508?l5al3:1(>>j:565?k57l3>876g<fc83>!57m3>?:6`<0e870>=n;ok1<7*<0d8703=i;9n18854i2d:>5<#;9o18984n22g>10<3`9m47>5$22f>1213g9;h7:8;:k0b2<72-9;i7:;6:l04a<3021b?k850;&04`<3<?1e?=j54898m6`2290/?=k54548j66c2=k07d=i4;29 66b2=>=7c=?d;6a?>o4n:0;6)=?e;672>h48m0?o65f3g094?"48l0?8;5a31f90a=<a:l;6=4+31g9010<f::o69k4;h1fb?6=,::n69:9;o13`?2a32c8ih4?:%13a?23>2d8<i4:0:9j7`b=83.8<h4;479m75b==810e>kl:18'75c=<=<0b>>k:408?l5bj3:1(>>j:565?k57l3?876g<e`83>!57m3>?:6`<0e860>=n;l31<7*<0d8703=i;9n19854i2g;>5<#;9o18984n22g>00<3`9n;7>5$22f>1213g9;h7;8;:k0a0<72-9;i7:;6:l04a<2021b?h:50;&04`<3<?1e?=j55898m6c4290/?=k54548j66c2<k07d=j2;29 66b2=>=7c=?d;7a?>o4m80;6)=?e;672>h48m0>o65f3d294?"48l0?8;5a31f91a=<a:nm6=4+31g9010<f::o68k4;h1ga?6=,::n69:9;o13`?3a32c8hi4?:%13a?23>2d8<i490:9j7ae=83.8<h4;479m75b=>810e>jn:18'75c=<=<0b>>k:708?l5c13:1(>>j:565?k57l3<876g<d983>!57m3>?:6`<0e850>=n;m=1<7*<0d8703=i;9n1:854i2f5>5<#;9o18984n22g>30<3`9o97>5$22f>1213g9;h788;:k0`1<72-9;i7:;6:l04a<1021b?i=50;&04`<3<?1e?=j56898m6b5290/?=k54548j66c2?k07d=k1;29 66b2=>=7c=?d;4a?>o4ko0;6)=?e;672>h48m0=o65f3bg94?"48l0?8;5a31f92a=<a:io6=4+31g9010<f::o6;k4;h1`g?6=,::n69:9;o13`?0a32c8oo4?:%13a?23>2d8<i480:9j7fg=83.8<h4;479m75b=?810e>m6:18'75c=<=<0b>>k:608?l5d83:1(>>j:565?k57l3=876g<b483>!57m3>?:6`<0e840>=n;hk1<7*<0d8703=i;9n1;854i53g>5<#;9o18984n22g>20<3`>:>7>5$22f>1213g9;h798;:k742<72-9;i7:;6:l04a<0021b?km50;&04`<3<?1e?=j57898m6`6290/?=k54548j66c2>k07d=j6;29 66b2=>=7c=?d;5a?>o4lk0;6)=?e;672>h48m0<o65f3e294?"48l0?8;5a31f93a=<a:k26=4+31g9010<f::o6:k4;h1b<?6=,::n69:9;o13`?1a32h8>h4?:083>5}O;;n0(><8:20f?j57j3:17pl>1283>4<729qC??j4$204>4743f;:>7>5;|`55?6=9??197?:dzJ06a=]>;0:>v?7:`827?d=9;0>6n4i:58`>44==3;36l4>3;`9b?2=u-99;7;i3:&5f?3a92.<=7;i2:&042<48h1b9hm50;9j1`b=831b9hk50;9j1c>=831b9k750;9j257=83.8<h49049m75b=821b:=>50;&04`<18<1e?=j51:9j1c`=83.8<h49049m75b=:21b9kk50;&04`<18<1e?=j53:9j25c=83.8<h491e9m75b=821b:=j50;&04`<19m1e?=j51:9j25e=83.8<h491e9m75b=:21b:=l50;&04`<19m1e?=j53:9j25g=83.8<h491e9m75b=<21b:=750;&04`<19m1e?=j55:9j240=83.8<h491e9m75b=>21b:<;50;&04`<19m1e?=j57:9j242=83.8<h491e9m75b=021b:<=50;&04`<19m1e?=j59:9j244=83.8<h491e9m75b=i21b:<?50;&04`<19m1e?=j5b:9j246=83.8<h491e9m75b=k21b:=h50;&04`<19m1e?=j5d:9j25>=83.8<h491e9m75b=m21b:=950;&04`<19m1e?=j5f:9j70d=83.8<h4<5d9m75b=821b?8o50;&04`<4=l1e?=j51:9j70?=83.8<h4<5d9m75b=:21b?;>50;&04`<4>81e?=j50:9j1cg=831b9kl50;9l1ce=831d8n<50;&04`<3m81e?=j50:9l0f7=83.8<h4;e09m75b=921d8oh50;&04`<3m81e?=j52:9l0gc=83.8<h4;e09m75b=;21d8oj50;&04`<3m81e?=j54:9l0ge=83.8<h4;e09m75b==21d8ol50;&04`<3m81e?=j56:9l0gg=83.8<h4;e09m75b=?21d8o750;&04`<3m81e?=j58:9l0g>=83.8<h4;e09m75b=121d8o950;&04`<3m81e?=j5a:9l0g0=83.8<h4;e09m75b=j21d8o:50;&04`<3m81e?=j5c:9l0g5=83.8<h4;e09m75b=l21d8o<50;&04`<3m81e?=j5e:9l0g7=83.8<h4;e09m75b=n21d8o>50;&04`<3m81e?=j51198k1ga290/?=k54d38j66c28;07b:ne;29 66b2=o:7c=?d;31?>i3im0;6)=?e;6f5>h48m0:?65`4`a94?"48l0?i<5a31f951=<g=ki6=4+31g90`7<f::o6<;4;n6`<?6=,::n69k>;o13`?7132e?o:4?:%13a?2b92d8<i4>7:9l0f0=83.8<h4;e09m75b=9110c9m::18'75c=<l;0b>>k:0;8?j2d<3:1(>>j:5g2?k57l3;j76a;c283>!57m3>n=6`<0e82f>=h<j:1<7*<0d87a4=i;9n1=n54o5`6>5<#;9o18h?4n22g>4b<3f>jm7>5$22f>1c63g9;h7?j;:m7e<<72-9;i7:j1:l04a<6n21d9=o50;&04`<2011e?=j50:9l15?=83.8<h4:899m75b=921d9=650;&04`<2011e?=j52:9l151=83.8<h4:899m75b=;21d9=850;&04`<2011e?=j54:9l153=83.8<h4:899m75b==21d9=:50;&04`<2011e?=j56:9l155=83.8<h4:899m75b=?21d9=?50;&04`<2011e?=j58:9l156=83.8<h4:899m75b=121d8kh50;&04`<2011e?=j5a:9l0cc=83.8<h4:899m75b=j21d8kj50;&04`<2011e?=j5c:9l0ce=83.8<h4:899m75b=l21d8kl50;&04`<2011e?=j5e:9l0cg=83.8<h4:899m75b=n21d8k750;&04`<2011e?=j51198k1`?290/?=k559:8j66c28;07b:i6;29 66b2<237c=?d;31?>i3n<0;6)=?e;7;<>h48m0:?65`4g694?"48l0>455a31f951=<g=l86=4+31g91=><f::o6<;4;n6e6?6=,::n6867;o13`?7132e?j<4?:%13a?3?02d8<i4>7:9l0c6=83.8<h4:899m75b=9110c9ki:18'75c==120b>>k:0;8?j2bm3:1(>>j:4:;?k57l3;j76a;ee83>!57m3?346`<0e82f>=h=?31<7*<0d86<==i;9n1=n54o44;>5<#;9o19564n22g>4b<3f?=;7>5$22f>0>?3g9;h7?j;:m623<72-9;i7;78:l04a<6n21d9;;50;&04`<2011e?=j52198k003290/?=k559:8j66c2;;07b;93;29 66b2<237c=?d;01?>i2>;0;6)=?e;7;<>h48m09?65`57394?"48l0>455a31f961=<g<<;6=4+31g91=><f::o6?;4;n76a?6=,::n6867;o13`?4132e>9i4?:%13a?3?02d8<i4=7:9l10e=83.8<h4:899m75b=:110c8;m:18'75c==120b>>k:3;8?j32i3:1(>>j:4:;?k57l38j76a:5883>!57m3?346`<0e81f>=h=<21<7*<0d86<==i;9n1>n54o474>5<#;9o19564n22g>7b<3f?>:7>5$22f>0>?3g9;h7<j;:m610<72-9;i7;78:l04a<5n21d98=50;&04`<2011e?=j53198k035290/?=k559:8j66c2:;07b;:1;29 66b2<237c=?d;11?>i2=90;6)=?e;7;<>h48m08?65`55d94?"48l0>455a31f971=<g<>n6=4+31g91=><f::o6>;4;n77`?6=,::n6867;o13`?5132e>8n4?:%13a?3?02d8<i4<7:9l11d=83.8<h4:899m75b=;110c8:n:18'75c==120b>>k:2;8?j3303:1(>>j:4:;?k57l39j76a:4683>!57m3?346`<0e80f>=h==<1<7*<0d86<==i;9n1?n54o466>5<#;9o19564n22g>6b<3f??87>5$22f>0>?3g9;h7=j;:m606<72-9;i7;78:l04a<4n21d99<50;&04`<2011e?=j54198k026290/?=k559:8j66c2=;07b;;0;29 66b2<237c=?d;61?>i2;o0;6)=?e;7;<>h48m0??65`52f94?"48l0>455a31f901=<g<9h6=4+31g91=><f::o69;4;n70f?6=,::n6867;o13`?2132e>?l4?:%13a?3?02d8<i4;7:9l16?=83.8<h4:899m75b=<110c8=7:18'75c==120b>>k:5;8?j34?3:1(>>j:4:;?k57l3>j76a:3783>!57m3?346`<0e87f>=h=:?1<7*<0d86<==i;9n18n54o417>5<#;9o19564n22g>1b<3f?8>7>5$22f>0>?3g9;h7:j;:m674<72-9;i7;78:l04a<3n21d9>>50;&04`<2011e?=j55198k04a290/?=k559:8j66c2<;07b;=e;29 66b2<237c=?d;71?>i2:m0;6)=?e;7;<>h48m0>?65`53a94?"48l0>455a31f911=<g<8i6=4+31g91=><f::o68;4;n71e?6=,::n6867;o13`?3132e>>44?:%13a?3?02d8<i4:7:9l171=83.8<h4:899m75b==110c8<9:18'75c==120b>>k:4;8?j35=3:1(>>j:4:;?k57l3?j76a:2583>!57m3?346`<0e86f>=h=;91<7*<0d86<==i;9n19n54o401>5<#;9o19564n22g>0b<3f?9=7>5$22f>0>?3g9;h7;j;:m665<72-9;i7;78:l04a<2n21d9<h50;&04`<2011e?=j56198k07b290/?=k559:8j66c2?;07b;>c;29 66b2<237c=?d;41?>i29k0;6)=?e;7;<>h48m0=?65`50c94?"48l0>455a31f921=<g<;26=4+31g91=><f::o6;;4;n72<?6=,::n6867;o13`?0132e>=:4?:%13a?3?02d8<i497:9l140=83.8<h4:899m75b=>110c8?::18'75c==120b>>k:7;8?j36<3:1(>>j:4:;?k57l3<j76a:1283>!57m3?346`<0e85f>=h=8;1<7*<0d86<==i;9n1:n54o433>5<#;9o19564n22g>3b<3f?;j7>5$22f>0>?3g9;h78j;:m64`<72-9;i7;78:l04a<1n21d9=j50;&04`<2011e?=j57198k06d290/?=k559:8j66c2>;07b;?b;29 66b2<237c=?d;51?>i28;0;6)=?e;7;<>h48m0<?65`4g594?"48l0>455a31f931=<g=oh6=4+31g91=><f::o6:;4;n76b?6=,::n6867;o13`?1132e>994?:%13a?3?02d8<i487:9l11?=83.8<h4:899m75b=?110c8=j:18'75c==120b>>k:6;8?j34;3:1(>>j:4:;?k57l3=j76a:2983>!57m3?346`<0e84f>=h=8n1<7*<0d86<==i;9n1;n54o431>5<#;9o19564n22g>2b<3f>nn7>5$22f>0>?3g9;h79j;:m7ad<72-9;i7;78:l04a<0n21b?;:50;9j733=831d9k;50;&04`<2n?1e?=j50:9j7=6=83.8<h4<9g9m75b=821b?:h50;&04`<41o1e?=j51:9j72b=83.8<h4<9g9m75b=:21b?:m50;&04`<41o1e?=j53:9j72d=83.8<h4<9g9m75b=<21b?:o50;&04`<41o1e?=j55:9j72?=83.8<h4<9g9m75b=>21b?:650;&04`<41o1e?=j57:9j721=83.8<h4<9g9m75b=021b?:850;&04`<41o1e?=j59:9j723=83.8<h4<9g9m75b=i21b?::50;&04`<41o1e?=j5b:9j724=83.8<h4<9g9m75b=k21b?:?50;&04`<41o1e?=j5d:9j726=83.8<h4<9g9m75b=m21b?;h50;&04`<41o1e?=j5f:9j73c=83.8<h4<9g9m75b=9910e>8k:18'75c=;0l0b>>k:038?l51k3:1(>>j:2;e?k57l3;976g<6c83>!57m392j6`<0e827>=n;?k1<7*<0d80=c=i;9n1=954i24:>5<#;9o1?4h4n22g>43<3`93:7>5$22f>6?a3g9;h7?9;:k0<0<72-9;i7=6f:l04a<6?21b?5:50;&04`<41o1e?=j51998m6>4290/?=k538d8j66c28307d=72;29 66b2:3m7c=?d;3b?>o4080;6)=?e;1:b>h48m0:n65f36g94?"48l085k5a31f95f=<a:=86=4+31g97<`<f::o6<j4;h15<?6=,::n6>7i;o13`?7b32c8::4?:%13a?5>n2d8<i4>f:9j7f>=83.8<h4;479m75b=821b?n950;&04`<3<?1e?=j51:9j7f0=83.8<h4;479m75b=:21b?n;50;&04`<3<?1e?=j53:9j7f2=83.8<h4;479m75b=<21b?n=50;&04`<3<?1e?=j55:9j7f4=83.8<h4;479m75b=>21b?n?50;&04`<3<?1e?=j57:9j7g`=83.8<h4;479m75b=021b?ok50;&04`<3<?1e?=j59:9j7gb=83.8<h4;479m75b=i21b?om50;&04`<3<?1e?=j5b:9j7gd=83.8<h4;479m75b=k21b?oo50;&04`<3<?1e?=j5d:9j7g?=83.8<h4;479m75b=m21b?o650;&04`<3<?1e?=j5f:9j7g1=83.8<h4;479m75b=9910e>l9:18'75c=<=<0b>>k:038?l5e<3:1(>>j:565?k57l3;976g<b283>!57m3>?:6`<0e827>=n;k81<7*<0d8703=i;9n1=954i2`2>5<#;9o18984n22g>43<3`9i<7>5$22f>1213g9;h7?9;:k0ec<72-9;i7:;6:l04a<6?21b?lk50;&04`<3<?1e?=j51998m6gc290/?=k54548j66c28307d=nc;29 66b2=>=7c=?d;3b?>o4ik0;6)=?e;672>h48m0:n65f43594?"48l0?8;5a31f95f=<a=8=6=4+31g9010<f::o6<j4;h611?6=,::n69:9;o13`?7b32c?>94?:%13a?23>2d8<i4>f:9j075=83.8<h4;479m75b=:910e9<=:18'75c=<=<0b>>k:338?l2593:1(>>j:565?k57l38976g;2183>!57m3>?:6`<0e817>=n<8l1<7*<0d8703=i;9n1>954i53f>5<#;9o18984n22g>73<3`>:o7>5$22f>1213g9;h7<9;:k75g<72-9;i7:;6:l04a<5?21b8<o50;&04`<3<?1e?=j52998m17>290/?=k54548j66c2;307d:>8;29 66b2=>=7c=?d;0b?>o39>0;6)=?e;672>h48m09n65f40494?"48l0?8;5a31f96f=<a=;>6=4+31g9010<f::o6?j4;h620?6=,::n69:9;o13`?4b32c?=>4?:%13a?23>2d8<i4=f:9j047=83.8<h4;479m75b=;910e9??:18'75c=<=<0b>>k:238?l27n3:1(>>j:565?k57l39976g;0d83>!57m3>?:6`<0e807>=n<9n1<7*<0d8703=i;9n1?954i52`>5<#;9o18984n22g>63<3`>;n7>5$22f>1213g9;h7=9;:k74d<72-9;i7:;6:l04a<4?21b8=750;&04`<3<?1e?=j53998m16?290/?=k54548j66c2:307d:?6;29 66b2=>=7c=?d;1b?>o38<0;6)=?e;672>h48m08n65f41694?"48l0?8;5a31f97f=<a=:86=4+31g9010<f::o6>j4;h636?6=,::n69:9;o13`?5b32c?<<4?:%13a?23>2d8<i4<f:9j056=83.8<h4;479m75b=<910e>hi:18'75c=<=<0b>>k:538?l5am3:1(>>j:565?k57l3>976g<fe83>!57m3>?:6`<0e877>=n;oh1<7*<0d8703=i;9n18954i2db>5<#;9o18984n22g>13<3`9m57>5$22f>1213g9;h7:9;:k0b=<72-9;i7:;6:l04a<3?21b?k950;&04`<3<?1e?=j54998m6`1290/?=k54548j66c2=307d=i5;29 66b2=>=7c=?d;6b?>o4n=0;6)=?e;672>h48m0?n65f3g194?"48l0?8;5a31f90f=<a:l96=4+31g9010<f::o69j4;h1e4?6=,::n69:9;o13`?2b32c8ik4?:%13a?23>2d8<i4;f:9j7`c=83.8<h4;479m75b==910e>kk:18'75c=<=<0b>>k:438?l5bk3:1(>>j:565?k57l3?976g<ec83>!57m3>?:6`<0e867>=n;lk1<7*<0d8703=i;9n19954i2g:>5<#;9o18984n22g>03<3`9n47>5$22f>1213g9;h7;9;:k0a2<72-9;i7:;6:l04a<2?21b?h;50;&04`<3<?1e?=j55998m6c3290/?=k54548j66c2<307d=j3;29 66b2=>=7c=?d;7b?>o4m;0;6)=?e;672>h48m0>n65f3d394?"48l0?8;5a31f91f=<a:o;6=4+31g9010<f::o68j4;h1gb?6=,::n69:9;o13`?3b32c8hh4?:%13a?23>2d8<i4:f:9j7ab=83.8<h4;479m75b=>910e>jl:18'75c=<=<0b>>k:738?l5ci3:1(>>j:565?k57l3<976g<d883>!57m3>?:6`<0e857>=n;m21<7*<0d8703=i;9n1:954i2f4>5<#;9o18984n22g>33<3`9o:7>5$22f>1213g9;h789;:k0`0<72-9;i7:;6:l04a<1?21b?i:50;&04`<3<?1e?=j56998m6b4290/?=k54548j66c2?307d=k2;29 66b2=>=7c=?d;4b?>o4l80;6)=?e;672>h48m0=n65f3bd94?"48l0?8;5a31f92f=<a:in6=4+31g9010<f::o6;j4;h1``?6=,::n69:9;o13`?0b32c8on4?:%13a?23>2d8<i49f:9j7fd=83.8<h4;479m75b=?910e>mn:18'75c=<=<0b>>k:638?l5d13:1(>>j:565?k57l3=976g<c183>!57m3>?:6`<0e847>=n;k?1<7*<0d8703=i;9n1;954i2cb>5<#;9o18984n22g>23<3`>:h7>5$22f>1213g9;h799;:k757<72-9;i7:;6:l04a<0?21b8=950;&04`<3<?1e?=j57998m6`d290/?=k54548j66c2>307d=i1;29 66b2=>=7c=?d;5b?>o4m?0;6)=?e;672>h48m0<n65f3e`94?"48l0?8;5a31f93f=<a:n;6=4+31g9010<f::o6:j4;h1b=?6=,::n69:9;o13`?1b32c8m54?:%13a?23>2d8<i48f:9j1``=831d?;850;9a705=83;1<7>t$204>4743A9>>6F<2e9l544=831vn><m:18247<729q/??9531d8L6353A99h6T92;33a<6<3o1=847:78:>2<6?3;=6<j51b824?7>28;1=l4rnd294>h68;0;7)?n2;08 4g42;1/=<:52:&250<53-;::7<4$034>7=#9821>6*>1881?!76i380(<?m:39'54e=:2.:=i4=;%32a?4<,8;m6?5+13296>"6:8097)==1;38 645281/=?:52:&260<53-;9:7<4$004>7=#9;21>6*>2881?!75i380(<<m:39'57e=:2.:>i4=;%31a?4<,88m6?5+12296>"6;8097)?<2;08 4542;1/=>:52:&270<53-;8:7<4$014>7=#9:21>6*>3881?!74i380(<=m:39'56e=:2.:?i4=;%30a?4<,89m6?5+15296>"6<8097)?;2;08 4242;1/=9:52:&200<53-;?:7<4$064>7=#9=21>6*>4881?!73i380(<:m:39'51e=:2.:8i4=;%37a?4<,8>m6?5+14296>"6=8097)?:2;08 4342;1/=8:52:&210<53-;>:7<4$074>7=#9<21>6*>5881?!72i380(<;m:39'50e=:2.:9i4=;%36a?4<,8?m6?5+17296>"6>8097)?92;08 4042;1/=;:52:&220<53-;=:7<4$044>7=#9?21>6*>6881?!71i380(<8m:39'53e=:2.::i4=;%35a?4<,8<m6?5+16296>"6?8097)?82;08 4142;1/=::52:&230<53-;<:7<4$054>7=#9>21>6*>7881?!70i380(<9m:39'52e=:2.:;i4=;%34a?4<,8=m6?5+19296>"608097)?72;08 4>42;1/=5:52:&2<0<53-;3:7<4$0:4>7=#9121>6*>8881?!7?i380(<6m:39'5=e=:2.:4i4=;%3;a?4<,82m6?5+18296>"618097)?62;08 4?42;1/=4:52:&2=0<53-;2:7<4$0;4>7=#9021>6*>9881?!7>i380(<7m:39'5<e=:2.:5i4=;%3:a?4<,83m6?5+1`296>"6i8097)=>d;325>"6:;097)?n6;13=>"49908<45+303975?<f:;9645a301961=#;8o1:=5+30d974e<,8k?6<5+1`795>"4<m088n5+35g971e<f:>m645a342961=#9;91>6g>0d83>>o68m0;66g>1183>>o68o0;66g<2583>>o4::0;66g<2783>>o4:<0;66g9d;29?l0d2900e;h50;9j2`<722c8=44?::k05=<722c8=o4?::k05d<722c8=84?::k051<722c8=:4?::k053<722c=?7>5;h47>5<<a??1<75f6783>>i1?3:17b87:188k3?=831d:l4?::k;g?6=,::n65l4n22g>5=<a1k1<7*<0d8;f>h48m0:76g78;29 66b21h0b>>k:398m=1=83.8<h47b:l04a<432c3:7>5$22f>=d<f::o6954i9794?"48l03n6`<0e86?>o?<3:1(>>j:9`8j66c2?10e5=50;&04`<?j2d8<i48;:k;6?6=,::n65l4n22g>==<a1;1<7*<0d8;f>h48m0276g70;29 66b21h0b>>k:`98m2`=83.8<h47b:l04a<e32c<h7>5$22f>=d<f::o6n54i6a94?"48l03n6`<0e8g?>o0j3:1(>>j:9`8j66c2l10e:o50;&04`<?j2d8<i4i;:k4=?6=,::n65l4n22g>46<3`=36=4+31g9<g=i;9n1=<54i6594?"48l03n6`<0e826>=n??0;6)=?e;:a?k57l3;876g85;29 66b21h0b>>k:068?l13290/?=k58c9m75b=9<10e4=50;&04`<?j2d8<i4>6:9j=7<72-9;i76m;o13`?7032c2=7>5$22f>=d<f::o6<64;h;3>5<#;9o14o5a31f95<=<a1l1<7*<0d8;f>h48m0:m65f8d83>!57m32i7c=?d;3a?>o?l3:1(>>j:9`8j66c28i07d66:18'75c=0k1e?=j51e98m2c=83.8<h47b:l04a<6m21b;>4?:%13a?>e3g9;h7?i;:ka=?6=,::n6o64n22g>5=<ak=1<7*<0d8a<>h48m0:76gm6;29 66b2k20b>>k:398mg3=83.8<h4m8:l04a<432cjh7>5$22f>de<f::o6=54i``94?"48l0jo6`<0e82?>of13:1(>>j:`a8j66c2;10el650;&04`<fk2d8<i4<;:kb3?6=,::n6lm4n22g>1=<ah<1<7*<0d8bg>h48m0>76gn5;29 66b2hi0b>>k:798md2=83.8<h4nc:l04a<032cj?7>5$22f>de<f::o6554i`094?"48l0jo6`<0e8:?>of93:1(>>j:`a8j66c2h10el>50;&04`<fk2d8<i4m;:k:a?6=,::n6lm4n22g>f=<a0n1<7*<0d8bg>h48m0o76g6c;29 66b2hi0b>>k:d98m<d=83.8<h4nc:l04a<a32c2m7>5$22f>de<f::o6<>4;h;:>5<#;9o1mn5a31f954=<a021<7*<0d8bg>h48m0:>65f9683>!57m3kh7c=?d;30?>o>>3:1(>>j:`a8j66c28>07d7::18'75c=ij1e?=j51498mg2=83.8<h4nc:l04a<6>21bn>4?:%13a?gd3g9;h7?8;:ka6?6=,::n6lm4n22g>4><3`h:6=4+31g9ef=i;9n1=454ic294?"48l0jo6`<0e82e>=nio0;6)=?e;c`?k57l3;i76gne;29 66b2hi0b>>k:0a8?lgf290/?=k5ab9m75b=9m10e4h50;&04`<fk2d8<i4>e:9j=1<72-9;i7ol;o13`?7a32cii7>5$22f>gb<f::o6=54ica94?"48l0ih6`<0e82?>oej3:1(>>j:cf8j66c2;10eoo50;&04`<el2d8<i4<;:k11?6=,::n6?:4n22g>5=<a;91<7*<0d810>h48m0:76g=2;29 66b2;>0b>>k:398m77=83.8<h4=4:l04a<432c9<7>5$22f>72<f::o6954i0d94?"48l0986`<0e86?>o5m3:1(>>j:368j66c2?10e?j50;&04`<5<2d8<i48;:k1g?6=,::n6?:4n22g>==<a;h1<7*<0d810>h48m0276g=a;29 66b2;>0b>>k:`98m7?=83.8<h4=4:l04a<e32c947>5$22f>72<f::o6n54i3594?"48l0986`<0e8g?>o5>3:1(>>j:368j66c2l10e<k50;&04`<5<2d8<i4i;:k01?6=,::n6>:4n22g>5=<a:91<7*<0d800>h48m0:76g<2;29 66b2:>0b>>k:398m67=83.8<h4<4:l04a<432c8<7>5$22f>62<f::o6954i2g94?"48l0886`<0e86?>o4l3:1(>>j:268j66c2?10e>m50;&04`<4<2d8<i48;:k0f?6=,::n6>:4n22g>==<a:k1<7*<0d800>h48m0276g<9;29 66b2:>0b>>k:`98m6>=83.8<h4<4:l04a<e32c8;7>5$22f>62<f::o6n54i2494?"48l0886`<0e8g?>o5n3:1(>>j:268j66c2l10e9850;&04`<3=2d8<i4?;:k70?6=,::n69;4n22g>4=<a=91<7*<0d871>h48m0976g;2;29 66b2=?0b>>k:298m17=83.8<h4;5:l04a<332c?<7>5$22f>13<f::o6854i5d94?"48l0?96`<0e85?>o3m3:1(>>j:578j66c2>10e9j50;&04`<3=2d8<i47;:k7g?6=,::n69;4n22g><=<a=h1<7*<0d871>h48m0j76g;a;29 66b2=?0b>>k:c98m1?=83.8<h4;5:l04a<d32c?47>5$22f>13<f::o6i54i5594?"48l0?96`<0e8f?>o4n3:1(>>j:578j66c2o10e8850;&04`<2=2d8<i4?;:k60?6=,::n68;4n22g>4=<a<91<7*<0d861>h48m0976g:2;29 66b2<?0b>>k:298m07=83.8<h4:5:l04a<332c>j7>5$22f>03<f::o6854i4g94?"48l0>96`<0e85?>o2l3:1(>>j:478j66c2>10e8m50;&04`<2=2d8<i47;:k6f?6=,::n68;4n22g><=<a<k1<7*<0d861>h48m0j76g:9;29 66b2<?0b>>k:c98m0>=83.8<h4:5:l04a<d32c>;7>5$22f>03<f::o6i54i4294?"48l0>96`<0e8f?>o4;00;6)=?e;10<>h48m0;76g<3683>!57m39846`<0e82?>o4;?0;6)=?e;10<>h48m0976g<3483>!57m39846`<0e80?>o4;=0;6)=?e;107>h48m0;76g<3383>!57m398?6`<0e82?>o4;80;6)=?e;107>h48m0976g<3183>!57m398?6`<0e80?>o4<k0;6)=?e;17e>h48m0;76g<4883>!57m39?m6`<0e82?>o4<10;6)=?e;17e>h48m0976g<4683>!57m39?m6`<0e80?>o4<?0;6)=?e;17e>h48m0?76g<4483>!57m39?m6`<0e86?>o4<=0;6)=?e;17e>h48m0=76g<4283>!57m39?m6`<0e84?>o4<;0;6)=?e;175>h48m0;76g<4183>!57m39?=6`<0e82?>o4;o0;6)=?e;175>h48m0976g<3d83>!57m39?=6`<0e80?>o4;m0;6)=?e;175>h48m0?76g<3b83>!57m39?=6`<0e86?>o4;k0;6)=?e;175>h48m0=76g<3`83>!57m39?=6`<0e84?>ic03:1(>>j:e58j66c2910ci850;&04`<c?2d8<i4>;:mg0?6=,::n6i94n22g>7=<gm91<7*<0d8g3>h48m0876ak2;29 66b2m=0b>>k:598ka7=83.8<h4k7:l04a<232eo<7>5$22f>a1<f::o6;54obd94?"48l0o;6`<0e84?>idm3:1(>>j:e58j66c2110cnj50;&04`<c?2d8<i46;:m`g?6=,::n6i94n22g>d=<gjh1<7*<0d8g3>h48m0i76al9;29 66b2m=0b>>k:b98kf>=83.8<h4k7:l04a<c32eh;7>5$22f>a1<f::o6h54ob494?"48l0o;6`<0e8e?>id=3:1(>>j:e58j66c28:07bm;:18'75c=l>1e?=j51098kf5=83.8<h4k7:l04a<6:21do?4?:%13a?b03g9;h7?<;:m`5?6=,::n6i94n22g>42<3fi;6=4+31g9`2=i;9n1=854oed94?"48l0o;6`<0e822>=hll0;6)=?e;f4?k57l3;<76akd;29 66b2m=0b>>k:0:8?jbd290/?=k5d69m75b=9010cil50;&04`<c?2d8<i4>a:9l`d<72-9;i7j8;o13`?7e32eo57>5$22f>a1<f::o6<m4;nf6>5<#;9o1h:5a31f95a=<gjk1<7*<0d8g3>h48m0:i65`bg83>!57m3n<7c=?d;3e?>i68>0;6)=?e;332>h48m0;76a>0483>!57m3;;:6`<0e82?>i68=0;6)=?e;332>h48m0976a>0283>!57m3;;:6`<0e80?>iai3:1(>>j:g;8j66c2910ck650;&04`<a12d8<i4>;:me2?6=,::n6k74n22g>7=<go?1<7*<0d8e=>h48m0876ai4;29 66b2o30b>>k:598kc5=83.8<h4i9:l04a<232em>7>5$22f>c?<f::o6;54og394?"48l0m56`<0e84?>ia83:1(>>j:g;8j66c2110chh50;&04`<a12d8<i46;:mfa?6=,::n6k74n22g>d=<gln1<7*<0d8e=>h48m0i76ajb;29 66b2o30b>>k:b98k`g=83.8<h4i9:l04a<c32en57>5$22f>c?<f::o6h54od:94?"48l0m56`<0e8e?>ib?3:1(>>j:g;8j66c28:07bk9:18'75c=n01e?=j51098k`3=83.8<h4i9:l04a<6:21di94?:%13a?`>3g9;h7?<;:mf7?6=,::n6k74n22g>42<3fo96=4+31g9b<=i;9n1=854o022>5<#;9o1j45a31f953=<g8:;6=4+31g9b<=i;9n1=:54ogd94?"48l0m56`<0e82<>=hnl0;6)=?e;d:?k57l3;276aid;29 66b2o30b>>k:0c8?j`d290/?=k5f89m75b=9k10ckl50;&04`<a12d8<i4>c:9lb2<72-9;i7h6;o13`?7c32eno7>5$22f>c?<f::o6<k4;ng2>5<#;9o1j45a31f95c=<g8:h6=4+31g955d<f::o6=54o02b>5<#;9o1==l4n22g>4=<g8:26=4+31g955d<f::o6?54o02;>5<#;9o1==l4n22g>6=<uk99m7>511094?6|,:8<6>>i;I166>N4:m1Q:?4>0zf951<b28?147859;5952<6>3;o6<m51182=?7628k1qck?:19m554=82.:m?4=;%3b7?4<,8;?6?5+10796>"69?097)?>7;08 47?2;1/=<752:&25d<53-;:n7<4$03`>7=#98n1>6*>1d81?!76n380(<<?:39'577=:2.8><4>;%116?7<,88?6?5+13796>"6:?097)?=7;08 44?2;1/=?752:&26d<53-;9n7<4$00`>7=#9;n1>6*>2d81?!75n380(<=?:39'567=:2.:??4=;%307?4<,89?6?5+12796>"6;?097)?<7;08 45?2;1/=>752:&27d<53-;8n7<4$01`>7=#9:n1>6*>3d81?!74n380(<:?:39'517=:2.:8?4=;%377?4<,8>?6?5+15796>"6<?097)?;7;08 42?2;1/=9752:&20d<53-;?n7<4$06`>7=#9=n1>6*>4d81?!73n380(<;?:39'507=:2.:9?4=;%367?4<,8??6?5+14796>"6=?097)?:7;08 43?2;1/=8752:&21d<53-;>n7<4$07`>7=#9<n1>6*>5d81?!72n380(<8?:39'537=:2.::?4=;%357?4<,8<?6?5+17796>"6>?097)?97;08 40?2;1/=;752:&22d<53-;=n7<4$04`>7=#9?n1>6*>6d81?!71n380(<9?:39'527=:2.:;?4=;%347?4<,8=?6?5+16796>"6??097)?87;08 41?2;1/=:752:&23d<53-;<n7<4$05`>7=#9>n1>6*>7d81?!70n380(<6?:39'5=7=:2.:4?4=;%3;7?4<,82?6?5+19796>"60?097)?77;08 4>?2;1/=5752:&2<d<53-;3n7<4$0:`>7=#91n1>6*>8d81?!7?n380(<7?:39'5<7=:2.:5?4=;%3:7?4<,83?6?5+18796>"61?097)?67;08 4??2;1/=4752:&2=d<53-;2n7<4$0;`>7=#90n1>6*>9d81?!7>n380(<o?:39'5d7=:2.8=i4>109'574=:2.:m;4<089'746=;930(>?>:22:?k56:330b>?<:368 67b2?:0(>?i:23`?!7f<3;0(<o::09'71b=;=i0(>:j:26`?k53n330b>;?:368 4442;1b==k50;9j55b=831b=<>50;9j55`=831b??:50;9j775=831b??850;9j773=831b:i4?::k5g?6=3`<m6=44i7g94?=n;831<75f30:94?=n;8h1<75f30c94?=n;8?1<75f30694?=n;8=1<75f30494?=n>:0;66g94;29?l022900e;850;9l22<722e=47>5;n4:>5<<g?k1<75f8b83>!57m32i7c=?d;28?l>f290/?=k58c9m75b=921b454?:%13a?>e3g9;h7<4;h:4>5<#;9o14o5a31f97>=n0?0;6)=?e;:a?k57l3>07d6::18'75c=0k1e?=j55:9j<1<72-9;i76m;o13`?0<3`286=4+31g9<g=i;9n1;65f8383>!57m32i7c=?d;:8?l>6290/?=k58c9m75b=121b4=4?:%13a?>e3g9;h7o4;h5e>5<#;9o14o5a31f9f>=n?m0;6)=?e;:a?k57l3i07d9l:18'75c=0k1e?=j5d:9j3g<72-9;i76m;o13`?c<3`=j6=4+31g9<g=i;9n1j65f7883>!57m32i7c=?d;33?>o003:1(>>j:9`8j66c28;07d98:18'75c=0k1e?=j51398m20=83.8<h47b:l04a<6;21b;84?:%13a?>e3g9;h7?;;:k40?6=,::n65l4n22g>43<3`386=4+31g9<g=i;9n1=;54i8094?"48l03n6`<0e823>=n180;6)=?e;:a?k57l3;376g60;29 66b21h0b>>k:0;8?l>a290/?=k58c9m75b=9h10e5k50;&04`<?j2d8<i4>b:9j<a<72-9;i76m;o13`?7d32c357>5$22f>=d<f::o6<j4;h5f>5<#;9o14o5a31f95`=<a>91<7*<0d8;f>h48m0:j65fb883>!57m3h37c=?d;28?ld0290/?=k5b99m75b=921bn;4?:%13a?d?3g9;h7<4;h`6>5<#;9o1n55a31f97>=nim0;6)=?e;c`?k57l3:07dom:18'75c=ij1e?=j51:9je<<72-9;i7ol;o13`?4<3`k36=4+31g9ef=i;9n1?65fa683>!57m3kh7c=?d;68?lg1290/?=k5ab9m75b==21bm84?:%13a?gd3g9;h784;hc7>5<#;9o1mn5a31f93>=ni:0;6)=?e;c`?k57l3207do=:18'75c=ij1e?=j59:9je4<72-9;i7ol;o13`?g<3`k;6=4+31g9ef=i;9n1n65f9d83>!57m3kh7c=?d;a8?l?c290/?=k5ab9m75b=l21b5n4?:%13a?gd3g9;h7k4;h;a>5<#;9o1mn5a31f9b>=n1h0;6)=?e;c`?k57l3;;76g69;29 66b2hi0b>>k:038?l??290/?=k5ab9m75b=9;10e4950;&04`<fk2d8<i4>3:9j=3<72-9;i7ol;o13`?7332c297>5$22f>de<f::o6<;4;h`7>5<#;9o1mn5a31f953=<ak91<7*<0d8bg>h48m0:;65fb383>!57m3kh7c=?d;3;?>oe93:1(>>j:`a8j66c28307dl?:18'75c=ij1e?=j51`98md`=83.8<h4nc:l04a<6j21bmh4?:%13a?gd3g9;h7?l;:kbe?6=,::n6lm4n22g>4b<3`3m6=4+31g9ef=i;9n1=h54i8694?"48l0jo6`<0e82b>=njl0;6)=?e;`g?k57l3:07dll:18'75c=jm1e?=j51:9jfg<72-9;i7lk;o13`?4<3`hj6=4+31g9fa=i;9n1?65f2483>!57m38?7c=?d;28?l44290/?=k5259m75b=921b>?4?:%13a?433g9;h7<4;h02>5<#;9o1>95a31f97>=n:90;6)=?e;07?k57l3>07d?i:18'75c=:=1e?=j55:9j6`<72-9;i7<;;o13`?0<3`8o6=4+31g961=i;9n1;65f2b83>!57m38?7c=?d;:8?l4e290/?=k5259m75b=121b>l4?:%13a?433g9;h7o4;h0:>5<#;9o1>95a31f9f>=n:10;6)=?e;07?k57l3i07d<8:18'75c=:=1e?=j5d:9j63<72-9;i7<;;o13`?c<3`;n6=4+31g961=i;9n1j65f3483>!57m39?7c=?d;28?l54290/?=k5359m75b=921b??4?:%13a?533g9;h7<4;h12>5<#;9o1?95a31f97>=n;90;6)=?e;17?k57l3>07d=j:18'75c=;=1e?=j55:9j7a<72-9;i7=;;o13`?0<3`9h6=4+31g971=i;9n1;65f3c83>!57m39?7c=?d;:8?l5f290/?=k5359m75b=121b?44?:%13a?533g9;h7o4;h1;>5<#;9o1?95a31f9f>=n;>0;6)=?e;17?k57l3i07d=9:18'75c=;=1e?=j5d:9j6c<72-9;i7=;;o13`?c<3`>=6=4+31g900=i;9n1<65f4583>!57m3>>7c=?d;38?l24290/?=k5449m75b=:21b8?4?:%13a?223g9;h7=4;h62>5<#;9o1885a31f90>=n<90;6)=?e;66?k57l3?07d:i:18'75c=<<1e?=j56:9j0`<72-9;i7::;o13`?1<3`>o6=4+31g900=i;9n1465f4b83>!57m3>>7c=?d;;8?l2e290/?=k5449m75b=i21b8l4?:%13a?223g9;h7l4;h6:>5<#;9o1885a31f9g>=n<10;6)=?e;66?k57l3n07d:8:18'75c=<<1e?=j5e:9j7c<72-9;i7::;o13`?`<3`?=6=4+31g910=i;9n1<65f5583>!57m3?>7c=?d;38?l34290/?=k5549m75b=:21b9?4?:%13a?323g9;h7=4;h72>5<#;9o1985a31f90>=n=o0;6)=?e;76?k57l3?07d;j:18'75c==<1e?=j56:9j1a<72-9;i7;:;o13`?1<3`?h6=4+31g910=i;9n1465f5c83>!57m3?>7c=?d;;8?l3f290/?=k5549m75b=i21b944?:%13a?323g9;h7l4;h7;>5<#;9o1985a31f9g>=n=>0;6)=?e;76?k57l3n07d;?:18'75c==<1e?=j5e:9j76?=83.8<h4<399m75b=821b?>950;&04`<4;11e?=j51:9j760=83.8<h4<399m75b=:21b?>;50;&04`<4;11e?=j53:9j762=83.8<h4<329m75b=821b?><50;&04`<4;:1e?=j51:9j767=83.8<h4<329m75b=:21b?>>50;&04`<4;:1e?=j53:9j71d=83.8<h4<4`9m75b=821b?9750;&04`<4<h1e?=j51:9j71>=83.8<h4<4`9m75b=:21b?9950;&04`<4<h1e?=j53:9j710=83.8<h4<4`9m75b=<21b?9;50;&04`<4<h1e?=j55:9j712=83.8<h4<4`9m75b=>21b?9=50;&04`<4<h1e?=j57:9j714=83.8<h4<409m75b=821b?9>50;&04`<4<81e?=j51:9j76`=83.8<h4<409m75b=:21b?>k50;&04`<4<81e?=j53:9j76b=83.8<h4<409m75b=<21b?>m50;&04`<4<81e?=j55:9j76d=83.8<h4<409m75b=>21b?>o50;&04`<4<81e?=j57:9l`=<72-9;i7j8;o13`?6<3fn=6=4+31g9`2=i;9n1=65`d583>!57m3n<7c=?d;08?jb4290/?=k5d69m75b=;21dh?4?:%13a?b03g9;h7:4;nf2>5<#;9o1h:5a31f91>=hl90;6)=?e;f4?k57l3<07bmi:18'75c=l>1e?=j57:9lg`<72-9;i7j8;o13`?><3fio6=4+31g9`2=i;9n1565`cb83>!57m3n<7c=?d;c8?jee290/?=k5d69m75b=j21do44?:%13a?b03g9;h7m4;na;>5<#;9o1h:5a31f9`>=hk>0;6)=?e;f4?k57l3o07bm9:18'75c=l>1e?=j5f:9lg0<72-9;i7j8;o13`?7732eh87>5$22f>a1<f::o6<?4;na0>5<#;9o1h:5a31f957=<gj81<7*<0d8g3>h48m0:?65`c083>!57m3n<7c=?d;37?>id83:1(>>j:e58j66c28?07bji:18'75c=l>1e?=j51798kac=83.8<h4k7:l04a<6?21dhi4?:%13a?b03g9;h7?7;:mgg?6=,::n6i94n22g>4?<3fni6=4+31g9`2=i;9n1=l54oec94?"48l0o;6`<0e82f>=hl00;6)=?e;f4?k57l3;h76ak5;29 66b2m=0b>>k:0f8?jef290/?=k5d69m75b=9l10coh50;&04`<c?2d8<i4>f:9l551=83.8<h4>079m75b=821d==;50;&04`<68?1e?=j51:9l552=83.8<h4>079m75b=:21d===50;&04`<68?1e?=j53:9lbd<72-9;i7h6;o13`?6<3fl36=4+31g9b<=i;9n1=65`f783>!57m3l27c=?d;08?j`2290/?=k5f89m75b=;21dj94?:%13a?`>3g9;h7:4;nd0>5<#;9o1j45a31f91>=hn;0;6)=?e;d:?k57l3<07bh>:18'75c=n01e?=j57:9lb5<72-9;i7h6;o13`?><3fom6=4+31g9b<=i;9n1565`ed83>!57m3l27c=?d;c8?jcc290/?=k5f89m75b=j21dio4?:%13a?`>3g9;h7m4;ngb>5<#;9o1j45a31f9`>=hm00;6)=?e;d:?k57l3o07bk7:18'75c=n01e?=j5f:9la2<72-9;i7h6;o13`?7732en:7>5$22f>c?<f::o6<?4;ng6>5<#;9o1j45a31f957=<gl>1<7*<0d8e=>h48m0:?65`e283>!57m3l27c=?d;37?>ib:3:1(>>j:g;8j66c28?07b??1;29 66b2o30b>>k:048?j7783:1(>>j:g;8j66c28=07bhi:18'75c=n01e?=j51998kcc=83.8<h4i9:l04a<6121dji4?:%13a?`>3g9;h7?n;:meg?6=,::n6k74n22g>4d<3fli6=4+31g9b<=i;9n1=n54og594?"48l0m56`<0e82`>=hmj0;6)=?e;d:?k57l3;n76aj1;29 66b2o30b>>k:0d8?j77k3:1(>>j:02a?k57l3:07b??a;29 66b28:i7c=?d;38?j7713:1(>>j:02a?k57l3807b??8;29 66b28:i7c=?d;18?xd4:00;6<>=:183!55?39;j6F<539K77b<R?81==uk:069a?72210=6448:05953<6l3;h6<>518825?7f2tdn<7>4n021>5=#9h81>6*>a281?!76<380(<?::39'540=:2.:=:4=;%32<?4<,8;26?5+10c96>"69k097)?>c;08 47c2;1/=<k52:&25c<53-;9<7<4$002>7=#;;;1=6*<2382?!75<380(<<::39'570=:2.:>:4=;%31<?4<,8826?5+13c96>"6:k097)?=c;08 44c2;1/=?k52:&26c<53-;8<7<4$012>7=#9:81>6*>3281?!74<380(<=::39'560=:2.:?:4=;%30<?4<,8926?5+12c96>"6;k097)?<c;08 45c2;1/=>k52:&27c<53-;?<7<4$062>7=#9=81>6*>4281?!73<380(<:::39'510=:2.:8:4=;%37<?4<,8>26?5+15c96>"6<k097)?;c;08 42c2;1/=9k52:&20c<53-;><7<4$072>7=#9<81>6*>5281?!72<380(<;::39'500=:2.:9:4=;%36<?4<,8?26?5+14c96>"6=k097)?:c;08 43c2;1/=8k52:&21c<53-;=<7<4$042>7=#9?81>6*>6281?!71<380(<8::39'530=:2.:::4=;%35<?4<,8<26?5+17c96>"6>k097)?9c;08 40c2;1/=;k52:&22c<53-;<<7<4$052>7=#9>81>6*>7281?!70<380(<9::39'520=:2.:;:4=;%34<?4<,8=26?5+16c96>"6?k097)?8c;08 41c2;1/=:k52:&23c<53-;3<7<4$0:2>7=#9181>6*>8281?!7?<380(<6::39'5=0=:2.:4:4=;%3;<?4<,8226?5+19c96>"60k097)?7c;08 4>c2;1/=5k52:&2<c<53-;2<7<4$0;2>7=#9081>6*>9281?!7><380(<7::39'5<0=:2.:5:4=;%3:<?4<,8326?5+18c96>"61k097)?6c;08 4?c2;1/=4k52:&2=c<53-;j<7<4$0c2>7=#;8n1=<?4$001>7=#9h<1?=74$233>66>3-9:=7=?9:l057<>3g9:?7<;;%12a?073-9:j7=>c:&2e1<63-;j97?4$26g>62d3-9?i7=;c:l00c<>3g9><7<;;%317?4<a8:n6=44i02g>5<<a8;;6=44i02e>5<<a:8?6=44i200>5<<a:8=6=44i206>5<<a?n1<75f6b83>>o1n3:17d8j:188m67>2900e>?7:188m67e2900e>?n:188m6722900e>?;:188m6702900e>?9:188m35=831b:94?::k51?6=3`<=6=44o7594?=h>10;66a99;29?j0f2900e5m50;&04`<?j2d8<i4?;:k;e?6=,::n65l4n22g>4=<a121<7*<0d8;f>h48m0976g77;29 66b21h0b>>k:298m=0=83.8<h47b:l04a<332c397>5$22f>=d<f::o6854i9694?"48l03n6`<0e85?>o?;3:1(>>j:9`8j66c2>10e5<50;&04`<?j2d8<i47;:k;5?6=,::n65l4n22g><=<a1:1<7*<0d8;f>h48m0j76g8f;29 66b21h0b>>k:c98m2b=83.8<h47b:l04a<d32c<o7>5$22f>=d<f::o6i54i6`94?"48l03n6`<0e8f?>o0i3:1(>>j:9`8j66c2o10e:750;&04`<?j2d8<i4>0:9j3=<72-9;i76m;o13`?7632c<;7>5$22f>=d<f::o6<<4;h55>5<#;9o14o5a31f956=<a>?1<7*<0d8;f>h48m0:865f7583>!57m32i7c=?d;36?>o>;3:1(>>j:9`8j66c28<07d7=:18'75c=0k1e?=j51698m<7=83.8<h47b:l04a<6021b5=4?:%13a?>e3g9;h7?6;:k;b?6=,::n65l4n22g>4g<3`2n6=4+31g9<g=i;9n1=o54i9f94?"48l03n6`<0e82g>=n000;6)=?e;:a?k57l3;o76g8e;29 66b21h0b>>k:0g8?l14290/?=k58c9m75b=9o10eo750;&04`<e02d8<i4?;:ka3?6=,::n6o64n22g>4=<ak<1<7*<0d8a<>h48m0976gm5;29 66b2k20b>>k:298mdb=83.8<h4nc:l04a<732cjn7>5$22f>de<f::o6<54i`;94?"48l0jo6`<0e81?>of03:1(>>j:`a8j66c2:10el950;&04`<fk2d8<i4;;:kb2?6=,::n6lm4n22g>0=<ah?1<7*<0d8bg>h48m0=76gn4;29 66b2hi0b>>k:698md5=83.8<h4nc:l04a<?32cj>7>5$22f>de<f::o6454i`394?"48l0jo6`<0e8b?>of83:1(>>j:`a8j66c2k10e4k50;&04`<fk2d8<i4l;:k:`?6=,::n6lm4n22g>a=<a0i1<7*<0d8bg>h48m0n76g6b;29 66b2hi0b>>k:g98m<g=83.8<h4nc:l04a<6821b544?:%13a?gd3g9;h7?>;:k:<?6=,::n6lm4n22g>44<3`3<6=4+31g9ef=i;9n1=>54i8494?"48l0jo6`<0e820>=n1<0;6)=?e;c`?k57l3;>76gm4;29 66b2hi0b>>k:048?ld4290/?=k5ab9m75b=9>10eo<50;&04`<fk2d8<i4>8:9jf4<72-9;i7ol;o13`?7>32ci<7>5$22f>de<f::o6<o4;hce>5<#;9o1mn5a31f95g=<aho1<7*<0d8bg>h48m0:o65fa`83>!57m3kh7c=?d;3g?>o>n3:1(>>j:`a8j66c28o07d7;:18'75c=ij1e?=j51g98mgc=83.8<h4md:l04a<732cio7>5$22f>gb<f::o6<54ic`94?"48l0ih6`<0e81?>oei3:1(>>j:cf8j66c2:10e?;50;&04`<5<2d8<i4?;:k17?6=,::n6?:4n22g>4=<a;81<7*<0d810>h48m0976g=1;29 66b2;>0b>>k:298m76=83.8<h4=4:l04a<332c:j7>5$22f>72<f::o6854i3g94?"48l0986`<0e85?>o5l3:1(>>j:368j66c2>10e?m50;&04`<5<2d8<i47;:k1f?6=,::n6?:4n22g><=<a;k1<7*<0d810>h48m0j76g=9;29 66b2;>0b>>k:c98m7>=83.8<h4=4:l04a<d32c9;7>5$22f>72<f::o6i54i3494?"48l0986`<0e8f?>o6m3:1(>>j:368j66c2o10e>;50;&04`<4<2d8<i4?;:k07?6=,::n6>:4n22g>4=<a:81<7*<0d800>h48m0976g<1;29 66b2:>0b>>k:298m66=83.8<h4<4:l04a<332c8i7>5$22f>62<f::o6854i2f94?"48l0886`<0e85?>o4k3:1(>>j:268j66c2>10e>l50;&04`<4<2d8<i47;:k0e?6=,::n6>:4n22g><=<a:31<7*<0d800>h48m0j76g<8;29 66b2:>0b>>k:c98m61=83.8<h4<4:l04a<d32c8:7>5$22f>62<f::o6i54i3d94?"48l0886`<0e8f?>o3>3:1(>>j:578j66c2910e9:50;&04`<3=2d8<i4>;:k77?6=,::n69;4n22g>7=<a=81<7*<0d871>h48m0876g;1;29 66b2=?0b>>k:598m16=83.8<h4;5:l04a<232c?j7>5$22f>13<f::o6;54i5g94?"48l0?96`<0e84?>o3l3:1(>>j:578j66c2110e9m50;&04`<3=2d8<i46;:k7f?6=,::n69;4n22g>d=<a=k1<7*<0d871>h48m0i76g;9;29 66b2=?0b>>k:b98m1>=83.8<h4;5:l04a<c32c?;7>5$22f>13<f::o6h54i2d94?"48l0?96`<0e8e?>o2>3:1(>>j:478j66c2910e8:50;&04`<2=2d8<i4>;:k67?6=,::n68;4n22g>7=<a<81<7*<0d861>h48m0876g:1;29 66b2<?0b>>k:598m0`=83.8<h4:5:l04a<232c>i7>5$22f>03<f::o6;54i4f94?"48l0>96`<0e84?>o2k3:1(>>j:478j66c2110e8l50;&04`<2=2d8<i46;:k6e?6=,::n68;4n22g>d=<a<31<7*<0d861>h48m0i76g:8;29 66b2<?0b>>k:b98m01=83.8<h4:5:l04a<c32c><7>5$22f>03<f::o6h54i21:>5<#;9o1?>64n22g>5=<a:9<6=4+31g976><f::o6<54i215>5<#;9o1?>64n22g>7=<a:9>6=4+31g976><f::o6>54i217>5<#;9o1?>=4n22g>5=<a:996=4+31g9765<f::o6<54i212>5<#;9o1?>=4n22g>7=<a:9;6=4+31g9765<f::o6>54i26a>5<#;9o1?9o4n22g>5=<a:>26=4+31g971g<f::o6<54i26;>5<#;9o1?9o4n22g>7=<a:><6=4+31g971g<f::o6>54i265>5<#;9o1?9o4n22g>1=<a:>>6=4+31g971g<f::o6854i267>5<#;9o1?9o4n22g>3=<a:>86=4+31g971g<f::o6:54i261>5<#;9o1?9?4n22g>5=<a:>;6=4+31g9717<f::o6<54i21e>5<#;9o1?9?4n22g>7=<a:9n6=4+31g9717<f::o6>54i21g>5<#;9o1?9?4n22g>1=<a:9h6=4+31g9717<f::o6854i21a>5<#;9o1?9?4n22g>3=<a:9j6=4+31g9717<f::o6:54oe:94?"48l0o;6`<0e83?>ic>3:1(>>j:e58j66c2810ci:50;&04`<c?2d8<i4=;:mg7?6=,::n6i94n22g>6=<gm81<7*<0d8g3>h48m0?76ak1;29 66b2m=0b>>k:498ka6=83.8<h4k7:l04a<132ehj7>5$22f>a1<f::o6:54obg94?"48l0o;6`<0e8;?>idl3:1(>>j:e58j66c2010cnm50;&04`<c?2d8<i4n;:m`f?6=,::n6i94n22g>g=<gj31<7*<0d8g3>h48m0h76al8;29 66b2m=0b>>k:e98kf1=83.8<h4k7:l04a<b32eh:7>5$22f>a1<f::o6k54ob794?"48l0o;6`<0e824>=hk=0;6)=?e;f4?k57l3;:76al3;29 66b2m=0b>>k:008?je5290/?=k5d69m75b=9:10cn?50;&04`<c?2d8<i4>4:9lg5<72-9;i7j8;o13`?7232eoj7>5$22f>a1<f::o6<84;nff>5<#;9o1h:5a31f952=<gmn1<7*<0d8g3>h48m0:465`db83>!57m3n<7c=?d;3:?>icj3:1(>>j:e58j66c28k07bjn:18'75c=l>1e?=j51c98ka?=83.8<h4k7:l04a<6k21dh84?:%13a?b03g9;h7?k;:m`e?6=,::n6i94n22g>4c<3fhm6=4+31g9`2=i;9n1=k54o024>5<#;9o1==84n22g>5=<g8:>6=4+31g9550<f::o6<54o027>5<#;9o1==84n22g>7=<g8:86=4+31g9550<f::o6>54ogc94?"48l0m56`<0e83?>ia03:1(>>j:g;8j66c2810ck850;&04`<a12d8<i4=;:me1?6=,::n6k74n22g>6=<go>1<7*<0d8e=>h48m0?76ai3;29 66b2o30b>>k:498kc4=83.8<h4i9:l04a<132em=7>5$22f>c?<f::o6:54og294?"48l0m56`<0e8;?>ibn3:1(>>j:g;8j66c2010chk50;&04`<a12d8<i4n;:mf`?6=,::n6k74n22g>g=<glh1<7*<0d8e=>h48m0h76aja;29 66b2o30b>>k:e98k`?=83.8<h4i9:l04a<b32en47>5$22f>c?<f::o6k54od594?"48l0m56`<0e824>=hm?0;6)=?e;d:?k57l3;:76aj5;29 66b2o30b>>k:008?jc3290/?=k5f89m75b=9:10ch=50;&04`<a12d8<i4>4:9la7<72-9;i7h6;o13`?7232e:<<4?:%13a?`>3g9;h7?9;:m245<72-9;i7h6;o13`?7032emj7>5$22f>c?<f::o6<64;ndf>5<#;9o1j45a31f95<=<gon1<7*<0d8e=>h48m0:m65`fb83>!57m3l27c=?d;3a?>iaj3:1(>>j:g;8j66c28i07bh8:18'75c=n01e?=j51e98k`e=83.8<h4i9:l04a<6m21di<4?:%13a?`>3g9;h7?i;:m24f<72-9;i7??b:l04a<732e:<l4?:%13a?77j2d8<i4>;:m24<<72-9;i7??b:l04a<532e:<54?:%13a?77j2d8<i4<;:a77>=83;;>7>50z&062<48o1C?8<4H20g?_0528:ph7?;:d821?>=>331;7?8:0495a<6k3;;6<751082e?{im90;7c??2;28 4g52;1/=l=52:&251<53-;:97<4$035>7=#98=1>6*>1981?!761380(<?n:39'54d=:2.:=n4=;%32`?4<,8;n6?5+10d96>"6:9097)?=1;08 646281/??<51:&261<53-;997<4$005>7=#9;=1>6*>2981?!751380(<<n:39'57d=:2.:>n4=;%31`?4<,88n6?5+13d96>"6;9097)?<1;08 4552;1/=>=52:&271<53-;897<4$015>7=#9:=1>6*>3981?!741380(<=n:39'56d=:2.:?n4=;%30`?4<,89n6?5+12d96>"6<9097)?;1;08 4252;1/=9=52:&201<53-;?97<4$065>7=#9==1>6*>4981?!731380(<:n:39'51d=:2.:8n4=;%37`?4<,8>n6?5+15d96>"6=9097)?:1;08 4352;1/=8=52:&211<53-;>97<4$075>7=#9<=1>6*>5981?!721380(<;n:39'50d=:2.:9n4=;%36`?4<,8?n6?5+14d96>"6>9097)?91;08 4052;1/=;=52:&221<53-;=97<4$045>7=#9?=1>6*>6981?!711380(<8n:39'53d=:2.::n4=;%35`?4<,8<n6?5+17d96>"6?9097)?81;08 4152;1/=:=52:&231<53-;<97<4$055>7=#9>=1>6*>7981?!701380(<9n:39'52d=:2.:;n4=;%34`?4<,8=n6?5+16d96>"609097)?71;08 4>52;1/=5=52:&2<1<53-;397<4$0:5>7=#91=1>6*>8981?!7?1380(<6n:39'5=d=:2.:4n4=;%3;`?4<,82n6?5+19d96>"619097)?61;08 4?52;1/=4=52:&2=1<53-;297<4$0;5>7=#90=1>6*>9981?!7>1380(<7n:39'5<d=:2.:5n4=;%3:`?4<,83n6?5+18d96>"6i9097)?n1;08 67c28;:7)?=2;08 4g12::27)=>0;13=>"49808<45a3009=>h49:0986*<1d854>"49o08=n5+1`695>"6i<0:7)=;d;17g>"4<l088n5a35d9=>h4=90986*>2281?l77m3:17d??d;29?l7683:17d??f;29?l55<3:17d==3;29?l55>3:17d==5;29?l0c2900e;m50;9j2c<722c=i7>5;h12=?6=3`9:47>5;h12f?6=3`9:m7>5;h121?6=3`9:87>5;h123?6=3`9::7>5;h40>5<<a?>1<75f6483>>o1>3:17b88:188k3>=831d:44?::m5e?6=3`2h6=4+31g9<g=i;9n1<65f8`83>!57m32i7c=?d;38?l>?290/?=k58c9m75b=:21b4:4?:%13a?>e3g9;h7=4;h:5>5<#;9o14o5a31f90>=n0<0;6)=?e;:a?k57l3?07d6;:18'75c=0k1e?=j56:9j<6<72-9;i76m;o13`?1<3`296=4+31g9<g=i;9n1465f8083>!57m32i7c=?d;;8?l>7290/?=k58c9m75b=i21b;k4?:%13a?>e3g9;h7l4;h5g>5<#;9o14o5a31f9g>=n?j0;6)=?e;:a?k57l3n07d9m:18'75c=0k1e?=j5e:9j3d<72-9;i76m;o13`?`<3`=26=4+31g9<g=i;9n1==54i6:94?"48l03n6`<0e825>=n?>0;6)=?e;:a?k57l3;976g86;29 66b21h0b>>k:018?l12290/?=k58c9m75b=9=10e::50;&04`<?j2d8<i4>5:9j=6<72-9;i76m;o13`?7132c2>7>5$22f>=d<f::o6<94;h;2>5<#;9o14o5a31f95==<a0:1<7*<0d8;f>h48m0:565f8g83>!57m32i7c=?d;3b?>o?m3:1(>>j:9`8j66c28h07d6k:18'75c=0k1e?=j51b98m=?=83.8<h47b:l04a<6l21b;h4?:%13a?>e3g9;h7?j;:k47?6=,::n65l4n22g>4`<3`h26=4+31g9f==i;9n1<65fb683>!57m3h37c=?d;38?ld1290/?=k5b99m75b=:21bn84?:%13a?d?3g9;h7=4;hcg>5<#;9o1mn5a31f94>=nik0;6)=?e;c`?k57l3;07do6:18'75c=ij1e?=j52:9je=<72-9;i7ol;o13`?5<3`k<6=4+31g9ef=i;9n1865fa783>!57m3kh7c=?d;78?lg2290/?=k5ab9m75b=>21bm94?:%13a?gd3g9;h794;hc0>5<#;9o1mn5a31f9<>=ni;0;6)=?e;c`?k57l3307do>:18'75c=ij1e?=j5a:9je5<72-9;i7ol;o13`?d<3`3n6=4+31g9ef=i;9n1o65f9e83>!57m3kh7c=?d;f8?l?d290/?=k5ab9m75b=m21b5o4?:%13a?gd3g9;h7h4;h;b>5<#;9o1mn5a31f955=<a031<7*<0d8bg>h48m0:=65f9983>!57m3kh7c=?d;31?>o>?3:1(>>j:`a8j66c28907d79:18'75c=ij1e?=j51598m<3=83.8<h4nc:l04a<6=21bn94?:%13a?gd3g9;h7?9;:ka7?6=,::n6lm4n22g>41<3`h96=4+31g9ef=i;9n1=554ic394?"48l0jo6`<0e82=>=nj90;6)=?e;c`?k57l3;j76gnf;29 66b2hi0b>>k:0`8?lgb290/?=k5ab9m75b=9j10elo50;&04`<fk2d8<i4>d:9j=c<72-9;i7ol;o13`?7b32c287>5$22f>de<f::o6<h4;h`f>5<#;9o1ni5a31f94>=njj0;6)=?e;`g?k57l3;07dlm:18'75c=jm1e?=j52:9jfd<72-9;i7lk;o13`?5<3`8>6=4+31g961=i;9n1<65f2283>!57m38?7c=?d;38?l45290/?=k5259m75b=:21b><4?:%13a?433g9;h7=4;h03>5<#;9o1>95a31f90>=n9o0;6)=?e;07?k57l3?07d<j:18'75c=:=1e?=j56:9j6a<72-9;i7<;;o13`?1<3`8h6=4+31g961=i;9n1465f2c83>!57m38?7c=?d;;8?l4f290/?=k5259m75b=i21b>44?:%13a?433g9;h7l4;h0;>5<#;9o1>95a31f9g>=n:>0;6)=?e;07?k57l3n07d<9:18'75c=:=1e?=j5e:9j5`<72-9;i7<;;o13`?`<3`9>6=4+31g971=i;9n1<65f3283>!57m39?7c=?d;38?l55290/?=k5359m75b=:21b?<4?:%13a?533g9;h7=4;h13>5<#;9o1?95a31f90>=n;l0;6)=?e;17?k57l3?07d=k:18'75c=;=1e?=j56:9j7f<72-9;i7=;;o13`?1<3`9i6=4+31g971=i;9n1465f3`83>!57m39?7c=?d;;8?l5>290/?=k5359m75b=i21b?54?:%13a?533g9;h7l4;h14>5<#;9o1?95a31f9g>=n;?0;6)=?e;17?k57l3n07d<i:18'75c=;=1e?=j5e:9j03<72-9;i7::;o13`?6<3`>?6=4+31g900=i;9n1=65f4283>!57m3>>7c=?d;08?l25290/?=k5449m75b=;21b8<4?:%13a?223g9;h7:4;h63>5<#;9o1885a31f91>=n<o0;6)=?e;66?k57l3<07d:j:18'75c=<<1e?=j57:9j0a<72-9;i7::;o13`?><3`>h6=4+31g900=i;9n1565f4c83>!57m3>>7c=?d;c8?l2f290/?=k5449m75b=j21b844?:%13a?223g9;h7m4;h6;>5<#;9o1885a31f9`>=n<>0;6)=?e;66?k57l3o07d=i:18'75c=<<1e?=j5f:9j13<72-9;i7;:;o13`?6<3`??6=4+31g910=i;9n1=65f5283>!57m3?>7c=?d;08?l35290/?=k5549m75b=;21b9<4?:%13a?323g9;h7:4;h7e>5<#;9o1985a31f91>=n=l0;6)=?e;76?k57l3<07d;k:18'75c==<1e?=j57:9j1f<72-9;i7;:;o13`?><3`?i6=4+31g910=i;9n1565f5`83>!57m3?>7c=?d;c8?l3>290/?=k5549m75b=j21b954?:%13a?323g9;h7m4;h74>5<#;9o1985a31f9`>=n=90;6)=?e;76?k57l3o07d=<9;29 66b2:937c=?d;28?l54?3:1(>>j:21;?k57l3;07d=<6;29 66b2:937c=?d;08?l54=3:1(>>j:21;?k57l3907d=<4;29 66b2:987c=?d;28?l54:3:1(>>j:210?k57l3;07d=<1;29 66b2:987c=?d;08?l5483:1(>>j:210?k57l3907d=;b;29 66b2:>j7c=?d;28?l5313:1(>>j:26b?k57l3;07d=;8;29 66b2:>j7c=?d;08?l53?3:1(>>j:26b?k57l3907d=;6;29 66b2:>j7c=?d;68?l53=3:1(>>j:26b?k57l3?07d=;4;29 66b2:>j7c=?d;48?l53;3:1(>>j:26b?k57l3=07d=;2;29 66b2:>:7c=?d;28?l5383:1(>>j:262?k57l3;07d=<f;29 66b2:>:7c=?d;08?l54m3:1(>>j:262?k57l3907d=<d;29 66b2:>:7c=?d;68?l54k3:1(>>j:262?k57l3?07d=<b;29 66b2:>:7c=?d;48?l54i3:1(>>j:262?k57l3=07bj7:18'75c=l>1e?=j50:9l`3<72-9;i7j8;o13`?7<3fn?6=4+31g9`2=i;9n1>65`d283>!57m3n<7c=?d;18?jb5290/?=k5d69m75b=<21dh<4?:%13a?b03g9;h7;4;nf3>5<#;9o1h:5a31f92>=hko0;6)=?e;f4?k57l3=07bmj:18'75c=l>1e?=j58:9lga<72-9;i7j8;o13`??<3fih6=4+31g9`2=i;9n1m65`cc83>!57m3n<7c=?d;`8?je>290/?=k5d69m75b=k21do54?:%13a?b03g9;h7j4;na4>5<#;9o1h:5a31f9a>=hk?0;6)=?e;f4?k57l3l07bm::18'75c=l>1e?=j51198kf2=83.8<h4k7:l04a<6921do>4?:%13a?b03g9;h7?=;:m`6?6=,::n6i94n22g>45<3fi:6=4+31g9`2=i;9n1=954ob294?"48l0o;6`<0e821>=hlo0;6)=?e;f4?k57l3;=76ake;29 66b2m=0b>>k:058?jbc290/?=k5d69m75b=9110cim50;&04`<c?2d8<i4>9:9l`g<72-9;i7j8;o13`?7f32eom7>5$22f>a1<f::o6<l4;nf:>5<#;9o1h:5a31f95f=<gm?1<7*<0d8g3>h48m0:h65`c`83>!57m3n<7c=?d;3f?>ien3:1(>>j:e58j66c28l07b??7;29 66b28:=7c=?d;28?j77=3:1(>>j:025?k57l3;07b??4;29 66b28:=7c=?d;08?j77;3:1(>>j:025?k57l3907bhn:18'75c=n01e?=j50:9lb=<72-9;i7h6;o13`?7<3fl=6=4+31g9b<=i;9n1>65`f483>!57m3l27c=?d;18?j`3290/?=k5f89m75b=<21dj>4?:%13a?`>3g9;h7;4;nd1>5<#;9o1j45a31f92>=hn80;6)=?e;d:?k57l3=07bh?:18'75c=n01e?=j58:9lac<72-9;i7h6;o13`??<3fon6=4+31g9b<=i;9n1m65`ee83>!57m3l27c=?d;`8?jce290/?=k5f89m75b=k21dil4?:%13a?`>3g9;h7j4;ng:>5<#;9o1j45a31f9a>=hm10;6)=?e;d:?k57l3l07bk8:18'75c=n01e?=j51198k`0=83.8<h4i9:l04a<6921di84?:%13a?`>3g9;h7?=;:mf0?6=,::n6k74n22g>45<3fo86=4+31g9b<=i;9n1=954od094?"48l0m56`<0e821>=h99;1<7*<0d8e=>h48m0::65`11294?"48l0m56`<0e823>=hno0;6)=?e;d:?k57l3;376aie;29 66b2o30b>>k:0;8?j`c290/?=k5f89m75b=9h10ckm50;&04`<a12d8<i4>b:9lbg<72-9;i7h6;o13`?7d32em;7>5$22f>c?<f::o6<j4;ng`>5<#;9o1j45a31f95`=<gl;1<7*<0d8e=>h48m0:j65`11a94?"48l0:<o5a31f94>=h99k1<7*<0d824g=i;9n1=65`11;94?"48l0:<o5a31f96>=h9921<7*<0d824g=i;9n1?65rs4d4>5<6ijqU?;84^4d`?[3a=2789>4>139>77d=;;>01><m:200?855j399:63<2c8060=:;;h1?<;4=20a>6733499n7=>7:?06g<49?16??l5629>77d=>=16??l5649>77d=>?16??l58b9>77d=0h16??l5899>77d=0>16??l5879>77d=0<16??l5859>77d=0:16??l5839>77d=0816??l5819>77d=?o16??l57e9>77d=?j16??l57c9>77d=?h16??l5789>77d=?116??l5769>77d=??16??l5749>77d=?=16??l5929>77d=1;16??l5b89>77d=j>16??l5b79>77d=j<16??l5bd9>77d=jj16??l5bc9>77d=jh16??l5249>77d=::16??l5239>77d=:816??l5219>77d=9o16??l52d9>77d=:m16??l52b9>77d=:k16??l5269>77d=:?16??l51d9>77d=;<16??l5329>77d=;;16??l5309>77d=;916??l53d9>77d=;m16??l53b9>77d=;k16??l5369>77d=;?16??l52g9>77d=<?16??l5459>77d=<:16??l5439>77d=<816??l5419>77d=<o16??l54d9>77d=<m16??l54b9>77d=<h16??l5489>77d=<116??l5469>77d=;o16??l5579>77d===16??l5529>77d==;16??l5509>77d==o16??l55d9>77d==m16??l55b9>77d==h16??l5589>77d==116??l5569>77d==916??l535`8964e2:>270==b;17<>;4:k088:5233`9714<5:8i6>:?;<11f?54n278>o4<3d9>77g=;;>01><n:200?855i399:63<2`8060=:;;k1?<;4=20b>6733499m7=>7:?06d<49?16??o5629>77g=>=16??o5649>77g=>?16??o58b9>77g=0h16??o5899>77g=0>16??o5879>77g=0<16??o5859>77g=0:16??o5839>77g=0816??o5819>77g=?o16??o57e9>77g=?j16??o57c9>77g=?h16??o5789>77g=?116??o5769>77g=??16??o5749>77g=?=16??o5929>77g=1;16??o5b89>77g=j>16??o5b79>77g=j<16??o5bd9>77g=jj16??o5bc9>77g=jh16??o5249>77g=::16??o5239>77g=:816??o5219>77g=9o16??o52d9>77g=:m16??o52b9>77g=:k16??o5269>77g=:?16??o51d9>77g=;<16??o5329>77g=;;16??o5309>77g=;916??o53d9>77g=;m16??o53b9>77g=;k16??o5369>77g=;?16??o52g9>77g=<?16??o5459>77g=<:16??o5439>77g=<816??o5419>77g=<o16??o54d9>77g=<m16??o54b9>77g=<h16??o5489>77g=<116??o5469>77g=;o16??o5579>77g===16??o5529>77g==;16??o5509>77g==o16??o55d9>77g==m16??o55b9>77g==h16??o5589>77g==116??o5569>77g==916??o535`8964f2:>270==a;17<>;4:h088:5233c9714<5:8j6>:?;<11e?54n278>l4<3d9>77?=;;>01><6:200?8551399:63<288060=:;;31?<;4=20:>673349957=>7:?06<<49?16??75629>77?=>=16??75649>77?=>?16??758b9>77?=0h16??75899>77?=0>16??75879>77?=0<16??75859>77?=0:16??75839>77?=0816??75819>77?=?o16??757e9>77?=?j16??757c9>77?=?h16??75789>77?=?116??75769>77?=??16??75749>77?=?=16??75929>77?=1;16??75b89>77?=j>16??75b79>77?=j<16??75bd9>77?=jj16??75bc9>77?=jh16??75249>77?=::16??75239>77?=:816??75219>77?=9o16??752d9>77?=:m16??752b9>77?=:k16??75269>77?=:?16??751d9>77?=;<16??75329>77?=;;16??75309>77?=;916??753d9>77?=;m16??753b9>77?=;k16??75369>77?=;?16??752g9>77?=<?16??75459>77?=<:16??75439>77?=<816??75419>77?=<o16??754d9>77?=<m16??754b9>77?=<h16??75489>77?=<116??75469>77?=;o16??75579>77?===16??75529>77?==;16??75509>77?==o16??755d9>77?==m16??755b9>77?==h16??75589>77?==116??75569>77?==916??7535`8964>2:>270==9;17<>;4:0088:5233;9714<5:826>:?;<11=?54n278>44<3d9>77>=;;>01><7:200?8550399:63<298060=:;;21?<;4=20;>673349947=>7:?06=<49?16??65629>77>=>=16??65649>77>=>?16??658b9>77>=0h16??65899>77>=0>16??65879>77>=0<16??65859>77>=0:16??65839>77>=0816??65819>77>=?o16??657e9>77>=?j16??657c9>77>=?h16??65789>77>=?116??65769>77>=??16??65749>77>=?=16??65929>77>=1;16??65b89>77>=j>16??65b79>77>=j<16??65bd9>77>=jj16??65bc9>77>=jh16??65249>77>=::16??65239>77>=:816??65219>77>=9o16??652d9>77>=:m16??652b9>77>=:k16??65269>77>=:?16??651d9>77>=;<16??65329>77>=;;16??65309>77>=;916??653d9>77>=;m16??653b9>77>=;k16??65369>77>=;?16??652g9>77>=<?16??65459>77>=<:16??65439>77>=<816??65419>77>=<o16??654d9>77>=<m16??654b9>77>=<h16??65489>77>=<116??65469>77>=;o16??65579>77>===16??65529>77>==;16??65509>77>==o16??655d9>77>==m16??655b9>77>==h16??65589>77>==116??65569>77>==916??6535`8964?2:>270==8;17<>;4:1088:5233:9714<5:836>:?;<11<?54n278>54<3d9~w0cd2902wS;jc:?06g<68l16??l511f8964f28:n70==a;33`>;4:00:<h5233;955b<5:836<>j;<11<?77l2wx9hj50;;xZ0cc3499n7?>0:?06g<68o16??o51028964f28:m70==9;324>;4:00:<k5233:9546<5:836<>i;|q021<728;pR>8;;<11f?0c3499n78l;<11f?561278>o4<199>77g=>m16??o56b9>77g=;8301><n:23;?85513<o70==9;4`?855139:563<28805==:;;21:i5233:92f=:;;21?<74=20;>67?3ty8:84?:03xZ6023499n78i;<11f?0b3499n7=>b:?06g<49h16??o56g9>77g=>l16??o530`8964f2:;j70==9;4e?85513<n70==9;12f>;4:008=l5233:92c=:;;21:h5233:974d<5:836>?n;|q7a7<72;qU8n<4=20a>ab<uz>n<7>52z\7g4=:;;h1hn5rs5ff>5<5sW>ij63<2c8gf>{t<mn1<7<t^5`f?855j3nj7p};db83>7}Y<kn01><m:e;8yv2cj3:1>vP;bb9>77d=l<1v9jn:181[2ej278>o4la:p0a?=838pR9ln;<11f?da3ty?h54?:3y]0g?<5:8j6ij4}r6g3?6=:rT?n55233c9`f=z{=n=6=4={_6a3>;4:h0on6s|4e794?4|V=h=70==a;fb?xu3l:0;6?uQ4c68964f2m30q~:k2;296~X3j:16??o5d49~w1b62909wS:m2:?06d<di2wx8i>50;0xZ1d63499m7li;|q7gc<72;qU8o>4=20:>ab<uz>hi7>52z\7ec=:;;31hn5rs5ag>5<5sW>ji63<288gf>{t<ji1<7<t^5cg?85513nj7p};cc83>7}Y<hi01><6:e;8yv2di3:1>vP;ac9>77?=l<1v9k6:181[2d0278>44la:p0`>=838pR9m8;<11=?da3ty?i:4?:3y]0f0<5:836ij4}r6f2?6=:rT?o85233:9`f=z{=o>6=4={_6`0>;4:10on6s|4d694?4|V=i870==8;fb?xu3m:0;6?uQ4b28964?2m30q~:kf;296~X3j<16??65d49~w1b32909wS:na:?06=<di2wx8n750;0xZ1g>349947li;|q6<<<72;qU9=o4=20a>cg<uz?3;7>52z\64<=:;;h1j55rs4:5>5<5sW?;463<2c8e2>{t=1?1<7<t^424?855j3l>7p}:8583>7}Y=9<01><m:g68yv3?;3:1>vP:049>77d=n:1v86=:181[37<278>o4i2:p1=7=838pR8><;<11f?`63ty>;k4?:3y]157<5:8j6ko4}r74a?6=:rT><=5233c9b==z{<=o6=4={_6eb>;4:h0m:6s|56a94?4|V=ln70==a;d6?xu2?k0;6?uQ4gf8964f2o>0q~;8a;296~X3nj16??o5f29~w01>2909wS:ib:?06d<a:2wx9:650;0xZ1`f3499m7h>;|q632<72;qU8k74=20:>cg<uz?<:7>52z\7b==:;;31j55rs457>5<5sW>m:63<288e2>{t=>91<7<t^5d6?85513l>7p}:7383>7}Y<o>01><6:g68yv3093:1>vP;f29>77?=n:1v89?:181[2a:278>44i2:p13`=838pR9h>;<11=?`63ty>:h4?:3y]0c6<5:836ko4}r75`?6=:rT?ik5233:9b==z{<<h6=4={_6fa>;4:10m:6s|57`94?4|V=oo70==8;d6?xu2m00;6?uQ57;8964?2o>0q~;j8;296~X2>116??65f29~w0c02909wS;97:?06=<a:2wx9h850;0xZ001349947h>;|q6a0<72;qU9;;4=20a>c6<uz?n87>52z\621=:;;h1ik5rs4g0>5<5sW?=?63<2c8fa>{t=l81<7<t^441?855j3oo7p}:e083>7}Y=?;01><m:d`8yv3b83:1>vP:619>77d=mh1v8jj:181[32m278>o4j9:p1ab=838pR8;k;<11f?c?3ty>hn4?:3y]10e<5:8j6k>4}r7gf?6=:rT>9o5233c9ac=z{<nj6=4={_76e>;4:h0ni6s|5e;94?4|V<?270==a;gg?xu2l10;6?uQ54:8964f2lh0q~;k7;296~X2=>16??o5e`9~w0b12909wS;:6:?06d<b12wx9i;50;0xZ0323499m7k7;|q6`6<72;qU98=4=20:>c6<uz?o>7>52z\617=:;;31ik5rs4f2>5<5sW?>=63<288fa>{t=m:1<7<t^473?85513oo7p}:cg83>7}Y==l01><6:d`8yv3dm3:1>vP:4d9>77?=mh1v8mk:181[33l278>44j9:p1fe=838pR8:l;<11=?c?3ty>oo4?:3y]11d<5:836k>4}r7`e?6=:rT>8l5233:9ac=z{<i36=4={_77<>;4:10ni6s|5b594?4|V<><70==8;gg?xu2k?0;6?uQ5548964?2lh0q~;l5;296~X2<<16??65e`9~w0e32909wS;;4:?06=<b12wx9n=50;0xZ024349947k7;|q6g7<72;qU99<4=20a>`1<uz?h=7>52z\604=:;;h1i;5rs4a3>5<5sW??<63<2c8f1>{t=kl1<7<t^41e?855j3o?7p}:be83>7}Y=:n01><m:d18yv3ek3:1>vP:3b9>77d=m;1v8lm:181[34j278>o4>009~w0df2909wS;<a:?06g<6891v8l6:181[341278>l4j7:p1g>=838pR8=7;<11e?c13ty>n:4?:3y]161<5:8j6h;4}r7a2?6=:rT>?;5233c9a1=z{<h>6=4={_701>;4:h0n?6s|5c694?4|V<9?70==a;g1?xu2j;0;6?uQ5208964f28::7p}:b083>7}Y=:;01><n:023?xu2j90;6?uQ5228964>2l=0q~;nf;296~X2:o16??75e79~w0gb2909wS;=e:?06<<b=2wx9lj50;0xZ04c349957k;;|q6ef<72;qU9?m4=20:>`5<uz?jn7>52z\66g=:;;31i?5rs4cb>5<5sW?9m63<288244=z{<k26=4={_71=>;4:00:<=5rs4c4>5<5sW?9;63<298f3>{t=h<1<7<t^405?85503o=7p}:a483>7}Y=;?01><7:d78yv3f<3:1>vP:259>77>=m=1v8o<:181[35;278>54j3:p1d4=838pR8<=;<11<?c53ty>m<4?:3y]177<5:836<>>;|q6e5<72;qU9?>4=20;>4673ty>5k4?:3y]14`<5:8i6kh4}r7:a?6=:rT>=h5233`9b`=z{<3h6=4={_72g>;4:k0mh6s|58`94?4|V<;i70==b;d`?xu21h0;6?uQ50c8964e2oh0q~;69;296~X29016??l5f69~w0??2909wS;>8:?06g<bk2wx94950;0xZ0703499n7k>;|q6=3<72;qU9<84=20b>c`<uz?297>52z\650=:;;k1jh5rs4;7>5<5sW?:863<2`8e`>{t=091<7<t^430?855i3lh7p}:9083>7}Y=8;01><n:g`8yv3>83:1>vP:119>77g=n>1v86i:181[37n278>l4jc:p1=c=838pR8>j;<11e?c63ty>4i4?:3y]15b<5:826kh4}r7;g?6=:rT><n5233;9b`=z{<2i6=4={_73f>;4:00mh6s|59c94?4|V<:970==9;d`?xu2090;6?uQ4g58964>2oh0q~;85;296~X3mj16??75f69~w0cf2909wS;:f:?06<<bk2wx9ih50;0xZ033349957k>;|q6`1<72;qU9974=20;>c`<uz?h57>52z\67`=:;;21jh5rs4`f>5<5sW?8?63<298e`>{t=k91<7<t^40;?85503lh7p}:a983>7}Y=8n01><7:g`8yv3>l3:1>vP:139>77>=n>1v87=:181[2bj278>54jc:p13g=838pR9kn;<11<?c63ty=<;4?:8y]257<5:8i6>=6;<11f?54?278>o4<379>77d=;:?01><m:217?855j398>63<2c8074=:;;h1?>>4}r430?6=1rT=<=5233c976?<5:8j6>=8;<11e?54>278>l4<349>77g=;:>01><n:211?855i398=63<2`8075=z{?:86=46{_7eb>;4:008?45233;9761<5:826>=9;<11=?54=278>44<359>77?=;:801><6:212?8551398<6s|61094??|V<ln70==8;10=>;4:108?:5233:9760<5:836>=:;<11<?54<278>54<339>77>=;:;01><7:213?xu19l0;6>uQ61g8964e2:>=70==b;10`>{t>8i1<7=t^72g?855i39?:63<2`807a=z{?;i6=4<{_43g>;4:0088;5233;976b<uz<:m7>53z\54g=:;;21?984=20;>65c3ty==44?:2y]25g<5:8i6>::;<11f?54k2wx:<650;1xZ36>3499m7=;5:?06d<4;j1v;<8:180[06>278>44<449>77?=;:i0q~8=6;297~X19<16??653578964?2:9h7p}92483>6}Y>8>01><m:267?855j398n6s|63694?5|V?;870==a;170>;4:h08?o5rs700>5<4sW<:>63<288001=:;;31?>l4}r416?6=;rT==<5233:9712<5:836>=m;|q564<72:qU:<>4=20a>6243499n7=<a:p276=839pR;>i;<11e?53;278>l4<3`9~w37a2908wS8?8:?06<<4<:16??7532c8yv06?3:1?vP9069>77>=;=901><7:21b?xu4=o0;64uQ34`8964e2;k01><m:2c8964f2;k01><n:2c8964>2;k01><6:2c8964?2;k01><7:2c8yv52l3:15vP<5`9>77d=:016??l5389>77g=:016??o5389>77?=:016??75389>77>=:016??65389~w63d2902wS=:9:?06g<50278>o4<8:?06d<50278>l4<8:?06<<50278>44<8:?06=<50278>54<8:p734=833pR>8?;<11f?2e3499n7;m;<11e?2e3499m7;m;<11=?2e349957;m;<11<?2e349947;m;|q0e5<72;qU?5>4=20a><7<uz92i7>52z\03c=:;;h15=5rs2;`>5<5sW9<h63<2c8;b>{t;0h1<7<t^25`?855j32n7p}<9`83>7}Y;>h01><m:9f8yv5>13:1>vP<7`9>77d=001v>77:181[501278>o48e:p7<1=838pR>97;<11f?143ty85;4?:3y]721<5:8j64?4}r1:1?6=:rT8;;5233c9=5=z{:3?6=4={_141>;4:h03j6s|38194?4|V:=?70==a;:f?xu4180;6?uQ3608964f21n0q~=60;296~X4?816??o5889~w6>a2909wS=80:?06d<0m2wx?5k50;0xZ60a3499m79<;|q0<a<72;qU?;k4=20:><7<uz93o7>52z\02a=:;;315=5rs2:a>5<5sW9=o63<288;b>{t;1k1<7<t^24a?855132n7p}<8883>7}Y;?k01><6:9f8yv5?03:1>vP<689>77?=001v>o8:181[5?>278>448e:p7d0=838pR>6:;<11=?143ty8m84?:3y]7=2<5:8364?4}r1b0?6=:rT84>5233:9=5=z{:k86=4={_1;6>;4:103j6s|3`094?4|V:2:70==8;:f?xu4i80;6?uQ36g8964?21n0q~=6d;296~X4?:16??65889~w6?52909wS=98:?06=<0m2wx?5950;0xZ6003499479<;|q702<72;qU?n64=20a>db<uz>?97>52z\0g2=:;;h1mo5rs567>5<5sW9h:63<2c8b=>{t<=91<7<t^2a6?855j3k37p};4383>7}Y;j>01><m:`58yv2393:1>vP<c29>77d=i?1v9:?:181[5d:278>o4n5:p06`=838pR>m>;<11f?g33ty??i4?:3y]7g`<5:8j6lj4}r60g?6=:rT8nh5233c9eg=z{=9i6=4={_1a`>;4:h0j56s|42c94?4|V:hh70==a;c;?xu3;00;6?uQ3c`8964f2h=0q~:<8;296~X4jh16??o5a79~w1502909wS=m9:?06d<f=2wx8>850;0xZ6d?3499m7o;;|q770<72;qU?o94=20:>db<uz>887>52z\0f3=:;;31mo5rs511>5<5sW9i863<288b=>{t<:;1<7<t^2`0?85513k37p};3183>7}Y;k801><6:`58yv25n3:1>vP<b09>77?=i?1v9<j:181[5e8278>44n5:p07b=838pR>oi;<11=?g33ty?>n4?:3y]7dc<5:836lj4}r61f?6=:rT8mi5233:9eg=z{=8j6=4={_1bg>;4:10j56s|43;94?4|V:ki70==8;c;?xu3i>0;6?uQ4358964?2h=0q~:n6;296~X3:?16??65a79~w1g22909wS:=5:?06=<f=2wx8l:50;0xZ143349947o;;|q7e6<72;qU8?=4=20a>d5<uz>j>7>52z\767=:;;h1m?5rs5c2>5<5sW>9=63<2c8b5>{t<h:1<7<t^503?855j3k;7p};9g83>7}Y<8l01><m:8g8yv2>m3:1>vP;1d9>77d=1m1v97l:181[26k278>o46c:p0<d=838pR9?m;<11f??e3ty?5l4?:3y]04g<5:8j6l=4}r6:=?6=:rT?=45233c9e7=z{=336=4={_62<>;4:h0j=6s|48594?4|V=;<70==a;c3?xu31?0;6?uQ4048964f20o0q~:65;296~X39<16??o59e9~w1?32909wS:>4:?06d<>k2wx84=50;0xZ1743499m77m;|q7=4<72;qU8<?4=20:>d5<uz>2<7>52z\755=:;;31m?5rs5:e>5<5sW>;j63<288b5>{t<1o1<7<t^52f?85513k;7p};8e83>7}Y<9n01><6:8g8yv2?k3:1>vP;0b9>77?=1m1v96m:181[27j278>446c:p0=g=838pR9>n;<11=??e3ty?444?:3y]05?<5:836l=4}r6;<?6=:rT?<55233:9e7=z{=2=6=4={_632>;4:10j=6s|49794?4|V=:>70==8;c3?xu30=0;6?uQ4168964?20o0q~:73;296~X38:16??659e9~w1>52909wS:?2:?06=<>k2wx85?50;0xZ1663499477m;|q7<5<72;qU8=>4=20a><g<uz><j7>52z\0bc=:;;h1545rs55f>5<5sW9mi63<2c8:<>{t<>n1<7<t^2dg?855j33<7p};7c83>7}Y;oh01><m:848yv20i3:1>vP<f`9>77d=1<1v996:181[5a1278>o4m4:p02>=838pR>h7;<11f?d43ty?;:4?:3y]7c1<5:8j64o4}r642?6=:rT8j;5233c9=<=z{==>6=4={_1e1>;4:h0246s|46694?4|V:l?70==a;;4?xu3?:0;6?uQ3g18964f20<0q~:82;296~X4n;16??o5949~w1172909wS=i0:?06d<e<2wx8;h50;0xZ6ca3499m7l<;|q72`<72;qU?hk4=20:><g<uz>=h7>52z\0aa=:;;31545rs54`>5<5sW9no63<288:<>{t<?h1<7<t^2ga?855133<7p};6`83>7}Y;lk01><6:848yv2113:1>vP<e89>77?=1<1v987:181[5b0278>44m4:p031=838pR>k8;<11=?d43ty?:84?:3y]7`3<5:8364o4}r650?6=:rT8i95233:9=<=z{=<86=4={_1f7>;4:10246s|47094?4|V:o970==8;;4?xu3>80;6?uQ3d38964?20<0q~:90;296~X4m916??65949~w13a2909wS=kf:?06=<e<2wx88k50;0xZ6bb349947l<;|q71a<72;qU?ij4=20a>g4<uz>>o7>52z\0`f=:;;h1n<5rs57b>5<5sW9om63<2c8a4>{t<<31<7<t^2f:?855j3km7p};5983>7}Y;m201><m:`g8yv22?3:1>vP<d69>77d=ih1v9;9:181[5c>278>o46f:p003=838pR>j:;<11f??33ty?994?:3y]7a2<5:8j6o<4}r667?6=:rT8h>5233c9f4=z{=?96=4={_1g6>;4:h0i<6s|44394?4|V:n:70==a;ce?xu3<o0;6?uQ3bd8964f2ho0q~:;e;296~X4kl16??o5a`9~w12c2909wS=ld:?06d<>n2wx89m50;0xZ6ed3499m77;;|q70g<72;qU?nl4=20:>g4<uz>?m7>52z\0gd=:;;31n<5rs56:>5<5sW9h563<288a4>{t<=21<7<t^2a3?85513km7p};3d83>7}Y;k?01><6:`g8yv24;3:1>vP<a`9>77?=ih1v9o7:181[26l278>446f:p0<b=838pR9?=;<11=??33ty?5?4?:3y]051<5:836o<4}r6;3?6=:rT8jn5233:9f4=z{==h6=4={_1e5>;4:10i<6s|46394?4|V:o=70==8;ce?xu3>?0;6?uQ3e`8964?2ho0q~::b;296~X4l916??65a`9~w1372909wS=n9:?06=<>n2wx8?650;0xZ6g?3499477;;|p732=838pR>8;;<42>6033-99o7<>9:p1`e=838pR8kl;<42>0cd3-99o7<l8:p250=838pR;>>;<42>3663-99o7<kd:p252=838pR;>?;<42>3673-99o7<j8:p255=838pR8hi;<42>0`a3-99o7<i2:p254=838pR8hj;<42>0`b3-99o7<ic:p70`=838pR>;m;<42>63e3-99o7?nb:p70b=838pR>;n;<42>63f3-99o7?m6:p70e=838pR>;6;<42>63>3-99o7?l1:p7d6=838pR>6?;<42>6>73-99o7?lc:p7<c=838pR>9i;<42>61a3-99o7?k7:p7<e=838pR>9k;<42>61c3-99o7?j2:p7<d=838pR>9l;<42>61d3-99o7?jd:p7<g=838pR>9m;<42>61e3-99o7?i8:p7<?=838pR>9n;<42>61f3-99o7<?3:p7<>=838pR>96;<42>61>3-99o7<?e:p7<1=838pR>97;<42>61?3-99o7<>a:p7<0=838pR>98;<42>6103-99o7<=5:p7<3=838pR>99;<42>6113-99o7<<0:p7<2=838pR>9:;<42>6123-99o7<<b:p7<5=838pR>9;;<42>6133-99o7<;6:p7<7=838pR>9=;<42>6153-99o7<:1:p7<6=838pR>9>;<42>6163-99o7<:c:p7=`=838pR>9?;<42>6173-99o7<97:p7=c=838pR>8i;<42>60a3-99o7<82:p7=b=838pR>8j;<42>60b3-99o7<8d:p7=e=838pR>8k;<42>60c3-99o7<78:p7=d=838pR>8l;<42>60d3-99o7<63:p7=g=838pR>8m;<42>60e3-99o7<6e:p7=?=838pR>8n;<42>60f3-99o7<n9:p7=>=838pR>86;<42>60>3-99o7<m4:p7d1=838pR>69;<42>6>13-99o7<mf:p7d0=838pR>6:;<42>6>23-99o7<l4:p7d3=838pR>6;;<42>6>33-99o7<l5:p7d2=838pR>6<;<42>6>43-99o7<l6:p7d5=838pR>6=;<42>6>53-99o7<l7:p7d4=838pR>6>;<42>6>63-99o7<l9:p7d7=838pR>9j;<42>61b3-99o7<la:p7<b=838pR>9<;<42>6143-99o7<lb:p7<4=838pR>87;<42>60?3-99o7<lc:p7=1=838pR>88;<42>6003-99o7<ld:p0`4=838pR9m=;<42>1e53-99o7<le:p0`6=838pR9m>;<42>1e63-99o7<lf:p0ac=838pR9li;<42>1da3-99o7<k0:p0ab=838pR9lj;<42>1db3-99o7<k1:p0ae=838pR9lk;<42>1dc3-99o7<k2:p0ad=838pR9ll;<42>1dd3-99o7<k3:p0ag=838pR9lm;<42>1de3-99o7<k4:p0a?=838pR9ln;<42>1df3-99o7<k5:p0a>=838pR9l6;<42>1d>3-99o7<k6:p0a1=838pR9l7;<42>1d?3-99o7<k7:p0a0=838pR9l8;<42>1d03-99o7<k8:p0a3=838pR9l9;<42>1d13-99o7<k9:p0a5=838pR9l;;<42>1d33-99o7<ka:p0a4=838pR9l<;<42>1d43-99o7<kb:p0a7=838pR9l=;<42>1d53-99o7<kc:p0a6=838pR9l>;<42>1d63-99o7<ke:p0f`=838pR9l?;<42>1d73-99o7<kf:p0fc=838pR9oi;<42>1ga3-99o7<j0:p0fb=838pR9oj;<42>1gb3-99o7<j1:p0fe=838pR9ok;<42>1gc3-99o7<j2:p0fd=838pR9ol;<42>1gd3-99o7<j3:p0fg=838pR9om;<42>1ge3-99o7<j4:p0`?=838pR9m7;<42>1e?3-99o7<j5:p0`>=838pR9m8;<42>1e03-99o7<j6:p0`1=838pR9m9;<42>1e13-99o7<j7:p0`0=838pR9m:;<42>1e23-99o7<j9:p0`3=838pR9m;;<42>1e33-99o7<ja:p0`2=838pR9m<;<42>1e43-99o7<jb:p0`5=838pR9m?;<42>1e73-99o7<jc:p0a`=838pR9l:;<42>1d23-99o7<jd:p0a2=838pR9on;<42>1gf3-99o7<je:p0f?=838pR9o6;<42>1g>3-99o7<jf:p733=838pR>8:;<42>6023-99o7<i0:p1`b=838pR8kk;<42>0cc3-99o7<i1:p24c=838pR;>j;<42>36b3-99o7<i3:p24e=838pR;>k;<42>36c3-99o7<i4:p24d=838pR;>l;<42>36d3-99o7<i5:p24g=838pR;>m;<42>36e3-99o7<i6:p24?=838pR;>n;<42>36f3-99o7<i7:p24>=838pR;>6;<42>36>3-99o7<i8:p271=838pR;?9;<42>3713-99o7<i9:p270=838pR;?:;<42>3723-99o7<ia:p273=838pR;?;;<42>3733-99o7<ib:p272=838pR;?<;<42>3743-99o7<id:p275=838pR;?=;<42>3753-99o7<ie:p274=838pR;?>;<42>3763-99o7<if:p277=838pR;??;<42>3773-99o7=?0:p276=838pR;>i;<42>36a3-99o7=?1:p24`=838pR;>7;<42>36?3-99o7=?2:p241=838pR;>8;<42>3603-99o7=?3:p734=838pR>8?;<42>6073-99o7=?4:p011=838pR>m7;<42>6e?3-99o7=?5:p013=838pR>m8;<42>6e03-99o7=?6:p012=838pR>m9;<42>6e13-99o7?nc:p015=838pR>m:;<42>6e23-99o7?nd:p014=838pR>m;;<42>6e33-99o7?ne:p017=838pR>m<;<42>6e43-99o7?nf:p016=838pR>m=;<42>6e53-99o7?m0:p06`=838pR>m>;<42>6e63-99o7?m1:p06b=838pR>li;<42>6da3-99o7?m2:p06e=838pR>lj;<42>6db3-99o7?m3:p06d=838pR>lk;<42>6dc3-99o7?m4:p06g=838pR>ll;<42>6dd3-99o7?m5:p06?=838pR>lm;<42>6de3-99o7?m7:p06>=838pR>ln;<42>6df3-99o7?m8:p061=838pR>l6;<42>6d>3-99o7?m9:p060=838pR>l7;<42>6d?3-99o7?ma:p063=838pR>l8;<42>6d03-99o7?mb:p062=838pR>l9;<42>6d13-99o7?mc:p064=838pR>l;;<42>6d33-99o7?md:p067=838pR>l<;<42>6d43-99o7?me:p066=838pR>l=;<42>6d53-99o7?mf:p07`=838pR>l>;<42>6d63-99o7?l0:p07c=838pR>l?;<42>6d73-99o7?l2:p07b=838pR>oi;<42>6ga3-99o7?l3:p07e=838pR>oj;<42>6gb3-99o7?l4:p07d=838pR>ok;<42>6gc3-99o7?l5:p07g=838pR>ol;<42>6gd3-99o7?l6:p07?=838pR>om;<42>6ge3-99o7?l7:p0d1=838pR9<8;<42>1403-99o7?l8:p0d0=838pR9<9;<42>1413-99o7?l9:p0d3=838pR9<:;<42>1423-99o7?la:p0d2=838pR9<;;<42>1433-99o7?lb:p0d5=838pR9<<;<42>1443-99o7?ld:p0d4=838pR9<=;<42>1453-99o7?le:p0d7=838pR9<>;<42>1463-99o7?lf:p0d6=838pR9<?;<42>1473-99o7?k0:p0<`=838pR9?i;<42>17a3-99o7?k1:p0<c=838pR9?j;<42>17b3-99o7?k2:p0<e=838pR9?l;<42>17d3-99o7?k3:p0<d=838pR9?m;<42>17e3-99o7?k4:p0<g=838pR9?n;<42>17f3-99o7?k5:p0<?=838pR9?6;<42>17>3-99o7?k6:p0<>=838pR9?7;<42>17?3-99o7?k8:p0<1=838pR9?8;<42>1703-99o7?k9:p0<0=838pR9?9;<42>1713-99o7?ka:p0<3=838pR9?:;<42>1723-99o7?kb:p0<2=838pR9?;;<42>1733-99o7?kc:p0<5=838pR9?<;<42>1743-99o7?kd:p0<7=838pR9?>;<42>1763-99o7?ke:p0<6=838pR9??;<42>1773-99o7?kf:p0=`=838pR9>i;<42>16a3-99o7?j0:p0=c=838pR9>j;<42>16b3-99o7?j1:p0=b=838pR9>k;<42>16c3-99o7?j3:p0=e=838pR9>l;<42>16d3-99o7?j4:p0=d=838pR9>m;<42>16e3-99o7?j5:p0=g=838pR9>n;<42>16f3-99o7?j6:p0=?=838pR9>6;<42>16>3-99o7?j7:p0=>=838pR9>7;<42>16?3-99o7?j8:p0=0=838pR9>9;<42>1613-99o7?j9:p0=3=838pR9>:;<42>1623-99o7?ja:p0=2=838pR9>;;<42>1633-99o7?jb:p0=5=838pR9><;<42>1643-99o7?jc:p0=4=838pR9>=;<42>1653-99o7?je:p0=7=838pR9>>;<42>1663-99o7?jf:p0=6=838pR9>?;<42>1673-99o7?i0:p02`=838pR>hi;<42>6`a3-99o7?i1:p02c=838pR>hj;<42>6`b3-99o7?i2:p02b=838pR>hk;<42>6`c3-99o7?i3:p02d=838pR>hm;<42>6`e3-99o7?i4:p02g=838pR>hn;<42>6`f3-99o7?i5:p02?=838pR>h6;<42>6`>3-99o7?i6:p02>=838pR>h7;<42>6`?3-99o7?i7:p021=838pR>h8;<42>6`03-99o7?i9:p020=838pR>h9;<42>6`13-99o7?ia:p023=838pR>h:;<42>6`23-99o7?ib:p022=838pR>h;;<42>6`33-99o7?ic:p025=838pR>h<;<42>6`43-99o7?id:p024=838pR>h=;<42>6`53-99o7?ie:p026=838pR>h?;<42>6`73-99o7?if:p03`=838pR>ki;<42>6ca3-99o7<?0:p03c=838pR>kj;<42>6cb3-99o7<?1:p03b=838pR>kk;<42>6cc3-99o7<?2:p03e=838pR>kl;<42>6cd3-99o7<?4:p03d=838pR>km;<42>6ce3-99o7<?5:p03g=838pR>kn;<42>6cf3-99o7<?6:p03?=838pR>k6;<42>6c>3-99o7<?7:p03>=838pR>k7;<42>6c?3-99o7<?8:p031=838pR>k8;<42>6c03-99o7<?9:p033=838pR>k:;<42>6c23-99o7<?a:p032=838pR>k;;<42>6c33-99o7<?b:p035=838pR>k<;<42>6c43-99o7<?c:p034=838pR>k=;<42>6c53-99o7<?d:p037=838pR>k>;<42>6c63-99o7<?f:p036=838pR>k?;<42>6c73-99o7<>0:p00`=838pR>ji;<42>6ba3-99o7<>1:p00c=838pR>jj;<42>6bb3-99o7<>2:p00b=838pR>jk;<42>6bc3-99o7<>3:p00e=838pR>jl;<42>6bd3-99o7<>4:p00g=838pR>jn;<42>6bf3-99o7<>5:p00?=838pR>j6;<42>6b>3-99o7<>6:p00>=838pR>j7;<42>6b?3-99o7<>7:p001=838pR>j8;<42>6b03-99o7<>8:p000=838pR>j9;<42>6b13-99o7<>b:p003=838pR>j:;<42>6b23-99o7<>c:p002=838pR>j;;<42>6b33-99o7<>d:p005=838pR>j<;<42>6b43-99o7<>e:p004=838pR>j=;<42>6b53-99o7<>f:p007=838pR>j>;<42>6b63-99o7<=0:p01`=838pR>mi;<42>6ea3-99o7<=1:p01c=838pR>mj;<42>6eb3-99o7<=2:p01b=838pR>mk;<42>6ec3-99o7<=3:p01e=838pR>ml;<42>6ed3-99o7<=4:p01d=838pR>mm;<42>6ee3-99o7<=6:p01g=838pR>mn;<42>6ef3-99o7<=7:p01?=838pR>m6;<42>6e>3-99o7<=8:p01>=838pR>m?;<42>6e73-99o7<=9:p06c=838pR>l:;<42>6d23-99o7<=a:p065=838pR>on;<42>6gf3-99o7<=b:p0d>=838pR9?k;<42>17c3-99o7<=c:p0<b=838pR9?=;<42>1753-99o7<=d:p0<4=838pR9>8;<42>1603-99o7<=e:p0=1=838pR>hl;<42>6`d3-99o7<=f:p02e=838pR>h>;<42>6`63-99o7<<1:p027=838pR>k9;<42>6c13-99o7<<2:p030=838pR>jm;<42>6be3-99o7<<3:p00d=838pR>j?;<42>6b73-99o7<<4:p006=838pR>o6;<42>6g>3-99o7<<5:p07>=838pR>o7;<42>6g?3-99o7<<6:p1=?=838pR8>n;<42>06f3-99o7<<7:p1=1=838pR8>6;<42>06>3-99o7<<8:p1=0=838pR8>7;<42>06?3-99o7<<9:p1=3=838pR8>8;<42>0603-99o7<<a:p1=2=838pR8>9;<42>0613-99o7<<c:p1=5=838pR8>:;<42>0623-99o7<<d:p1=4=838pR8>;;<42>0633-99o7<<e:p1=7=838pR8><;<42>0643-99o7<<f:p12`=838pR8>>;<42>0663-99o7<;0:p12c=838pR8>?;<42>0673-99o7<;1:p12b=838pR9hi;<42>1`a3-99o7<;2:p12e=838pR9hj;<42>1`b3-99o7<;3:p12d=838pR9hk;<42>1`c3-99o7<;4:p12g=838pR9hl;<42>1`d3-99o7<;5:p12?=838pR9hm;<42>1`e3-99o7<;7:p12>=838pR9hn;<42>1`f3-99o7<;8:p121=838pR9h6;<42>1`>3-99o7<;9:p120=838pR9h7;<42>1`?3-99o7<;a:p122=838pR9h9;<42>1`13-99o7<;b:p125=838pR9h:;<42>1`23-99o7<;c:p124=838pR9h;;<42>1`33-99o7<;d:p127=838pR9h<;<42>1`43-99o7<;e:p126=838pR9h=;<42>1`53-99o7<;f:p13`=838pR9h>;<42>1`63-99o7<:0:p13c=838pR9h?;<42>1`73-99o7<:2:p13b=838pR9ki;<42>1ca3-99o7<:3:p13e=838pR9kj;<42>1cb3-99o7<:4:p13d=838pR9kk;<42>1cc3-99o7<:5:p1`?=838pR886;<42>00>3-99o7<:6:p1`>=838pR887;<42>00?3-99o7<:7:p1`1=838pR888;<42>0003-99o7<:8:p1`0=838pR889;<42>0013-99o7<:9:p1`3=838pR88:;<42>0023-99o7<:a:p1`2=838pR88;;<42>0033-99o7<:b:p1`5=838pR88<;<42>0043-99o7<:d:p1`4=838pR88=;<42>0053-99o7<:e:p1`7=838pR88>;<42>0063-99o7<:f:p1`6=838pR88?;<42>0073-99o7<90:p1ac=838pR8;j;<42>03b3-99o7<91:p1ab=838pR8;k;<42>03c3-99o7<92:p1ae=838pR8;l;<42>03d3-99o7<93:p1ad=838pR8;m;<42>03e3-99o7<94:p1ag=838pR8;n;<42>03f3-99o7<95:p1a?=838pR8;6;<42>03>3-99o7<96:p1a>=838pR8;7;<42>03?3-99o7<98:p1a1=838pR8;8;<42>0303-99o7<99:p1a0=838pR8;9;<42>0313-99o7<9a:p1a3=838pR8;:;<42>0323-99o7<9b:p1a5=838pR8;<;<42>0343-99o7<9c:p1a4=838pR8;=;<42>0353-99o7<9d:p1a7=838pR8;>;<42>0363-99o7<9e:p1a6=838pR8;?;<42>0373-99o7<9f:p1f`=838pR8:i;<42>02a3-99o7<80:p1fc=838pR8:j;<42>02b3-99o7<81:p1fb=838pR8:k;<42>02c3-99o7<83:p1fe=838pR8:l;<42>02d3-99o7<84:p1fd=838pR8:m;<42>02e3-99o7<85:p1fg=838pR8:n;<42>02f3-99o7<86:p1f>=838pR8:7;<42>02?3-99o7<87:p1f1=838pR8:8;<42>0203-99o7<88:p1f0=838pR8:9;<42>0213-99o7<89:p1f3=838pR8::;<42>0223-99o7<8a:p1f2=838pR8:;;<42>0233-99o7<8b:p1f5=838pR8:<;<42>0243-99o7<8c:p1f4=838pR8:=;<42>0253-99o7<8e:p1f7=838pR8:>;<42>0263-99o7<8f:p1f6=838pR8:?;<42>0273-99o7<70:p1g`=838pR8=i;<42>05a3-99o7<71:p1gb=838pR8=k;<42>05c3-99o7<72:p1ge=838pR8=l;<42>05d3-99o7<73:p1gd=838pR8=m;<42>05e3-99o7<74:p1gg=838pR8=n;<42>05f3-99o7<75:p1g?=838pR8=6;<42>05>3-99o7<76:p1g>=838pR8=7;<42>05?3-99o7<77:p1g1=838pR8=8;<42>0503-99o7<79:p1g0=838pR8=9;<42>0513-99o7<7a:p1g3=838pR8=:;<42>0523-99o7<7b:p1g2=838pR8=;;<42>0533-99o7<7c:p1g4=838pR8==;<42>0553-99o7<7d:p1g7=838pR8=>;<42>0563-99o7<7e:p1g6=838pR8=?;<42>0573-99o7<7f:p1d`=838pR8<i;<42>04a3-99o7<60:p1dc=838pR8<j;<42>04b3-99o7<61:p1db=838pR8<k;<42>04c3-99o7<62:p1de=838pR8<l;<42>04d3-99o7<64:p1dd=838pR8<m;<42>04e3-99o7<65:p1dg=838pR8<n;<42>04f3-99o7<66:p1d?=838pR8<6;<42>04>3-99o7<67:p1d1=838pR8<8;<42>0403-99o7<68:p1d0=838pR8<9;<42>0413-99o7<69:p1d3=838pR8<:;<42>0423-99o7<6a:p1d2=838pR8<;;<42>0433-99o7<6b:p1d5=838pR8<<;<42>0443-99o7<6c:p1d4=838pR8<=;<42>0453-99o7<6d:p1d7=838pR8<>;<42>0463-99o7<6f:p1d6=838pR8<?;<42>0473-99o7<n0:p1<`=838pR8?i;<42>07a3-99o7<n1:p1<c=838pR8?j;<42>07b3-99o7<n2:p1<e=838pR8?l;<42>07d3-99o7<n3:p1<d=838pR8?m;<42>07e3-99o7<n4:p1<g=838pR8?n;<42>07f3-99o7<n5:p1<?=838pR8?6;<42>07>3-99o7<n6:p1<>=838pR8?7;<42>07?3-99o7<n7:p1<1=838pR8?8;<42>0703-99o7<n8:p1<0=838pR8?9;<42>0713-99o7<na:p1<3=838pR8?:;<42>0723-99o7<nb:p1<2=838pR8?;;<42>0733-99o7<nc:p1<5=838pR8?<;<42>0743-99o7<nd:p1<7=838pR8?>;<42>0763-99o7<ne:p1<6=838pR8??;<42>0773-99o7<nf:p1=`=838pR8>i;<42>06a3-99o7<m0:p1=c=838pR8>j;<42>06b3-99o7<m1:p1=b=838pR8>k;<42>06c3-99o7<m2:p1=e=838pR8>l;<42>06d3-99o7<m3:p1=d=838pR8>m;<42>06e3-99o7<m5:p1=g=838pR8>=;<42>0653-99o7<m6:p1=6=838pR9h8;<42>1`03-99o7<m7:p123=838pR9kl;<42>1cd3-99o7<m8:p1`g=838pR8;i;<42>03a3-99o7<m9:p1a`=838pR8;;;<42>0333-99o7<ma:p1a2=838pR8:6;<42>02>3-99o7<mb:p1f?=838pR8=j;<42>05b3-99o7<mc:p1gc=838pR8=<;<42>0543-99o7<md:p1g5=838pR8<7;<42>04?3-99o7<me:p1d>=838pR8?k;<42>07c3-99o7<l0:p1<b=838pR8?=;<42>0753-99o7<l1:p1<4=838pR9km;<42>1ce3-99o7<l2:p13g=838pR9kn;<42>1cf3-99o7<l3:~j=5d2909wE==d:m<6b=838pD><k;|l;7`<72;qC??j4}o:0b?6=:rB8>i5rn963>5<5sA99h6sa85394?4|@:8o7p`74383>7}O;;n0qc6;3;296~N4:m1vb5:;:181M55l2we49;50;0xL64c3td38;4?:3yK77b<ug2?;7>52zJ06a=zf1>36=4={I11`>{i0=31<7<tH20g?xh?<h0;6?uG33f8yk>3j3:1>vF<2e9~j=2d2909wE==d:m<1b=838pD><k;|l;0`<72;qC??j4}o:7b?6=:rB8>i5rn973>5<5sA99h6sa84394?4|@:8o7p`75383>7}O;;n0qc6:3;296~N4:m1vb5;;:181M55l2we48;50;0xL64c3td39;4?:3yK77b<ug2>;7>52zJ06a=zf1?36=4={I11`>{i0<31<7<tH20g?xh?=h0;6?uG33f8yk>2j3:1>vF<2e9~j=3d2909wE==d:m<0b=838pD><k;|l;1`<72;qC??j4}o:6b?6=:rB8>i5rn943>5<5sA99h6sa87394?4|@:8o7p`76383>7}O;;n0qc693;296~N4:m1vb58;:181M55l2we4;;50;0xL64c3td3:;4?:3yK77b<ug2=;7>52zJ06a=zf1<36=4={I11`>{i0?31<7<tH20g?xh?>h0;6?uG33f8yk>1j3:1>vF<2e9~j=0d2909wE==d:m<3b=838pD><k;|l;2`<72;qC??j4}o:5b?6=:rB8>i5rn953>5<5sA99h6sa86394?4|@:8o7p`77383>7}O;;n0qc683;296~N4:m1vb59;:181M55l2we4:;50;0xL64c3td3;;4?:3yK77b<ug2<;7>52zJ06a=zf1=36=4={I11`>{i0>31<7<tH20g?xh??h0;6?uG33f8yk>0j3:1>vF<2e9~j=1d2909wE==d:m<2b=838pD><k;|l;3`<72;qC??j4}o:4b?6=:rB8>i5rn9:3>5<5sA99h6sa89394?4|@:8o7p`78383>7}O;;n0qc673;296~N4:m1vb56;:181M55l2we45;50;0xL64c3td34;4?:3yK77b<ug23;7>52zJ06a=zf1236=4={I11`>{i0131<7<tH20g?xh?0h0;6?uG33f8yk>?j3:1>vF<2e9~j=>d2909wE==d:m<=b=838pD><k;|l;<`<72;qC??j4}o:;b?6=:rB8>i5rn9;3>5<5sA99h6sa88394?4|@:8o7p`79383>7}O;;n0qc663;296~N4:m1vb57;:181M55l2we44;50;0xL64c3td35;4?:3yK77b<ug22;7>52zJ06a=zf1336=4={I11`>{i0031<7<tH20g?xh?1h0;6?uG33f8yk>>j3:1>vF<2e9~j=?d2909wE==d:m<<b=838pD><k;|l;=`<72;qC??j4}o::b?6=:rB8>i5rn9c3>5<5sA99h6sa8`394?4|@:8o7p`7a383>7}O;;n0qc6n3;296~N4:m1vb5o;:181M55l2we4l;50;0xL64c3td3m;4?:3yK77b<ug2j;7>52zJ06a=zf1k36=4={I11`>{i0h31<7<tH20g?xh?ih0;6?uG33f8yk>fj3:1>vF<2e9~j=gd2909wE==d:m<db=838pD><k;|l;e`<72;qC??j4}o:bb?6=:rB8>i5rn9`3>5<5sA99h6sa8c394?4|@:8o7p`7b383>7}O;;n0qc6m3;296~N4:m1vb5l;:181M55l2we4o;50;0xL64c3td3n;4?:3yK77b<ug2i;7>52zJ06a=zf1h36=4={I11`>{i0k31<7<tH20g?xh?jh0;6?uG33f8yk>ej3:1>vF<2e9~j=dd2909wE==d:m<gb=838pD><k;|l;f`<72;qC??j4}o:ab?6=:rB8>i5rn9a3>5<5sA99h6sa8b394?4|@:8o7p`7c383>7}O;;n0qc6l3;296~N4:m1vb5m;:181M55l2we4n;50;0xL64c3td3o;4?:3yK77b<ug2h;7>52zJ06a=zf1i36=4={I11`>{i0j31<7<tH20g?xh?kh0;6?uG33f8yk>dj3:1>vF<2e9~j=ed2909wE==d:m<fb=838pD><k;|l;g`<72;qC??j4}o:`b?6=:rB8>i5rn9f3>5<5sA99h6sa8e394?4|@:8o7p`7d383>7}O;;n0qc6k3;296~N4:m1vb5j;:181M55l2we4i;50;0xL64c3td3h;4?:3yK77b<ug2o;7>52zJ06a=zf1n36=4={I11`>{i0m31<7<tH20g?xh?lh0;6?uG33f8yk>cj3:1>vF<2e9~j=bd2909wE==d:m<ab=838pD><k;|l;``<72;qC??j4}o:gb?6=:rB8>i5rn9g3>5<5sA99h6sa8d394?4|@:8o7p`7e383>7}O;;n0qc6j3;296~N4:m1vb5k;:181M55l2we4h;50;0xL64c3td3i;4?:3yK77b<ug2n;7>52zJ06a=zf1o36=4={I11`>{i0l31<7<tH20g?xh?mh0;6?uG33f8yk>bj3:1>vF<2e9~j=cd2909wE==d:m<`b=838pD><k;|l;a`<72;qC??j4}o:fb?6=:rB8>i5rn9d3>5<5sA99h6sa8g394?4|@:8o7p`7f383>7}O;;n0qc6i3;296~N4:m1vb5h;:181M55l2we4k;50;0xL64c3td3j;4?:3yK77b<ug2m;7>52zJ06a=zf1l36=4={I11`>{i0o31<7<tH20g?xh?nh0;6?uG33f8yk>aj3:1>vF<2e9~j=`d2909wE==d:m<cb=838pD><k;|l;b`<72;qC??j4}o:eb?6=:rB8>i5rn823>5<5sA99h6sa91394?4|@:8o7p`60383>7}O;;n0qc7?3;296~N4:m1vb4>;:181M55l2we5=;50;0xL64c3td2<;4?:3yK77b<ug3;;7>52zJ06a=zf0:36=4={I11`>{i1931<7<tH20g?xh>8h0;6?uG33f8yk?7j3:1>vF<2e9~j<6d2909wE==d:m=5b=838pD><k;|l:4`<72;qC??j4}o;3b?6=:rB8>i5rn833>5<5sA99h6sa90394?4|@:8o7p`61383>7}O;;n0qc7>3;296~N4:m1vb4?;:181M55l2we5<;50;0xL64c3td2=;4?:3yK77b<ug3:;7>52zJ06a=zf0;36=4={I11`>{i1831<7<tH20g?xh>9h0;6?uG33f8yk?6j3:1>vF<2e9~j<7d2909wE==d:m=4b=838pD><k;|l:5`<72;qC??j4}o;2b?6=:rB8>i5rn803>5<5sA99h6sa93394?4|@:8o7p`62383>7}O;;n0qc7=3;296~N4:m1vb4<;:181M55l2we5?;50;0xL64c3td2>;4?:3yK77b<ug39;7>52zJ06a=zf0836=4={I11`>{i1;31<7<tH20g?xh>:h0;6?uG33f8yk?5j3:1>vF<2e9~j<4d2909wE==d:m=7b=838pD><k;|l:6`<72;qC??j4}o;1b?6=:rB8>i5rn813>5<5sA99h6sa92394?4|@:8o7p`63383>7}O;;n0qc7<3;296~N4:m1vb4=;:181M55l2we5>;50;0xL64c3td2?;4?:3yK77b<ug38;7>52zJ06a=zf0936=4={I11`>{i1:31<7<tH20g?xh>;h0;6?uG33f8yk?4j3:1>vF<2e9~j<5d2909wE==d:m=6b=838pD><k;|l:7`<72;qC??j4}o;0b?6=:rB8>i5rn863>5<5sA99h6sa95394?4|@:8o7p`64383>7}O;;n0qc7;3;296~N4:m1vb4:;:181M55l2we59;50;0xL64c3td28;4?:3yK77b<ug3?;7>52zJ06a=zf0>36=4={I11`>{i1=31<7<tH20g?xh><h0;6?uG33f8yk?3j3:1>vF<2e9~j<2d2909wE==d:m=1b=838pD><k;|l:0`<72;qC??j4}o;7b?6=:rB8>i5rn873>5<5sA99h6sa94394?4|@:8o7p`65383>7}O;;n0qc7:3;296~N4:m1vb4;;:181M55l2we58;50;0xL64c3td29;4?:3yK77b<ug3>;7>52zJ06a=zf0?36=4={I11`>{i1<31<7<tH20g?xh>=h0;6?uG33f8yk?2j3:1>vF<2e9~j<3d2909wE==d:m=0b=838pD><k;|l:1`<72;qC??j4}o;6b?6=:rB8>i5rn843>5<5sA99h6sa97394?4|@:8o7p`66383>7}O;;n0qc793;296~N4:m1vb48;:181M55l2we5;;50;0xL64c3td2:;4?:3yK77b<ug3=;7>52zJ06a=zf0<36=4={I11`>{i1?31<7<tH20g?xh>>h0;6?uG33f8yk?1j3:1>vF<2e9~j<0d2909wE==d:m=3b=838pD><k;|l:2`<72;qC??j4}o;5b?6=:rB8>i5rn853>5<5sA99h6sa96394?4|@:8o7p`67383>7}O;;n0qc783;296~N4:m1vb49;:181M55l2we5:;50;0xL64c3td2;;4?:3yK77b<ug3<;7>52zJ06a=zf0=36=4={I11`>{i1>31<7<tH20g?xh>?h0;6?uG33f8yk?0j3:1>vF<2e9~j<1d2909wE==d:m=2b=838pD><k;|l:3`<72;qC??j4}o;4b?6=:rB8>i5rn8:3>5<5sA99h6sa99394?4|@:8o7p`68383>7}O;;n0qc773;296~N4:m1vb46;:181M55l2we55;50;0xL64c3td24;4?:3yK77b<ug33;7>52zJ06a=zf0236=4={I11`>{i1131<7<tH20g?xh>0h0;6?uG33f8yk??j3:1>vF<2e9~j<>d2909wE==d:m==b=838pD><k;|l:<`<72;qC??j4}o;;b?6=:rB8>i5rn8;3>5<5sA99h6sa98394?4|@:8o7p`69383>7}O;;n0qc763;296~N4:m1vb47;:181M55l2we54;50;0xL64c3td25;4?:3yK77b<ug32;7>52zJ06a=zf?nm6=4>{I11`>{zutJKOvoi5;;2136e1<wKLOu?}ABSxFG
/openrisc/trunk/orpsocv2/boards/xilinx/ml501/syn/ml501_xst.tpl
0,0 → 1,16
 
# XST Script for ORPSoCv2 synthesis
 
run
-ifn $BOARD.prj
-ifmt mixed
-top $BOARD
-ofn $BOARD.ngc
-ofmt NGC
-p $PART
-opt_mode Speed
-opt_level 2
-vlgincdir {../rtl $RTL_COMPONENT_PATHS }
-uc $BOARD.xcf
 
 
/openrisc/trunk/orpsocv2/boards/xilinx/ml501/syn/timescale.v
0,0 → 1,2
// Some modules include this, but i'd rather not put bench dirs in the synthesis scripts
`timescale 1ns/1ns
/openrisc/trunk/orpsocv2/boards/xilinx/ml501/syn/Makefile
0,0 → 1,98
#
# ORPSoC on ML501 Synthesis Makefile
#
# Only uses XST currently. run "make ml501.ngc"
#
 
# Include file for tools, etc
include ../../../tools.inc
 
BOARD=ml501
PART=xc5vlx50-ff676-1
 
# Paths in rtl/verilog/components that we're including in the system
MODULES=or1200r2 or1k_startup or1k_top tap debug_if wb_conbus uart16550 ram_wb ethernet
 
# A list of parts of names of files to be excluded from the automatic file list generation
EXCLUDE=or1200_dpram or1200_fpu
 
# When cleaning - files not to delete
FILES_TO_KEEP=$(BOARD).xcf $(BOARD)_xst.tpl ml501_ddr2_wb_if_cache.ngc timescale.v Makefile
 
# Relative path to the rtl, sim, sw, etc. directories
ORPSOC_ROOT=../../../..
CUR_DIR=$(shell pwd)
 
# Path from the root to the verilog components
RTL_COMPONENTS_PATH=rtl/verilog/components
 
# Make RTL_PATHS contain a list of paths to the RTL dirs for the modules
RTL_PATHS=$(shell for module in $(MODULES); do echo $(ORPSOC_ROOT)/$(RTL_COMPONENTS_PATH)/$$module; done)
 
EXCLUDE_LIST_E=$(shell for exclude in $(EXCLUDE); do echo "-e $$exclude"; done)
 
# Get a list of the verilog source files themselves
VERILOG_SRC=$(shell for path in $(RTL_PATHS); do ls $$path/*.v | grep -v $(EXCLUDE_LIST_E); done)
# Add the source files from the board's RTL dir
VERILOG_SRC += $(shell ls ../rtl/*.v)
VERILOG_SRC += $(shell ls ../rtl/ddr2_mig/*.v)
 
XST_PRJ_FILE_SRC_DECLARE=verilog work
XILINX_FLAGS=-intstyle silent
XILINX_XST_FLAGS += -power NO -glob_opt AllClockNets -write_timing_constraints NO -cross_clock_analysis NO -slice_utilization_ratio 100 -bram_utilization_ratio 100 -dsp_utilization_ratio 100 -safe_implementation No -fsm_style lut -ram_extract Yes -ram_style Auto -rom_extract Yes -rom_style Auto -auto_bram_packing NO -mux_extract YES -mux_style Auto -decoder_extract YES -priority_extract YES -shreg_extract YES -shift_extract YES -xor_collapse YES -resource_sharing YES -async_to_sync NO -use_dsp48 auto -iobuf YES -max_fanout 100000 -bufg 32 -register_duplication YES -equivalent_register_removal YES -register_balancing No -slice_packing YES -optimize_primitives NO -use_clock_enable Auto -use_sync_set Auto -use_sync_reset Auto -iob Auto -slice_utilization_ratio_maxmargin 5
 
 
 
BOOT_SW=boot
BOOT_SW_DIR=$(CUR_DIR)/../sw/$(BOOT_SW)
 
$(BOOT_SW).vmem: $(BOOT_SW_DIR)/$(BOOT_SW).vmem
if [ ! -e sram.vmem ]; then ln -s $? sram.vmem; fi
# Force this to happen each time
.PHONY: $(BOOT_SW_DIR)/$(BOOT_SW).vmem
$(BOOT_SW_DIR)/$(BOOT_SW).vmem:
$(MAKE) -C $(BOOT_SW_DIR) clean $(BOOT_SW) SYNTHESIS=1
 
# Generate the .xst file from the template, .tpl
# Substitute in the include paths, board name and part
%.xst: %_xst.tpl Makefile
@echo; echo "\t#### Generating Xilinx XST file ####";
@sed < $< > $@ \
-e s!\$$RTL_COMPONENT_PATHS!"$(RTL_PATHS)"! \
-e s!\$$BOARD!"$(BOARD)"! \
-e s!\$$PART!"$(PART)"!
@echo
 
# Generate Xilinx project (.prj) file
%.prj: Makefile
@echo; echo "\t#### Generating Xilinx PRJ file ####";
@if [ -e $@ ]; then rm -f $@; fi
@for file in $(VERILOG_SRC); do \
echo $(XST_PRJ_FILE_SRC_DECLARE) $$file >> $@ ; \
done
@echo
 
%.ngc: %.prj %.xst %.xcf ../rtl/%.v $(BOOT_SW).vmem
@echo; echo "\t#### Running XST ####";
@(. $(XILINX_SETTINGS_SCRIPT) ; xst -ifn $*.xst $(XILINX_FLAGS) $(XST_FLAGS) )
@echo
 
%.v: %.ngc
@echo; echo "\t#### Generating verilog netlist ####";
@(. $(XILINX_SETTINGS_SCRIPT) ; \
netgen -sim -aka -dir . -ofmt verilog $*.ngc -w $@ )
 
FILES_TO_KEEP_E=$(shell for file in $(FILES_TO_KEEP); do echo "-e $$file"; done)
FILES_TO_DEL=$(shell ls | grep -v $(FILES_TO_KEEP_E))
 
clean-test:
@echo Would remove: $(FILES_TO_DEL)
 
clean-sw:
@$(MAKE) -C $(BOOT_SW_DIR)
clean: clean-sw
@rm -rfv $(FILES_TO_DEL)
 
 
 
.PRECIOUS : %.ngc %.prj %.xst
/openrisc/trunk/orpsocv2/boards/xilinx/ml501/syn/ml501.xcf
0,0 → 1,34
# Xilinx synthesis constraints file for ml501
#
# Not much here, XST is smart enough to determine clocks through DCMs
#
# TODO: Potentially use the other XTAL for DDR RAM clocking
#
 
# 200MHz diff. XTAL used as main system clock
NET "sys_clk_in_p" TNM_NET = "sys_clk_in_p_grp";
NET "sys_clk_in_n" TNM_NET = "sys_clk_in_n_grp";
TIMESPEC "TS_sys_clk_in_p_grp" = PERIOD "sys_clk_in_p_grp" 5 ns HIGH 50 %;
TIMESPEC "TS_sys_clk_in_n_grp" = PERIOD "sys_clk_in_n_grp" 5 ns LOW 50 %;
 
# 100 MHz user clock
NET "sys_clk_in" TNM_NET = "sys_clk_in_grp";
TIMESPEC "TS_sys_clk_in" = PERIOD "sys_clk_in_grp" 10 ns HIGH 50%;
 
 
# Ignore the debounce reset logic
NET reset_debounce0/debounce_count* TIG;
 
# SSRAM multicylce constraints:
 
# Define the two clock domains as timespecs
#NET dcm0_clkdv TNM_NET="wb_clk";
#TIMESPEC "TS_wb_clk" = PERIOD "wb_clk" 20 ns HIGH 10;
#NET dcm0_clk0 TNM_NET = "ssram_clk200";
#TIMESPEC "TS_ssram_clk200" = PERIOD "ssram_clk200" "TS_wb_clk" / 4;
 
# Now define their relationship - logic should be configured so that there's
# 1 WB cycle at all times before anything is sampled across domains
#TIMESPEC "TS_wb_clk_ssram_clk200" = from "wb_clk" TO "ssram_clk200" 15 ns;
#TIMESPEC "TS_ssram_clk200_wb_clk" = from "ssram_clk200" TO "wb_clk" 20 ns;
 

powered by: WebSVN 2.1.0

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