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/run/Makefile
0,0 → 1,75
include ../bin/Makefile |
/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; |
|