Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
X
x393
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Commits
Open sidebar
Elphel
x393
Commits
cbbd4ed1
Commit
cbbd4ed1
authored
Feb 13, 2015
by
Andrey Filippov
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
split top level test fixture file into separate includes with tasks
parent
38d73a7b
Changes
9
Show whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
1131 additions
and
1048 deletions
+1131
-1048
x393_tasks01.vh
includes/x393_tasks01.vh
+9
-1
x393_tasks_mcntrl_buffers.vh
includes/x393_tasks_mcntrl_buffers.vh
+121
-0
x393_tasks_mcntrl_en_dis_priority.vh
includes/x393_tasks_mcntrl_en_dis_priority.vh
+70
-0
x393_tasks_mcntrl_timing.vh
includes/x393_tasks_mcntrl_timing.vh
+200
-0
x393_tasks_pio_sequences.vh
includes/x393_tasks_pio_sequences.vh
+543
-0
x393_tasks_ps_pio.vh
includes/x393_tasks_ps_pio.vh
+59
-0
x393_tasks_status.vh
includes/x393_tasks_status.vh
+112
-0
x393_testbench01.sav
x393_testbench01.sav
+10
-6
x393_testbench01.tf
x393_testbench01.tf
+7
-1041
No files found.
includes/x393_tasks01.vh
View file @
cbbd4ed1
...
@@ -2,7 +2,7 @@
...
@@ -2,7 +2,7 @@
* File: x393_tasks01.vh
* File: x393_tasks01.vh
* Date:2015-02-07
* Date:2015-02-07
* Author: andrey
* Author: andrey
* Description: Simulation tasks for the x393
* Description: Simulation tasks for the x393
(low level)
*
*
* Copyright (c) 2015 <set up in Preferences-Verilog/VHDL Editor-Templates> .
* Copyright (c) 2015 <set up in Preferences-Verilog/VHDL Editor-Templates> .
* x393_tasks01.vh is free software; you can redistribute it and/or modify
* x393_tasks01.vh is free software; you can redistribute it and/or modify
...
@@ -20,6 +20,14 @@
...
@@ -20,6 +20,14 @@
*******************************************************************************/
*******************************************************************************/
// Low-level tasks
// Low-level tasks
// alternative way to check for empty read queue (without a separate counter)
// alternative way to check for empty read queue (without a separate counter)
task write_contol_register;
input [29:0] reg_addr;
input [31:0] data;
begin
axi_write_single_w(CONTROL_ADDR+reg_addr, data);
end
endtask
task wait_read_queue_empty;
task wait_read_queue_empty;
begin
begin
wait (~rvalid && rready && (rid==LAST_ARID)); // nothing left in read queue?
wait (~rvalid && rready && (rid==LAST_ARID)); // nothing left in read queue?
...
...
includes/x393_tasks_mcntrl_buffers.vh
0 → 100644
View file @
cbbd4ed1
/*******************************************************************************
* File: x393_tasks_mcntrl_buffers.vh
* Date:2015-02-07
* Author: andrey
* Description: Simulation tasks for software reading/writing (with test patterns)
* of the block buffers.
*
* Copyright (c) 2015 <set up in Preferences-Verilog/VHDL Editor-Templates> .
* x393_tasks_mcntrl_buffers.vh is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* x393_tasks_mcntrl_buffers.vh 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/> .
*******************************************************************************/
//MCONTR_BUF1_WR_ADDR
task write_block_buf_chn; // S uppressThisWarning VEditor : may be unused
input integer chn; // buffer channel
input [1:0] page;
input integer num_words; // number of words to write (will be rounded up to multiple of 16)
reg [29:0] start_addr;
begin
case (chn)
1: start_addr=MCONTR_BUF1_WR_ADDR + (page << 8);
3: start_addr=MCONTR_BUF3_WR_ADDR + (page << 8);
default: begin
$display("**** ERROR: Invalid channel for write buffer = %d @%t", chn, $time);
start_addr = MCONTR_BUF1_WR_ADDR+ (page << 8);
end
endcase
write_block_buf (start_addr, num_words);
end
endtask
task write_block_buf;
input [29:0] start_word_address;
input integer num_words; // number of words to write (will be rounded up to multiple of 16)
integer i, j;
begin
$display("**** write_block_buf @%t", $time);
for (i = 0; i < num_words; i = i + 16) begin
axi_write_addr_data(
i, // id
{start_word_address,2'b0}+( i << 2),
// (MCONTR_BUF1_WR_ADDR + (page <<8)+ i) << 2, // addr
i | (((i + 7) & 'hff) << 8) | (((i + 23) & 'hff) << 16) | (((i + 31) & 'hff) << 24),
4'hf, // len
1, // burst type - increment
1'b1, // data_en
4'hf, // wstrb
1'b0 // last
);
$display("+Write block data (addr:data): 0x%x:0x%08x @%t", i, i | (((i + 7) & 'hff) << 8) | (((i + 23) & 'hff) << 16) | (((i + 31) & 'hff) << 24), $time);
for (j = 1; j < 16; j = j + 1) begin
axi_write_data(
i, // id
(i + j) | ((((i + j) + 7) & 'hff) << 8) | ((((i + j) + 23) & 'hff) << 16) | ((((i + j) + 31) & 'hff) << 24),
4'hf, // wstrb
(1 == 15) ? 1 : 0 // last
);
$display(" Write block data (addr:data): 0x%08x:0x%x @%t", (i + j),
(i + j) | ((((i + j) + 7) & 'hff) << 8) | ((((i + j) + 23) & 'hff) << 16) | ((((i + j) + 31) & 'hff) << 24), $time);
end
end
end
endtask
// read memory
task read_block_buf_chn; // S uppressThisWarning VEditor : may be unused
input integer chn; // buffer channel
input [1:0] page;
input integer num_read; // number of words to read (will be rounded up to multiple of 16)
input wait_done;
reg [29:0] start_addr;
begin
case (chn)
0: start_addr=MCONTR_BUF0_RD_ADDR + (page << 8);
2: start_addr=MCONTR_BUF2_RD_ADDR + (page << 8);
4: start_addr=MCONTR_BUF4_RD_ADDR + (page << 8);
default: begin
$display("**** ERROR: Invalid channel for read buffer = %d @%t", chn, $time);
start_addr = 30'b0+ (page << 8);
end
endcase
read_block_buf (start_addr, num_read, wait_done);
end
endtask
task read_block_buf;
input [29:0] start_word_address;
input integer num_read; // number of words to read (will be rounded up to multiple of 16)
input wait_done;
integer i; //,j;
begin
wait (~rstb);
SIMUL_AXI_FULL<=1'b0;
$display("**** read_block_buf @%t", $time);
axi_set_rd_lag(0);
for (i = 0; i < num_read; i = i + 16) begin
wait(arready);
// $display ("read_block_buf (0x%x) @%t",i,$time);
axi_read_addr(
i, // id
{start_word_address,2'b0}+( i << 2), // addr
4'hf, // len
1 // burst type - increment
);
end
if (wait_done) begin
// wait (AXI_RD_EMPTY);
wait_read_queue_empty;
end
end
endtask
includes/x393_tasks_mcntrl_en_dis_priority.vh
0 → 100644
View file @
cbbd4ed1
/*******************************************************************************
* File: x393_tasks_mcntrl_en_dis_priority.vh
* Date:2015-02-07
* Author: andrey
* Description: Simulation tasks for software reading/writing (with test patterns)
* of the block buffers.
*
* Copyright (c) 2015 <set up in Preferences-Verilog/VHDL Editor-Templates> .
* x393_tasks_mcntrl_en_dis_priority.vh is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* x393_tasks_mcntrl_en_dis_priority.vh 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/> .
*******************************************************************************/
task enable_cmda;
input en;
begin
write_contol_register(MCONTR_PHY_0BIT_ADDR + MCONTR_PHY_0BIT_CMDA_EN + en, 0);
end
endtask
task enable_cke;
input en;
begin
write_contol_register(MCONTR_PHY_0BIT_ADDR + MCONTR_PHY_0BIT_CKE_EN + en, 0);
end
endtask
task activate_sdrst;
input en;
begin
write_contol_register(MCONTR_PHY_0BIT_ADDR + MCONTR_PHY_0BIT_SDRST_ACT + en, 0);
end
endtask
task enable_refresh;
input en;
begin
write_contol_register(MCONTR_TOP_0BIT_ADDR + MCONTR_TOP_0BIT_REFRESH_EN + en, 0);
end
endtask
task enable_memcntrl;
input en;
begin
write_contol_register(MCONTR_TOP_0BIT_ADDR + MCONTR_TOP_0BIT_MCONTR_EN + en, 0);
end
endtask
task enable_memcntrl_channels;
input [15:0] chnen; // bit-per-channel, 1 - enable;
begin
write_contol_register(MCONTR_TOP_16BIT_ADDR + MCONTR_TOP_16BIT_CHN_EN, {16'b0,chnen});
end
endtask
task configure_channel_priority;
input [ 3:0] chn;
input [15:0] priority; // (higher is more important)
begin
write_contol_register(MCONTR_ARBIT_ADDR + chn, {16'b0,priority});
end
endtask
includes/x393_tasks_mcntrl_timing.vh
0 → 100644
View file @
cbbd4ed1
/*******************************************************************************
* File: x393_tasks_mcntrl_timing.vh
* Date:2015-02-07
* Author: andrey
* Description: Simulation tasks for programming I/O delays and other timing
* parameters in the memory controller
*
* Copyright (c) 2015 <set up in Preferences-Verilog/VHDL Editor-Templates> .
* x393_tasks_mcntrl_timing.vh is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* x393_tasks_mcntrl_timing.vh 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/> .
*******************************************************************************/
task axi_set_same_delays; //SuppressThisWarning VEditor : may be unused
input [7:0] dq_idelay;
input [7:0] dq_odelay;
input [7:0] dqs_idelay;
input [7:0] dqs_odelay;
input [7:0] dm_odelay;
input [7:0] cmda_odelay;
begin
$display("SET DELAYS(0x%x,0x%x,0x%x,0x%x,0x%x,0x%x) @ %t",
dq_idelay,dq_odelay,dqs_idelay,dqs_odelay,dm_odelay,cmda_odelay,$time);
axi_set_dq_idelay(dq_idelay);
axi_set_dq_odelay(dq_odelay);
axi_set_dqs_idelay(dqs_idelay);
axi_set_dqs_odelay(dqs_odelay);
axi_set_dm_odelay(dm_odelay);
axi_set_cmda_odelay(cmda_odelay);
end
endtask
task axi_set_dqs_odelay_nominal; //SuppressThisWarning VEditor : may be unused
begin
// axi_set_dqs_idelay(
write_contol_register(LD_DLY_LANE0_ODELAY + 8, (DLY_LANE0_ODELAY >> (8<<3)) & 32'hff);
write_contol_register(LD_DLY_LANE1_ODELAY + 8, (DLY_LANE1_ODELAY >> (8<<3)) & 32'hff);
write_contol_register(DLY_SET,0);
end
endtask
task axi_set_dqs_idelay_nominal; //SuppressThisWarning VEditor : may be unused
begin
// axi_set_dqs_idelay(
write_contol_register(LD_DLY_LANE0_IDELAY + 8, (DLY_LANE0_IDELAY >> (8<<3)) & 32'hff);
write_contol_register(LD_DLY_LANE1_IDELAY + 8, (DLY_LANE1_IDELAY >> (8<<3)) & 32'hff);
write_contol_register(DLY_SET,0);
end
endtask
task axi_set_dqs_idelay_wlv; //SuppressThisWarning VEditor : may be unused
begin
write_contol_register(LD_DLY_LANE0_IDELAY + 8, DLY_LANE0_DQS_WLV_IDELAY);
write_contol_register(LD_DLY_LANE1_IDELAY + 8, DLY_LANE1_DQS_WLV_IDELAY);
write_contol_register(DLY_SET,0);
end
endtask
task axi_set_delays; // set all individual delays
integer i;
begin
for (i=0;i<10;i=i+1) begin
write_contol_register(LD_DLY_LANE0_ODELAY + i, (DLY_LANE0_ODELAY >> (i<<3)) & 32'hff);
end
for (i=0;i<9;i=i+1) begin
write_contol_register(LD_DLY_LANE0_IDELAY + i, (DLY_LANE0_IDELAY >> (i<<3)) & 32'hff);
end
for (i=0;i<10;i=i+1) begin
write_contol_register(LD_DLY_LANE1_ODELAY + i, (DLY_LANE1_ODELAY >> (i<<3)) & 32'hff);
end
for (i=0;i<9;i=i+1) begin
write_contol_register(LD_DLY_LANE1_IDELAY + i, (DLY_LANE1_IDELAY >> (i<<3)) & 32'hff);
end
for (i=0;i<32;i=i+1) begin
write_contol_register(LD_DLY_CMDA + i, (DLY_CMDA >> (i<<3)) & 32'hff);
end
// write_contol_register(DLY_SET,0);
axi_set_phase(DLY_PHASE); // also sets all delays
end
endtask
task axi_set_dq_idelay; // sets same delay to all dq idelay
input [7:0] delay;
begin
$display("SET DQ IDELAY=0x%x @ %t",delay,$time);
axi_set_multiple_delays(LD_DLY_LANE0_IDELAY, 8, delay);
axi_set_multiple_delays(LD_DLY_LANE1_IDELAY, 8, delay);
write_contol_register(DLY_SET,0); // set all delays
end
endtask
task axi_set_dq_odelay;
input [7:0] delay;
begin
$display("SET DQ ODELAY=0x%x @ %t",delay,$time);
axi_set_multiple_delays(LD_DLY_LANE0_ODELAY, 8, delay);
axi_set_multiple_delays(LD_DLY_LANE1_ODELAY, 8, delay);
write_contol_register(DLY_SET,0); // set all delays
end
endtask
task axi_set_dqs_idelay;
input [7:0] delay;
begin
$display("SET DQS IDELAY=0x%x @ %t",delay,$time);
axi_set_multiple_delays(LD_DLY_LANE0_IDELAY + 8, 1, delay);
axi_set_multiple_delays(LD_DLY_LANE1_IDELAY + 8, 1, delay);
write_contol_register(DLY_SET,0); // set all delays
end
endtask
task axi_set_dqs_odelay;
input [7:0] delay;
begin
$display("SET DQS ODELAY=0x%x @ %t",delay,$time);
axi_set_multiple_delays(LD_DLY_LANE0_ODELAY + 8, 1, delay);
axi_set_multiple_delays(LD_DLY_LANE1_ODELAY + 8, 1, delay);
write_contol_register(DLY_SET,0); // set all delays
end
endtask
task axi_set_dm_odelay;
input [7:0] delay;
begin
$display("SET DQM IDELAY=0x%x @ %t",delay,$time);
axi_set_multiple_delays(LD_DLY_LANE0_ODELAY + 9, 1, delay);
axi_set_multiple_delays(LD_DLY_LANE1_ODELAY + 9, 1, delay);
write_contol_register(DLY_SET,0); // set all delays
end
endtask
task axi_set_cmda_odelay;
input [7:0] delay;
begin
$display("SET COMMAND and ADDRESS ODELAY=0x%x @ %t",delay,$time);
axi_set_multiple_delays(LD_DLY_CMDA, 32, delay);
write_contol_register(DLY_SET,0); // set all delays
end
endtask
task axi_set_multiple_delays;
input [29:0] reg_addr;
input integer number;
input [7:0] delay;
integer i;
begin
for (i=0;i<number;i=i+1) begin
write_contol_register(reg_addr + i, {24'b0,delay}); // control regiter address
end
end
endtask
task axi_set_phase;
input [PHASE_WIDTH-1:0] phase;
begin
$display("SET CLOCK PHASE to 0x%x @ %t",phase,$time);
write_contol_register(LD_DLY_PHASE, {{(32-PHASE_WIDTH){1'b0}},phase}); // control regiter address
write_contol_register(DLY_SET,0);
target_phase <= phase;
end
endtask
task axi_set_wbuf_delay;
input [3:0] delay;
begin
$display("SET WBUF DELAY to 0x%x @ %t",delay,$time);
write_contol_register(MCONTR_PHY_16BIT_ADDR+MCONTR_PHY_16BIT_WBUF_DELAY, {28'h0, delay});
end
endtask
// set dq /dqs tristate on/off patterns
task axi_set_tristate_patterns;
begin
$display("SET TRISTATE PATTERNS @ %t",$time);
write_contol_register(MCONTR_PHY_16BIT_ADDR +MCONTR_PHY_16BIT_PATTERNS_TRI,
{16'h0, DQSTRI_LAST, DQSTRI_FIRST, DQTRI_LAST, DQTRI_FIRST});
end
endtask
task axi_set_dqs_dqm_patterns;
begin
$display("SET DQS+DQM PATTERNS @ %t",$time);
// set patterns for DM (always 0) and DQS - always the same (may try different for write lev.)
write_contol_register(MCONTR_PHY_16BIT_ADDR + MCONTR_PHY_16BIT_PATTERNS,
32'h0055);
end
endtask
includes/x393_tasks_pio_sequences.vh
0 → 100644
View file @
cbbd4ed1
/*******************************************************************************
* File: x393_tasks_pio_sequences.vh
* Date:2015-02-07
* Author: andrey
* Description: Simulation tasks for programming memory transaction
* sequences (controlles by PS)
*
* Copyright (c) 2015 <set up in Preferences-Verilog/VHDL Editor-Templates> .
* x393_tasks_pio_sequences.vh is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* x393_tasks_pio_sequences.vh 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/> .
*******************************************************************************/
task enable_reset_ps_pio; // control reset and enable of the PS PIO channel;
input en;
input rst;
begin
write_contol_register(MCNTRL_PS_ADDR + MCNTRL_PS_EN_RST, {30'b0,en,~rst});
end
endtask
task set_read_block;
input [ 2:0] ba;
input [14:0] ra;
input [ 9:0] ca;
reg [29:0] cmd_addr;
reg [31:0] data;
integer i;
begin
cmd_addr <= MCONTR_CMD_WR_ADDR + READ_BLOCK_OFFSET;
// activate
// addr bank RCW ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD NOP, B_RST
data <= func_encode_cmd( ra[14:0], ba[2:0], 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
@(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
// see if pause is needed . See when buffer read should be started - maybe before WR command
// skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
data <= func_encode_skip( 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
@(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
// first read
// read
// addr bank RCW ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD NOP, B_RST
data <= func_encode_cmd( {5'b0,ca[9:0]}, ba[2:0], 2, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0);
@(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
// nop
// skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
data <= func_encode_skip( 0, 0, ba[2:0], 0, 0, 1, 0, 0, 0, 1, 0, 0, 0);
@(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
//repeat remaining reads
for (i=1;i<64;i=i+1) begin
// read
// addr bank RCW ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD NOP, B_RST
data <= func_encode_cmd({5'b0,ca[9:0]}+(i<<3),ba[2:0],2, 0, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0);
@(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
end
// nop - all 3 below are the same? - just repeat?
// skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
data <= func_encode_skip( 0, 0, ba[2:0], 0, 0, 1, 0, 0, 0, 1, 1, 0, 0);
@(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
// nop
// skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
data <= func_encode_skip( 0, 0, ba[2:0], 0, 0, 1, 0, 0, 0, 1, 1, 0, 0);
@(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
// nop
// skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
data <= func_encode_skip( 0, 0, ba[2:0], 0, 0, 1, 0, 0, 0, 1, 0, 0, 0);
@(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
// tRTP = 4*tCK is already satisfied, no skip here
// precharge, end of a page (B_RST)
// addr bank RCW ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD NOP, B_RST
data <= func_encode_cmd( ra[14:0], ba[2:0], 5, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1);
@(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
// skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
data <= func_encode_skip( 2, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0);
@(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
// Turn off DCI, set DONE
// skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
data <= func_encode_skip( 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
@(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
end
endtask
task set_write_block;
input[2:0]ba;
input[14:0]ra;
input[9:0]ca;
reg[29:0] cmd_addr;
reg[31:0] data;
integer i;
begin
cmd_addr <= MCONTR_CMD_WR_ADDR + WRITE_BLOCK_OFFSET;
// activate
// addr bank RCW ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD NOP, B_RST
data <= func_encode_cmd( ra[14:0], ba[2:0], 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
@(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
// see if pause is needed . See when buffer read should be started - maybe before WR command
// skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
data <= func_encode_skip( 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0); // tRCD - 2 read bufs
@(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
// first write, 3 rd_buf
// write
// addr bank RCW ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD NOP, B_RST
data <= func_encode_cmd( {5'b0,ca[9:0]}, ba[2:0], 3, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0); // B_RD moved 1 cycle earlier
@(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
// nop 4-th rd_buf
// skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
// data <= func_encode_skip( 0, 0, ba[2:0], 1, 0, 1, 1, 1, 0, 1, 0, 1, 0);
data <= func_encode_skip( 0, 0, ba[2:0], 1, 0, 0, 1, 1, 0, 0, 0, 1, 0);
@(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
//repeat remaining writes
for (i = 1; i < 63; i = i + 1) begin
// write
// add bank RCW ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD NOP, B_RST
data <= func_encode_cmd( {5'b0,ca[9:0]}+(i<<3),ba[2:0],3, 1, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0);
@(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
end
// One last write pair w/o buffer
// add bank RCW ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD NOP, B_RST
data <= func_encode_cmd( {5'b0,ca[9:0]}+(63<<3),ba[2:0],3,1, 0, 1, 1, 1, 1, 0, 0, 0, 1, 0);
@(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
// nop
// skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
data <= func_encode_skip( 0, 0, ba[2:0], 1, 0, 0, 1, 1, 1, 0, 0, 0, 0);
@(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
// nop
// skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
data <= func_encode_skip( 0, 0, ba[2:0], 1, 0, 0, 1, 1, 1, 0, 0, 0, 1); // removed B_RD 1 cycle earlier
@(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
// nop
// skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
data <= func_encode_skip( 0, 0, ba[2:0], 1, 0, 0, 1, 1, 1, 0, 0, 0, 0);
@(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
// ODT off, it has latency
// skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
data <= func_encode_skip( 2, 0, ba[2:0], 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
@(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
// precharge, ODT off
// addr bank RCW ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD NOP, B_RST
data <= func_encode_cmd( ra[14:0], ba[2:0], 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
@(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
// skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
data <= func_encode_skip( 2, 0, ba[2:0], 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
@(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
// Finalize, set DONE
// skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
data <= func_encode_skip( 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
@(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
end
endtask
// Set MR3, read nrep*8 words, save to buffer (port0). No ACTIVATE/PRECHARGE are needed/allowed
task set_read_pattern;
input integer nrep;
// input [ 2:0] ba;
// input [14:0] ra;
// input [ 9:0] ca;
reg[29:0] cmd_addr;
reg[31:0] data;
reg[17:0] mr3_norm;
reg[17:0] mr3_patt;
integer i;
begin
cmd_addr <= MCONTR_CMD_WR_ADDR + READ_PATTERN_OFFSET;
mr3_norm <= ddr3_mr3(
1'h0, // mpr; // MPR mode: 0 - normal, 1 - dataflow from MPR
2'h0); // [1:0] mpr_rf; // MPR read function: 2'b00: predefined pattern 0101...
mr3_patt <= ddr3_mr3(
1'h1, // mpr; // MPR mode: 0 - normal, 1 - dataflow from MPR
2'h0); // [1:0] mpr_rf; // MPR read function: 2'b00: predefined pattern 0101...
@(posedge CLK);
// Set pattern mode
// addr bank RCW ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD NOP, B_RST
data <= func_encode_cmd(mr3_patt[14:0], mr3_patt[17:15], 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
@(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
// skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
data <= func_encode_skip( 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); // tMOD
@(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
// first read
// read
// addr bank RCW ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD NOP, B_RST
data <= func_encode_cmd( 0, 0, 2, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0);
@(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
// nop (combine with previous?)
// skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
data <= func_encode_skip( 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0);
@(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
//repeat remaining reads
for (i = 1; i < nrep; i = i + 1) begin
// addr bank RCW ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD NOP, B_RST
data <= func_encode_cmd( 0, 0, 2, 0, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0);
@(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
end
// nop - all 3 below are the same? - just repeat?
// skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
data <= func_encode_skip( 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0);
@(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
// nop
// skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
data <= func_encode_skip( 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0);
@(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
// nop
// skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
data <= func_encode_skip( 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0);
@(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
// nop, no write buffer - next page
// skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
data <= func_encode_skip( 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1);
@(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
// skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
data <= func_encode_skip( 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0);
@(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
// Turn off read pattern mode
// addr bank RCW ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD NOP, B_RST
data <= func_encode_cmd(mr3_norm[14:0], mr3_norm[17:15], 7, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0);
@(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
// tMOD (keep DCI enabled)
// skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
data <= func_encode_skip( 5, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0);
@(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
// Turn off DCI
// skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
data <= func_encode_skip( 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
@(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
// Finalize (set DONE)
data <= func_encode_skip( 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
@(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
end
endtask
task set_write_lev;
input[CMD_PAUSE_BITS-1:0]nrep;
reg[17:0] mr1_norm;
reg[17:0] mr1_wlev;
reg[29:0] cmd_addr;
reg[31:0] data;
reg[CMD_PAUSE_BITS-1:0] dqs_low_rpt;
reg[CMD_PAUSE_BITS-1:0] nrep_minus_1;
begin
dqs_low_rpt <= 8;
nrep_minus_1 <= nrep - 1;
mr1_norm <= ddr3_mr1(
1'h0, // qoff; // output enable: 0 - DQ, DQS operate in normal mode, 1 - DQ, DQS are disabled
1'h0, // tdqs; // termination data strobe (for x8 devices) 0 - disabled, 1 - enabled
3'h2, // [2:0] rtt; // on-die termination resistance: // 3'b010 - RZQ/2 (120 Ohm)
1'h0, // wlev; // write leveling
2'h0, // ods; // output drive strength: // 2'b00 - RZQ/6 - 40 Ohm
2'h0, // [1:0] al; // additive latency: 2'b00 - disabled (AL=0)
1'b0); // dll; // 0 - DLL enabled (normal), 1 - DLL disabled
mr1_wlev <= ddr3_mr1(
1'h0, // qoff; // output enable: 0 - DQ, DQS operate in normal mode, 1 - DQ, DQS are disabled
1'h0, // tdqs; // termination data strobe (for x8 devices) 0 - disabled, 1 - enabled
3'h2, // [2:0] rtt; // on-die termination resistance: // 3'b010 - RZQ/2 (120 Ohm)
1'h1, // wlev; // write leveling
2'h0, // ods; // output drive strength: // 2'b00 - RZQ/6 - 40 Ohm
2'h0, // [1:0] al; // additive latency: 2'b00 - disabled (AL=0)
1'b0); // dll; // 0 - DLL enabled (normal), 1 - DLL disabled
cmd_addr <= MCONTR_CMD_WR_ADDR + WRITELEV_OFFSET;
// Enter write leveling mode
@(posedge CLK)
// addr bank RCW ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD NOP, B_RST
data <= func_encode_cmd(mr1_wlev[14:0], mr1_wlev[17:15], 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
@(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
// skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
data <= func_encode_skip( 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); // tWLDQSEN=25tCK
@(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
// enable DQS output, keep it low (15 more tCK for the total of 40 tCK
// skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
data <= func_encode_skip(dqs_low_rpt, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0);
@(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
// Toggle DQS as needed for write leveling, write to buffer
// skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
data <= func_encode_skip(nrep_minus_1,0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0);
@(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
// continue toggling (5 times), but disable writing to buffer (used same wbuf latency as for read)
// skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
data <= func_encode_skip( 4, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0);
@(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
// Keep DCI (but not ODT) active ODT should be off befor MRS
// skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
data <= func_encode_skip( 2, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0);
@(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
// exit write leveling mode, ODT off, DCI off
// addr bank RCW ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD NOP, B_RST
data <= func_encode_cmd(mr1_norm[14:0], mr1_norm[17:15], 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
@(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
// skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
data <= func_encode_skip( 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); // tMOD
@(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
// Finalize. See if DONE can be combined with B_RST, if not - insert earlier
// skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
data <= func_encode_skip( 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1); // can DONE be combined with B_RST?
@(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
end
endtask
task set_refresh;
input[9:0]t_rfc; // =50 for tCK=2.5ns
input[7:0]t_refi; // 48/97 for normal, 8 - for simulation
reg[29:0] cmd_addr;
reg[31:0] data;
begin
cmd_addr <= MCONTR_CMD_WR_ADDR + REFRESH_OFFSET;
@(posedge CLK)
// addr bank RCW ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD NOP, B_RST
data <= func_encode_cmd( 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
@(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
// =50 tREFI=260 ns before next ACTIVATE or REFRESH, @2.5ns clock, @5ns cycle
// skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
data <= func_encode_skip( t_rfc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
@(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
// Ready for normal operation
// skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
data <= func_encode_skip( 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
@(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
// write_contol_register(DLY_SET,0);
write_contol_register(MCONTR_TOP_16BIT_ADDR + MCONTR_TOP_16BIT_REFRESH_ADDRESS, REFRESH_OFFSET);
write_contol_register(MCONTR_TOP_16BIT_ADDR + MCONTR_TOP_16BIT_REFRESH_PERIOD, {24'h0,t_refi});
// enable refresh - should it be done here?
// write_contol_register(MCONTR_PHY_0BIT_ADDR + MCONTR_TOP_0BIT_REFRESH_EN + 1, 0);
end
endtask
task set_mrs; // will also calibrate ZQ
input reset_dll;
reg[17:0] mr0;
reg[17:0] mr1;
reg[17:0] mr2;
reg[17:0] mr3;
reg[29:0] cmd_addr;
reg[31:0] data;
begin
mr0 <= ddr3_mr0(
1'h0, // pd; // precharge power down 0 - dll off (slow exit), 1 - dll on (fast exit)
3'h2, // [2:0] wr; // write recovery (encode ceil(tWR/tCK)) // 3'b010: 6
reset_dll, // dll_rst; // 1 - dll reset (self clearing bit)
4'h4, // [3:0] cl; // CAS latency: // 0100: 6 (time 15ns)
1'h0, // bt; // read burst type: 0 sequential (nibble), 1 - interleave
2'h0); // [1:0] bl; // burst length: // 2'b00 - fixed BL8
mr1 <= ddr3_mr1(
1'h0, // qoff; // output enable: 0 - DQ, DQS operate in normal mode, 1 - DQ, DQS are disabled
1'h0, // tdqs; // termination data strobe (for x8 devices) 0 - disabled, 1 - enabled
3'h2, // [2:0] rtt; // on-die termination resistance: // 3'b010 - RZQ/2 (120 Ohm)
1'h0, // wlev; // write leveling
2'h0, // ods; // output drive strength: // 2'b00 - RZQ/6 - 40 Ohm
2'h0, // [1:0] al; // additive latency: 2'b00 - disabled (AL=0)
1'b0); // dll; // 0 - DLL enabled (normal), 1 - DLL disabled
mr2 <= ddr3_mr2(
2'h0, // [1:0] rtt_wr; // Dynamic ODT : // 2'b00 - disabled, 2'b01 - RZQ/4 = 60 Ohm, 2'b10 - RZQ/2 = 120 Ohm
1'h0, // srt; // Self-refresh temperature 0 - normal (0-85C), 1 - extended (<=95C)
1'h0, // asr; // Auto self-refresh 0 - disabled (manual), 1 - enabled (auto)
3'h0); // [2:0] cwl; // CAS write latency:3'b000 5CK (tCK >= 2.5ns), 3'b001 6CK (1.875ns <= tCK < 2.5ns)
mr3 <= ddr3_mr3(
1'h0, // mpr; // MPR mode: 0 - normal, 1 - dataflow from MPR
2'h0); // [1:0] mpr_rf; // MPR read function: 2'b00: predefined pattern 0101...
cmd_addr <= MCONTR_CMD_WR_ADDR + INITIALIZE_OFFSET;
@(posedge CLK)
$display("mr0=0x%x", mr0);
$display("mr1=0x%x", mr1);
$display("mr2=0x%x", mr2);
$display("mr3=0x%x", mr3);
// addr bank RCW ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD NOP, B_RST
data <= func_encode_cmd(mr2[14:0], mr2[17:15], 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
@(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
// skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
data <= func_encode_skip( 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
@(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
// addr bank RCW ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD NOP, B_RST
data <= func_encode_cmd(mr3[14:0], mr3[17:15], 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
@(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
// skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
data <= func_encode_skip( 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
@(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
// addr bank RCW ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD NOP, B_RST
data <= func_encode_cmd(mr1[14:0], mr1[17:15], 7, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0); // SEL==1 - just testing?
@(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
// skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
data <= func_encode_skip( 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
@(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
// addr bank RCW ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD NOP, B_RST
data <= func_encode_cmd(mr0[14:0], mr0[17:15], 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
@(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
// skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
data <= func_encode_skip( 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
@(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
// encode ZQCL:
// addr bank RCW ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD NOP, B_RST
data <= func_encode_cmd(15'h400, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
@(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
// 512 clock cycles after ZQCL
// skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
data <= func_encode_skip( 256, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
@(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
// sequence done bit, skip length is ignored
// skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
data <= func_encode_skip( 10, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
@(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
end
endtask
function [ADDRESS_NUMBER+2:0] ddr3_mr0;
input pd; // precharge power down 0 - dll off (slow exit), 1 - dll on (fast exit)
input [2:0] wr; // write recovery:
// 3'b000: 16
// 3'b001: 5
// 3'b010: 6
// 3'b011: 7
// 3'b100: 8
// 3'b101: 10
// 3'b110: 12
// 3'b111: 14
input dll_rst; // 1 - dll reset (self clearing bit)
input [3:0] cl; // CAS latency (>=15ns):
// 0000: reserved
// 0010: 5
// 0100: 6
// 0110: 7
// 1000: 8
// 1010: 9
// 1100: 10
// 1110: 11
// 0001: 12
// 0011: 13
// 0101: 14
input bt; // read burst type: 0 sequential (nibble), 1 - interleaved
input [1:0] bl; // burst length:
// 2'b00 - fixed BL8
// 2'b01 - 4 or 8 on-the-fly by A12
// 2'b10 - fixed BL4 (chop)
// 2'b11 - reserved
begin
ddr3_mr0 = {
3'b0,
{ADDRESS_NUMBER-13{1'b0}},
pd, // MR0.12
wr, // MR0.11_9
dll_rst, // MR0.8
1'b0, // MR0.7
cl[3:1], // MR0.6_4
bt, // MR0.3
cl[0], // MR0.2
bl[1:0]}; // MR0.1_0
end
endfunction
function [ADDRESS_NUMBER+2:0] ddr3_mr1;
input qoff; // output enable: 0 - DQ, DQS operate in normal mode, 1 - DQ, DQS are disabled
input tdqs; // termination data strobe (for x8 devices) 0 - disabled, 1 - enabled
input [2:0] rtt; // on-die termination resistance:
// 3'b000 - disabled
// 3'b001 - RZQ/4 (60 Ohm)
// 3'b010 - RZQ/2 (120 Ohm)
// 3'b011 - RZQ/6 (40 Ohm)
// 3'b100 - RZQ/12(20 Ohm)
// 3'b101 - RZQ/8 (30 Ohm)
// 3'b11x - reserved
input wlev; // write leveling
input [1:0] ods; // output drive strength:
// 2'b00 - RZQ/6 - 40 Ohm
// 2'b01 - RZQ/7 - 34 Ohm
// 2'b1x - reserved
input [1:0] al; // additive latency:
// 2'b00 - disabled (AL=0)
// 2'b01 - AL=CL-1;
// 2'b10 - AL=CL-2
// 2'b11 - reserved
input dll; // 0 - DLL enabled (normal), 1 - DLL disabled
begin
ddr3_mr1 = {
3'h1,
{ADDRESS_NUMBER-13{1'b0}},
qoff, // MR1.12
tdqs, // MR1.11
1'b0, // MR1.10
rtt[2], // MR1.9
1'b0, // MR1.8
wlev, // MR1.7
rtt[1], // MR1.6
ods[1], // MR1.5
al[1:0], // MR1.4_3
rtt[0], // MR1.2
ods[0], // MR1.1
dll}; // MR1.0
end
endfunction
function [ADDRESS_NUMBER+2:0] ddr3_mr2;
input [1:0] rtt_wr; // Dynamic ODT :
// 2'b00 - disabled
// 2'b01 - RZQ/4 = 60 Ohm
// 2'b10 - RZQ/2 = 120 Ohm
// 2'b11 - reserved
input srt; // Self-refresh temperature 0 - normal (0-85C), 1 - extended (<=95C)
input asr; // Auto self-refresh 0 - disabled (manual), 1 - enabled (auto)
input [2:0] cwl; // CAS write latency:
// 3'b000 5CK ( tCK >= 2.5ns)
// 3'b001 6CK (1.875ns <= tCK < 2.5ns)
// 3'b010 7CK (1.5ns <= tCK < 1.875ns)
// 3'b011 8CK (1.25ns <= tCK < 1.5ns)
// 3'b100 9CK (1.071ns <= tCK < 1.25ns)
// 3'b101 10CK (0.938ns <= tCK < 1.071ns)
// 3'b11x reserved
begin
ddr3_mr2 = {
3'h2,
{ADDRESS_NUMBER-11{1'b0}},
rtt_wr[1:0], // MR2.10_9
1'b0, // MR2.8
srt, // MR2.7
asr, // MR2.6
cwl[2:0], // MR2.5_3
3'b0}; // MR2.2_0
end
endfunction
function [ADDRESS_NUMBER+2:0] ddr3_mr3;
input mpr; // MPR mode: 0 - normal, 1 - dataflow from MPR
input [1:0] mpr_rf; // MPR read function:
// 2'b00: predefined pattern 0101...
// 2'b1x, 2'bx1 - reserved
begin
ddr3_mr3 = {
3'h3,
{ADDRESS_NUMBER-3{1'b0}},
mpr, // MR3.2
mpr_rf[1:0]}; // MR3.1_0
end
endfunction
includes/x393_tasks_ps_pio.vh
0 → 100644
View file @
cbbd4ed1
/*******************************************************************************
* File: x393_tasks_ps_pio.vh
* Date:2015-02-07
* Author: andrey
* Description: Simulation tasks for mcntrl_ps_pio module (launching software
* - programmed memory transaction sequences)
*
* Copyright (c) 2015 <set up in Preferences-Verilog/VHDL Editor-Templates> .
* x393_tasks_ps_pio.vh is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* x393_tasks_ps_pio.vh 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/> .
*******************************************************************************/
task schedule_ps_pio; // shedule software-control memory operation (may need to check FIFO status first)
input [9:0] seq_addr; // sequence start address
input [1:0] page; // buffer page number
input urgent; // high priority request (only for competion wityh other channels, wiil not pass in this FIFO)
input chn; // channel buffer to use: 0 - memory read, 1 - memory write
input wait_complete; // Do not request a newe transaction from the scheduler until previous memory transaction is finished
begin
// wait_ps_pio_ready(DEFAULT_STATUS_MODE); // wait FIFO not half full
write_contol_register(MCNTRL_PS_ADDR + MCNTRL_PS_CMD, {17'b0,wait_complete,chn,urgent,page,seq_addr});
end
endtask
task wait_ps_pio_ready; // wait PS PIO module can accept comamnds (fifo half empty)
input [1:0] mode;
begin
wait_status_condition (
MCNTRL_PS_STATUS_REG_ADDR,
MCNTRL_PS_ADDR+MCNTRL_PS_STATUS_CNTRL,
mode,
0,
2 << STATUS_2LSB_SHFT,
0);
end
endtask
task wait_ps_pio_done; // wait PS PIO module has no pending/running memory transaction
input [1:0] mode;
begin
wait_status_condition (
MCNTRL_PS_STATUS_REG_ADDR,
MCNTRL_PS_ADDR+MCNTRL_PS_STATUS_CNTRL,
mode,
0,
3 << STATUS_2LSB_SHFT,
0);
end
endtask
includes/x393_tasks_status.vh
0 → 100644
View file @
cbbd4ed1
/*******************************************************************************
* File: x393_status.vh
* Date:2015-02-07
* Author: andrey
* Description: Simulation tasks for the x393 related to status
*
* Copyright (c) 2015 <set up in Preferences-Verilog/VHDL Editor-Templates> .
* x393_status.vh is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* x393_status.vh 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/> .
*******************************************************************************/
task wait_status_condition;
input [STATUS_DEPTH-1:0] status_address;
input [29:0] status_control_address;
input [1:0] status_mode;
input [25:0] pattern; // bits as in read registers
input [25:0] mask; // which bits to compare
input invert_match; // 0 - wait until match to pattern (all bits), 1 - wait until no match (any of bits differ)
reg match;
reg [5:0] seq_num;
begin
WAITING_STATUS = 1;
for (match=0; !match; match = invert_match ^ (((registered_rdata ^ {6'h0,pattern}) & {6'h0,mask})==0)) begin
read_and_wait_status(status_address);
write_contol_register(status_control_address, {24'b0,status_mode,registered_rdata[STATUS_SEQ_SHFT+:6] ^ 6'h20});
seq_num <= registered_rdata[STATUS_SEQ_SHFT+:6] ^ 6'h20;
read_and_wait_status(status_address);
while (((registered_rdata[STATUS_SEQ_SHFT+:6] ^ seq_num) & 6'h30)!=0) begin // match just 2 MSBs
read_and_wait_status(status_address);
end
end
WAITING_STATUS = 0;
end
endtask
task wait_phase_shifter_ready;
begin
WAITING_STATUS = 1;
read_and_wait_status(MCONTR_PHY_STATUS_REG_ADDR);
while (((registered_rdata & STATUS_PSHIFTER_RDY_MASK) == 0) || (((registered_rdata ^ {24'h0,target_phase}) & 'hff) != 0)) begin
read_and_wait_status(MCONTR_PHY_STATUS_REG_ADDR); // exits after negedge CLK
end
WAITING_STATUS = 0;
end
endtask
task read_all_status;
begin
read_and_wait_status (MCONTR_PHY_STATUS_REG_ADDR);
read_and_wait_status (MCONTR_TOP_STATUS_REG_ADDR);
read_and_wait_status (MCNTRL_PS_STATUS_REG_ADDR);
read_and_wait_status (MCNTRL_SCANLINE_STATUS_REG_CHN2_ADDR);
read_and_wait_status (MCNTRL_SCANLINE_STATUS_REG_CHN3_ADDR);
read_and_wait_status (MCNTRL_TILED_STATUS_REG_CHN4_ADDR);
read_and_wait_status (MCNTRL_TEST01_STATUS_REG_CHN2_ADDR);
read_and_wait_status (MCNTRL_TEST01_STATUS_REG_CHN3_ADDR);
read_and_wait_status (MCNTRL_TEST01_STATUS_REG_CHN4_ADDR);
end
endtask
task read_and_wait_status;
input [STATUS_DEPTH-1:0] address;
begin
read_and_wait_w(STATUS_ADDR + address ); // Will set: registered_rdata <= rdata;
end
endtask
task program_status_all;
input [1:0] mode;
input [5:0] seq_num;
begin
program_status (MCONTR_PHY_16BIT_ADDR, MCONTR_PHY_STATUS_CNTRL, mode,seq_num); //MCONTR_PHY_STATUS_REG_ADDR= 'h0,
program_status (MCONTR_TOP_16BIT_ADDR, MCONTR_TOP_16BIT_STATUS_CNTRL, mode,seq_num); //MCONTR_TOP_STATUS_REG_ADDR= 'h1,
program_status (MCNTRL_PS_ADDR, MCNTRL_PS_STATUS_CNTRL, mode,seq_num); //MCNTRL_PS_STATUS_REG_ADDR= 'h2,
program_status (MCNTRL_SCANLINE_CHN2_ADDR, MCNTRL_SCANLINE_STATUS_CNTRL, mode,seq_num); //MCNTRL_SCANLINE_STATUS_REG_CHN2_ADDR='h4,
program_status (MCNTRL_SCANLINE_CHN3_ADDR, MCNTRL_SCANLINE_STATUS_CNTRL, mode,seq_num); //MCNTRL_SCANLINE_STATUS_REG_CHN3_ADDR='h5,
program_status (MCNTRL_TILED_CHN4_ADDR, MCNTRL_TILED_STATUS_CNTRL, mode,seq_num); //MCNTRL_TILED_STATUS_REG_CHN4_ADDR= 'h6,
program_status (MCNTRL_TEST01_ADDR, MCNTRL_TEST01_CHN2_STATUS_CNTRL,mode,seq_num); //MCNTRL_TEST01_STATUS_REG_CHN2_ADDR= 'h3c,
program_status (MCNTRL_TEST01_ADDR, MCNTRL_TEST01_CHN3_STATUS_CNTRL,mode,seq_num); //MCNTRL_TEST01_STATUS_REG_CHN3_ADDR= 'h3d,
program_status (MCNTRL_TEST01_ADDR, MCNTRL_TEST01_CHN4_STATUS_CNTRL,mode,seq_num); //MCNTRL_TEST01_STATUS_REG_CHN4_ADDR= 'h3e,
end
endtask
task program_status;
input [29:0] base_addr;
input [7:0] reg_addr;
input [1:0] mode;
// mode bits:
// 0 disable status generation,
// 1 single status request,
// 2 - auto status, keep specified seq number,
// 3 - auto, inc sequence number
input [5:0] seq_number;
begin
// axi_write_single_w(CONTROL_ADDR+base_addr+reg_addr, {24'b0,mode,seq_number});
write_contol_register(base_addr + reg_addr, {24'b0,mode,seq_number});
end
endtask
x393_testbench01.sav
View file @
cbbd4ed1
[*]
[*]
[*] GTKWave Analyzer v3.3.58 (w)1999-2014 BSI
[*] GTKWave Analyzer v3.3.58 (w)1999-2014 BSI
[*] Fri Feb 13
18:38:10
2015
[*] Fri Feb 13
20:24:18
2015
[*]
[*]
[dumpfile] "/home/andrey/git/x393/simulation/x393_testbench01-2015021311
1425884
.lxt"
[dumpfile] "/home/andrey/git/x393/simulation/x393_testbench01-2015021311
3832125
.lxt"
[dumpfile_mtime] "Fri Feb 13 18:
19:38
2015"
[dumpfile_mtime] "Fri Feb 13 18:
43:22
2015"
[dumpfile_size] 23
2662775
[dumpfile_size] 23
3070602
[savefile] "/home/andrey/git/x393/x393_testbench01.sav"
[savefile] "/home/andrey/git/x393/x393_testbench01.sav"
[timestart]
138611
000
[timestart]
97060
000
[size] 1823 1173
[size] 1823 1173
[pos] 1922 0
[pos] 1922 0
*-2
0.698502 143181875 141406879 141780000 142422500 142495000 143137500 143495000 144137500 140756879
-1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
*-2
3.698502 146225000 -1 -1 -1 -1 -1 -1 -1 -1
-1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
[treeopen] x393_testbench01.
[treeopen] x393_testbench01.
[treeopen] x393_testbench01.x393_i.
[treeopen] x393_testbench01.x393_i.
[treeopen] x393_testbench01.x393_i.mcntrl393_i.
[treeopen] x393_testbench01.x393_i.mcntrl393_i.
...
@@ -1455,6 +1455,8 @@ x393_testbench01.x393_i.mcntrl393_i.mcntrl_ps_pio_i.chn1_buf_i.rpage_in[1:0]
...
@@ -1455,6 +1455,8 @@ x393_testbench01.x393_i.mcntrl393_i.mcntrl_ps_pio_i.chn1_buf_i.rpage_in[1:0]
x393_testbench01.x393_i.mcntrl393_i.mcntrl_ps_pio_i.chn1_buf_i.rpage_set[0]
x393_testbench01.x393_i.mcntrl393_i.mcntrl_ps_pio_i.chn1_buf_i.rpage_set[0]
@1000200
@1000200
-PS_PIO_CHN1
-PS_PIO_CHN1
@c00201
-other_modules
@28
@28
x393_testbench01.x393_i.mcntrl393_i.memctrl16_i.ext_buf_rrun[0]
x393_testbench01.x393_i.mcntrl393_i.memctrl16_i.ext_buf_rrun[0]
x393_testbench01.x393_i.mcntrl393_i.memctrl16_i.ext_buf_wrun[0]
x393_testbench01.x393_i.mcntrl393_i.memctrl16_i.ext_buf_wrun[0]
...
@@ -1490,6 +1492,8 @@ x393_testbench01.x393_i.mcntrl393_i.memctrl16_i.seq_done1[0]
...
@@ -1490,6 +1492,8 @@ x393_testbench01.x393_i.mcntrl393_i.memctrl16_i.seq_done1[0]
x393_testbench01.x393_i.mcntrl393_i.memctrl16_i.seq_done0[0]
x393_testbench01.x393_i.mcntrl393_i.memctrl16_i.seq_done0[0]
@1001200
@1001200
-group_end
-group_end
@1401201
-other_modules
@200
@200
-
-
@28
@28
...
...
x393_testbench01.tf
View file @
cbbd4ed1
...
@@ -396,7 +396,7 @@ assign bvalid= x393_i.ps7_i.MAXIGP0BVALID;
...
@@ -396,7 +396,7 @@ assign bvalid= x393_i.ps7_i.MAXIGP0BVALID;
assign x393_i.ps7_i.MAXIGP0BREADY= bready;
assign x393_i.ps7_i.MAXIGP0BREADY= bready;
assign bid= x393_i.ps7_i.MAXIGP0BID;
assign bid= x393_i.ps7_i.MAXIGP0BID;
assign bresp= x393_i.ps7_i.MAXIGP0BRESP;
assign bresp= x393_i.ps7_i.MAXIGP0BRESP;
//TODO: See how to show problems in include files opened in the editor (test all top *.v files that have it)
// Top module under test
// Top module under test
x393 #(
x393 #(
.MCONTR_WR_MASK (MCONTR_WR_MASK),
.MCONTR_WR_MASK (MCONTR_WR_MASK),
...
@@ -958,1047 +958,13 @@ task set_all_sequences;
...
@@ -958,1047 +958,13 @@ task set_all_sequences;
end
end
endtask
endtask
task
enable_cmda
;
input
en
;
begin
write_contol_register
(
MCONTR_PHY_0BIT_ADDR
+
MCONTR_PHY_0BIT_CMDA_EN
+
en
,
0
);
end
endtask
task
enable_cke
;
input
en
;
begin
write_contol_register
(
MCONTR_PHY_0BIT_ADDR
+
MCONTR_PHY_0BIT_CKE_EN
+
en
,
0
);
end
endtask
task
activate_sdrst
;
input
en
;
begin
write_contol_register
(
MCONTR_PHY_0BIT_ADDR
+
MCONTR_PHY_0BIT_SDRST_ACT
+
en
,
0
);
end
endtask
task
enable_refresh
;
input
en
;
begin
write_contol_register
(
MCONTR_TOP_0BIT_ADDR
+
MCONTR_TOP_0BIT_REFRESH_EN
+
en
,
0
);
end
endtask
task
enable_memcntrl
;
input
en
;
begin
write_contol_register
(
MCONTR_TOP_0BIT_ADDR
+
MCONTR_TOP_0BIT_MCONTR_EN
+
en
,
0
);
end
endtask
task
enable_memcntrl_channels
;
input
[
15
:
0
]
chnen
;
// bit-per-channel, 1 - enable;
begin
write_contol_register
(
MCONTR_TOP_16BIT_ADDR
+
MCONTR_TOP_16BIT_CHN_EN
,
{
16
'b0,chnen});
end
endtask
task configure_channel_priority;
input [ 3:0] chn;
input [15:0] priority; // (higher is more important)
begin
write_contol_register(MCONTR_ARBIT_ADDR + chn, {16'
b0
,
priority
}
);
end
endtask
task
enable_reset_ps_pio
;
// control reset and enable of the PS PIO channel;
input
en
;
input
rst
;
begin
write_contol_register
(
MCNTRL_PS_ADDR
+
MCNTRL_PS_EN_RST
,
{
30
'b0,en,~rst});
end
endtask
task schedule_ps_pio; // shedule software-control memory operation (may need to check FIFO status first)
input [9:0] seq_addr; // sequence start address
input [1:0] page; // buffer page number
input urgent; // high priority request (only for competion wityh other channels, wiil not pass in this FIFO)
input chn; // channel buffer to use: 0 - memory read, 1 - memory write
input wait_complete; // Do not request a newe transaction from the scheduler until previous memory transaction is finished
begin
// wait_ps_pio_ready(DEFAULT_STATUS_MODE); // wait FIFO not half full
write_contol_register(MCNTRL_PS_ADDR + MCNTRL_PS_CMD, {17'
b0
,
wait_complete
,
chn
,
urgent
,
page
,
seq_addr
}
);
end
endtask
//MCONTR_BUF1_WR_ADDR
task
write_block_buf_chn
;
// S uppressThisWarning VEditor : may be unused
input
integer
chn
;
// buffer channel
input
[
1
:
0
]
page
;
input
integer
num_words
;
// number of words to write (will be rounded up to multiple of 16)
reg
[
29
:
0
]
start_addr
;
begin
case
(
chn
)
1
:
start_addr
=
MCONTR_BUF1_WR_ADDR
+
(
page
<<
8
);
3: start_addr=MCONTR_BUF3_WR_ADDR + (page << 8);
default: begin
$display("**** ERROR: Invalid channel for write buffer = %d @%t", chn, $time);
start_addr = MCONTR_BUF1_WR_ADDR+ (page << 8);
end
endcase
write_block_buf (start_addr, num_words);
end
endtask
task write_block_buf;
input [29:0] start_word_address;
input integer num_words; // number of words to write (will be rounded up to multiple of 16)
integer i, j;
begin
$display("**** write_block_buf @%t", $time);
for (i = 0; i < num_words; i = i + 16) begin
axi_write_addr_data(
i, // id
{start_word_address,2'b0}+( i << 2),
// (MCONTR_BUF1_WR_ADDR + (page <<8)+ i) << 2, // addr
i | (((i + 7) & 'hff) << 8) | (((i + 23) & 'hff) << 16) | (((i + 31) & 'hff) << 24),
4'hf, // len
1, // burst type - increment
1'b1, // data_en
4'hf, // wstrb
1'b0 // last
);
$display("+Write block data (addr:data): 0x%x:0x%08x @%t", i, i | (((i + 7) & 'hff) << 8) | (((i + 23) & 'hff) << 16) | (((i + 31) & 'hff) << 24), $time);
for (j = 1; j < 16; j = j + 1) begin
axi_write_data(
i, // id
(i + j) | ((((i + j) + 7) & 'hff) << 8) | ((((i + j) + 23) & 'hff) << 16) | ((((i + j) + 31) & 'hff) << 24),
4'hf, // wstrb
(1 == 15) ? 1 : 0 // last
);
$display(" Write block data (addr:data): 0x%08x:0x%x @%t", (i + j),
(i + j) | ((((i + j) + 7) & 'hff) << 8) | ((((i + j) + 23) & 'hff) << 16) | ((((i + j) + 31) & 'hff) << 24), $time);
end
end
end
endtask
// read memory
task read_block_buf_chn; // S uppressThisWarning VEditor : may be unused
input integer chn; // buffer channel
input [1:0] page;
input integer num_read; // number of words to read (will be rounded up to multiple of 16)
input wait_done;
reg [29:0] start_addr;
begin
case (chn)
0: start_addr=MCONTR_BUF0_RD_ADDR + (page << 8);
2: start_addr=MCONTR_BUF2_RD_ADDR + (page << 8);
4: start_addr=MCONTR_BUF4_RD_ADDR + (page << 8);
default: begin
$display("**** ERROR: Invalid channel for read buffer = %d @%t", chn, $time);
start_addr = 30'b0+ (page << 8);
end
endcase
read_block_buf (start_addr, num_read, wait_done);
end
endtask
task read_block_buf;
input [29:0] start_word_address;
input integer num_read; // number of words to read (will be rounded up to multiple of 16)
input wait_done;
integer i; //,j;
begin
wait (~rstb);
SIMUL_AXI_FULL<=1'b0;
$display("**** read_block_buf @%t", $time);
axi_set_rd_lag(0);
for (i = 0; i < num_read; i = i + 16) begin
wait(arready);
// $display ("read_block_buf (0x%x) @%t",i,$time);
axi_read_addr(
i, // id
{start_word_address,2'b0}+( i << 2), // addr
4'hf, // len
1 // burst type - increment
);
end
if (wait_done) begin
// wait (AXI_RD_EMPTY);
wait_read_queue_empty;
end
end
endtask
task set_read_block;
input [ 2:0] ba;
input [14:0] ra;
input [ 9:0] ca;
reg [29:0] cmd_addr;
reg [31:0] data;
integer i;
begin
cmd_addr <= MCONTR_CMD_WR_ADDR + READ_BLOCK_OFFSET;
// activate
// addr bank RCW ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD NOP, B_RST
data <= func_encode_cmd( ra[14:0], ba[2:0], 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
@(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
// see if pause is needed . See when buffer read should be started - maybe before WR command
// skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
data <= func_encode_skip( 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
@(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
// first read
// read
// addr bank RCW ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD NOP, B_RST
data <= func_encode_cmd( {5'b0,ca[9:0]}, ba[2:0], 2, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0);
@(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
// nop
// skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
data <= func_encode_skip( 0, 0, ba[2:0], 0, 0, 1, 0, 0, 0, 1, 0, 0, 0);
@(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
//repeat remaining reads
for (i=1;i<64;i=i+1) begin
// read
// addr bank RCW ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD NOP, B_RST
data <= func_encode_cmd({5'b0,ca[9:0]}+(i<<3),ba[2:0],2, 0, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0);
@(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
end
// nop - all 3 below are the same? - just repeat?
// skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
data <= func_encode_skip( 0, 0, ba[2:0], 0, 0, 1, 0, 0, 0, 1, 1, 0, 0);
@(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
// nop
// skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
data <= func_encode_skip( 0, 0, ba[2:0], 0, 0, 1, 0, 0, 0, 1, 1, 0, 0);
@(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
// nop
// skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
data <= func_encode_skip( 0, 0, ba[2:0], 0, 0, 1, 0, 0, 0, 1, 0, 0, 0);
@(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
// tRTP = 4*tCK is already satisfied, no skip here
// precharge, end of a page (B_RST)
// addr bank RCW ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD NOP, B_RST
data <= func_encode_cmd( ra[14:0], ba[2:0], 5, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1);
@(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
// skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
data <= func_encode_skip( 2, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0);
@(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
// Turn off DCI, set DONE
// skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
data <= func_encode_skip( 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
@(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
end
endtask
task set_write_block;
input[2:0]ba;
input[14:0]ra;
input[9:0]ca;
reg[29:0] cmd_addr;
reg[31:0] data;
integer i;
begin
cmd_addr <= MCONTR_CMD_WR_ADDR + WRITE_BLOCK_OFFSET;
// activate
// addr bank RCW ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD NOP, B_RST
data <= func_encode_cmd( ra[14:0], ba[2:0], 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
@(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
// see if pause is needed . See when buffer read should be started - maybe before WR command
// skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
data <= func_encode_skip( 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0); // tRCD - 2 read bufs
@(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
// first write, 3 rd_buf
// write
// addr bank RCW ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD NOP, B_RST
data <= func_encode_cmd( {5'b0,ca[9:0]}, ba[2:0], 3, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0); // B_RD moved 1 cycle earlier
@(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
// nop 4-th rd_buf
// skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
// data <= func_encode_skip( 0, 0, ba[2:0], 1, 0, 1, 1, 1, 0, 1, 0, 1, 0);
data <= func_encode_skip( 0, 0, ba[2:0], 1, 0, 0, 1, 1, 0, 0, 0, 1, 0);
@(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
//repeat remaining writes
for (i = 1; i < 63; i = i + 1) begin
// write
// add bank RCW ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD NOP, B_RST
data <= func_encode_cmd( {5'b0,ca[9:0]}+(i<<3),ba[2:0],3, 1, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0);
@(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
end
// One last write pair w/o buffer
// add bank RCW ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD NOP, B_RST
data <= func_encode_cmd( {5'b0,ca[9:0]}+(63<<3),ba[2:0],3,1, 0, 1, 1, 1, 1, 0, 0, 0, 1, 0);
@(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
// nop
// skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
data <= func_encode_skip( 0, 0, ba[2:0], 1, 0, 0, 1, 1, 1, 0, 0, 0, 0);
@(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
// nop
// skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
data <= func_encode_skip( 0, 0, ba[2:0], 1, 0, 0, 1, 1, 1, 0, 0, 0, 1); // removed B_RD 1 cycle earlier
@(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
// nop
// skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
data <= func_encode_skip( 0, 0, ba[2:0], 1, 0, 0, 1, 1, 1, 0, 0, 0, 0);
@(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
// ODT off, it has latency
// skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
data <= func_encode_skip( 2, 0, ba[2:0], 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
@(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
// precharge, ODT off
// addr bank RCW ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD NOP, B_RST
data <= func_encode_cmd( ra[14:0], ba[2:0], 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
@(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
// skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
data <= func_encode_skip( 2, 0, ba[2:0], 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
@(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
// Finalize, set DONE
// skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
data <= func_encode_skip( 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
@(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
end
endtask
// Set MR3, read nrep*8 words, save to buffer (port0). No ACTIVATE/PRECHARGE are needed/allowed
task set_read_pattern;
input integer nrep;
// input [ 2:0] ba;
// input [14:0] ra;
// input [ 9:0] ca;
reg[29:0] cmd_addr;
reg[31:0] data;
reg[17:0] mr3_norm;
reg[17:0] mr3_patt;
integer i;
begin
cmd_addr <= MCONTR_CMD_WR_ADDR + READ_PATTERN_OFFSET;
mr3_norm <= ddr3_mr3(
1'h0, // mpr; // MPR mode: 0 - normal, 1 - dataflow from MPR
2'h0); // [1:0] mpr_rf; // MPR read function: 2'b00: predefined pattern 0101...
mr3_patt <= ddr3_mr3(
1'h1, // mpr; // MPR mode: 0 - normal, 1 - dataflow from MPR
2'h0); // [1:0] mpr_rf; // MPR read function: 2'b00: predefined pattern 0101...
@(posedge CLK);
// Set pattern mode
// addr bank RCW ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD NOP, B_RST
data <= func_encode_cmd(mr3_patt[14:0], mr3_patt[17:15], 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
@(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
// skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
data <= func_encode_skip( 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); // tMOD
@(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
// first read
// read
// addr bank RCW ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD NOP, B_RST
data <= func_encode_cmd( 0, 0, 2, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0);
@(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
// nop (combine with previous?)
// skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
data <= func_encode_skip( 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0);
@(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
//repeat remaining reads
for (i = 1; i < nrep; i = i + 1) begin
// addr bank RCW ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD NOP, B_RST
data <= func_encode_cmd( 0, 0, 2, 0, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0);
@(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
end
// nop - all 3 below are the same? - just repeat?
// skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
data <= func_encode_skip( 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0);
@(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
// nop
// skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
data <= func_encode_skip( 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0);
@(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
// nop
// skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
data <= func_encode_skip( 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0);
@(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
// nop, no write buffer - next page
// skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
data <= func_encode_skip( 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1);
@(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
// skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
data <= func_encode_skip( 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0);
@(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
// Turn off read pattern mode
// addr bank RCW ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD NOP, B_RST
data <= func_encode_cmd(mr3_norm[14:0], mr3_norm[17:15], 7, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0);
@(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
// tMOD (keep DCI enabled)
// skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
data <= func_encode_skip( 5, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0);
@(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
// Turn off DCI
// skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
data <= func_encode_skip( 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
@(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
// Finalize (set DONE)
data <= func_encode_skip( 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
@(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
end
endtask
task set_write_lev;
input[CMD_PAUSE_BITS-1:0]nrep;
reg[17:0] mr1_norm;
reg[17:0] mr1_wlev;
reg[29:0] cmd_addr;
reg[31:0] data;
reg[CMD_PAUSE_BITS-1:0] dqs_low_rpt;
reg[CMD_PAUSE_BITS-1:0] nrep_minus_1;
begin
dqs_low_rpt <= 8;
nrep_minus_1 <= nrep - 1;
mr1_norm <= ddr3_mr1(
1'h0, // qoff; // output enable: 0 - DQ, DQS operate in normal mode, 1 - DQ, DQS are disabled
1'h0, // tdqs; // termination data strobe (for x8 devices) 0 - disabled, 1 - enabled
3'h2, // [2:0] rtt; // on-die termination resistance: // 3'b010 - RZQ/2 (120 Ohm)
1'h0, // wlev; // write leveling
2'h0, // ods; // output drive strength: // 2'b00 - RZQ/6 - 40 Ohm
2'h0, // [1:0] al; // additive latency: 2'b00 - disabled (AL=0)
1'b0); // dll; // 0 - DLL enabled (normal), 1 - DLL disabled
mr1_wlev <= ddr3_mr1(
1'h0, // qoff; // output enable: 0 - DQ, DQS operate in normal mode, 1 - DQ, DQS are disabled
1'h0, // tdqs; // termination data strobe (for x8 devices) 0 - disabled, 1 - enabled
3'h2, // [2:0] rtt; // on-die termination resistance: // 3'b010 - RZQ/2 (120 Ohm)
1'h1, // wlev; // write leveling
2'h0, // ods; // output drive strength: // 2'b00 - RZQ/6 - 40 Ohm
2'h0, // [1:0] al; // additive latency: 2'b00 - disabled (AL=0)
1'b0); // dll; // 0 - DLL enabled (normal), 1 - DLL disabled
cmd_addr <= MCONTR_CMD_WR_ADDR + WRITELEV_OFFSET;
// Enter write leveling mode
@(posedge CLK)
// addr bank RCW ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD NOP, B_RST
data <= func_encode_cmd(mr1_wlev[14:0], mr1_wlev[17:15], 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
@(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
// skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
data <= func_encode_skip( 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); // tWLDQSEN=25tCK
@(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
// enable DQS output, keep it low (15 more tCK for the total of 40 tCK
// skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
data <= func_encode_skip(dqs_low_rpt, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0);
@(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
// Toggle DQS as needed for write leveling, write to buffer
// skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
data <= func_encode_skip(nrep_minus_1,0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0);
@(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
// continue toggling (5 times), but disable writing to buffer (used same wbuf latency as for read)
// skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
data <= func_encode_skip( 4, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0);
@(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
// Keep DCI (but not ODT) active ODT should be off befor MRS
// skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
data <= func_encode_skip( 2, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0);
@(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
// exit write leveling mode, ODT off, DCI off
// addr bank RCW ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD NOP, B_RST
data <= func_encode_cmd(mr1_norm[14:0], mr1_norm[17:15], 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
@(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
// skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
data <= func_encode_skip( 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); // tMOD
@(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
// Finalize. See if DONE can be combined with B_RST, if not - insert earlier
// skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
data <= func_encode_skip( 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1); // can DONE be combined with B_RST?
@(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
end
endtask
task set_refresh;
input[9:0]t_rfc; // =50 for tCK=2.5ns
input[7:0]t_refi; // 48/97 for normal, 8 - for simulation
reg[29:0] cmd_addr;
reg[31:0] data;
begin
cmd_addr <= MCONTR_CMD_WR_ADDR + REFRESH_OFFSET;
@(posedge CLK)
// addr bank RCW ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD NOP, B_RST
data <= func_encode_cmd( 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
@(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
// =50 tREFI=260 ns before next ACTIVATE or REFRESH, @2.5ns clock, @5ns cycle
// skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
data <= func_encode_skip( t_rfc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
@(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
// Ready for normal operation
// skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
data <= func_encode_skip( 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
@(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
// write_contol_register(DLY_SET,0);
write_contol_register(MCONTR_TOP_16BIT_ADDR + MCONTR_TOP_16BIT_REFRESH_ADDRESS, REFRESH_OFFSET);
write_contol_register(MCONTR_TOP_16BIT_ADDR + MCONTR_TOP_16BIT_REFRESH_PERIOD, {24'h0,t_refi});
// enable refresh - should it be done here?
// write_contol_register(MCONTR_PHY_0BIT_ADDR + MCONTR_TOP_0BIT_REFRESH_EN + 1, 0);
end
endtask
task set_mrs; // will also calibrate ZQ
input reset_dll;
reg[17:0] mr0;
reg[17:0] mr1;
reg[17:0] mr2;
reg[17:0] mr3;
reg[29:0] cmd_addr;
reg[31:0] data;
begin
mr0 <= ddr3_mr0(
1'h0, // pd; // precharge power down 0 - dll off (slow exit), 1 - dll on (fast exit)
3'h2, // [2:0] wr; // write recovery (encode ceil(tWR/tCK)) // 3'b010: 6
reset_dll, // dll_rst; // 1 - dll reset (self clearing bit)
4'h4, // [3:0] cl; // CAS latency: // 0100: 6 (time 15ns)
1'h0, // bt; // read burst type: 0 sequential (nibble), 1 - interleave
2'h0); // [1:0] bl; // burst length: // 2'b00 - fixed BL8
mr1 <= ddr3_mr1(
1'h0, // qoff; // output enable: 0 - DQ, DQS operate in normal mode, 1 - DQ, DQS are disabled
1'h0, // tdqs; // termination data strobe (for x8 devices) 0 - disabled, 1 - enabled
3'h2, // [2:0] rtt; // on-die termination resistance: // 3'b010 - RZQ/2 (120 Ohm)
1'h0, // wlev; // write leveling
2'h0, // ods; // output drive strength: // 2'b00 - RZQ/6 - 40 Ohm
2'h0, // [1:0] al; // additive latency: 2'b00 - disabled (AL=0)
1'b0); // dll; // 0 - DLL enabled (normal), 1 - DLL disabled
mr2 <= ddr3_mr2(
2'h0, // [1:0] rtt_wr; // Dynamic ODT : // 2'b00 - disabled, 2'b01 - RZQ/4 = 60 Ohm, 2'b10 - RZQ/2 = 120 Ohm
1'h0, // srt; // Self-refresh temperature 0 - normal (0-85C), 1 - extended (<=95C)
1'h0, // asr; // Auto self-refresh 0 - disabled (manual), 1 - enabled (auto)
3'h0); // [2:0] cwl; // CAS write latency:3'b000 5CK (tCK >= 2.5ns), 3'b001 6CK (1.875ns <= tCK < 2.5ns)
mr3 <= ddr3_mr3(
1'h0, // mpr; // MPR mode: 0 - normal, 1 - dataflow from MPR
2'h0); // [1:0] mpr_rf; // MPR read function: 2'b00: predefined pattern 0101...
cmd_addr <= MCONTR_CMD_WR_ADDR + INITIALIZE_OFFSET;
@(posedge CLK)
$display("mr0=0x%x", mr0);
$display("mr1=0x%x", mr1);
$display("mr2=0x%x", mr2);
$display("mr3=0x%x", mr3);
// addr bank RCW ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD NOP, B_RST
data <= func_encode_cmd(mr2[14:0], mr2[17:15], 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
@(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
// skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
data <= func_encode_skip( 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
@(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
// addr bank RCW ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD NOP, B_RST
data <= func_encode_cmd(mr3[14:0], mr3[17:15], 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
@(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
// skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
data <= func_encode_skip( 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
@(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
// addr bank RCW ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD NOP, B_RST
data <= func_encode_cmd(mr1[14:0], mr1[17:15], 7, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0); // SEL==1 - just testing?
@(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
// skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
data <= func_encode_skip( 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
@(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
// addr bank RCW ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD NOP, B_RST
data <= func_encode_cmd(mr0[14:0], mr0[17:15], 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
@(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
// skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
data <= func_encode_skip( 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
@(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
// encode ZQCL:
// addr bank RCW ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD NOP, B_RST
data <= func_encode_cmd(15'h400, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
@(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
// 512 clock cycles after ZQCL
// skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
data <= func_encode_skip( 256, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
@(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
// sequence done bit, skip length is ignored
// skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
data <= func_encode_skip( 10, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
@(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
end
endtask
/*
function [31:0] encode_seq_skip;
input [CMD_PAUSE_BITS-1:0] skip;
input done;
input dci_en;
input odt_en;
begin
encode_seq_skip={
{14-CMD_DONE_BIT{1'b0}},
done,
skip[CMD_PAUSE_BITS-1:0],
3'b0, //phy_bank_in[2:0],
3'b0, // phy_rcw_in[2:0], // {ras,cas,we}
odt_en, // phy_odt_in,
1'b0, // phy_cke_in, // may be optimized?
1'b0, // phy_sel_in, // first/second half-cycle, other will be nop (cke+odt applicable to both)
1'b0, // phy_dq_en_in, //phy_dq_tri_in, // tristate DQ lines (internal timing sequencer for 0->1 and 1->0)
1'b0, // phy_dqs_en_in, //phy_dqs_tri_in, // tristate DQS lines (internal timing sequencer for 0->1 and 1->0)
1'b0, //enable toggle DQS according to the pattern
dci_en, // phy_dci_en_in, //phy_dci_in, // DCI disable, both DQ and DQS lines (internal logic and timing sequencer for 0->1 and 1->0)
1'b0, // phy_buf_wr, // connect to external buffer (but only if not paused)
1'b0, // phy_buf_rd, // connect to external buffer (but only if not paused)
1'b0, // add NOP after the current command, keep other data
1'b0 // Reserved for future use
};
end
endfunction
*/
function [ADDRESS_NUMBER+2:0] ddr3_mr0;
input pd; // precharge power down 0 - dll off (slow exit), 1 - dll on (fast exit)
input [2:0] wr; // write recovery:
// 3'b000: 16
// 3'b001: 5
// 3'b010: 6
// 3'b011: 7
// 3'b100: 8
// 3'b101: 10
// 3'b110: 12
// 3'b111: 14
input dll_rst; // 1 - dll reset (self clearing bit)
input [3:0] cl; // CAS latency (>=15ns):
// 0000: reserved
// 0010: 5
// 0100: 6
// 0110: 7
// 1000: 8
// 1010: 9
// 1100: 10
// 1110: 11
// 0001: 12
// 0011: 13
// 0101: 14
input bt; // read burst type: 0 sequential (nibble), 1 - interleaved
input [1:0] bl; // burst length:
// 2'b00 - fixed BL8
// 2'b01 - 4 or 8 on-the-fly by A12
// 2'b10 - fixed BL4 (chop)
// 2'b11 - reserved
begin
ddr3_mr0 = {
3'b0,
{ADDRESS_NUMBER-13{1'b0}},
pd, // MR0.12
wr, // MR0.11_9
dll_rst, // MR0.8
1'b0, // MR0.7
cl[3:1], // MR0.6_4
bt, // MR0.3
cl[0], // MR0.2
bl[1:0]}; // MR0.1_0
end
endfunction
function [ADDRESS_NUMBER+2:0] ddr3_mr1;
input qoff; // output enable: 0 - DQ, DQS operate in normal mode, 1 - DQ, DQS are disabled
input tdqs; // termination data strobe (for x8 devices) 0 - disabled, 1 - enabled
input [2:0] rtt; // on-die termination resistance:
// 3'b000 - disabled
// 3'b001 - RZQ/4 (60 Ohm)
// 3'b010 - RZQ/2 (120 Ohm)
// 3'b011 - RZQ/6 (40 Ohm)
// 3'b100 - RZQ/12(20 Ohm)
// 3'b101 - RZQ/8 (30 Ohm)
// 3'b11x - reserved
input wlev; // write leveling
input [1:0] ods; // output drive strength:
// 2'b00 - RZQ/6 - 40 Ohm
// 2'b01 - RZQ/7 - 34 Ohm
// 2'b1x - reserved
input [1:0] al; // additive latency:
// 2'b00 - disabled (AL=0)
// 2'b01 - AL=CL-1;
// 2'b10 - AL=CL-2
// 2'b11 - reserved
input dll; // 0 - DLL enabled (normal), 1 - DLL disabled
begin
ddr3_mr1 = {
3'h1,
{ADDRESS_NUMBER-13{1'b0}},
qoff, // MR1.12
tdqs, // MR1.11
1'b0, // MR1.10
rtt[2], // MR1.9
1'b0, // MR1.8
wlev, // MR1.7
rtt[1], // MR1.6
ods[1], // MR1.5
al[1:0], // MR1.4_3
rtt[0], // MR1.2
ods[0], // MR1.1
dll}; // MR1.0
end
endfunction
function [ADDRESS_NUMBER+2:0] ddr3_mr2;
input [1:0] rtt_wr; // Dynamic ODT :
// 2'b00 - disabled
// 2'b01 - RZQ/4 = 60 Ohm
// 2'b10 - RZQ/2 = 120 Ohm
// 2'b11 - reserved
input srt; // Self-refresh temperature 0 - normal (0-85C), 1 - extended (<=95C)
input asr; // Auto self-refresh 0 - disabled (manual), 1 - enabled (auto)
input [2:0] cwl; // CAS write latency:
// 3'b000 5CK ( tCK >= 2.5ns)
// 3'b001 6CK (1.875ns <= tCK < 2.5ns)
// 3'b010 7CK (1.5ns <= tCK < 1.875ns)
// 3'b011 8CK (1.25ns <= tCK < 1.5ns)
// 3'b100 9CK (1.071ns <= tCK < 1.25ns)
// 3'b101 10CK (0.938ns <= tCK < 1.071ns)
// 3'b11x reserved
begin
ddr3_mr2 = {
3'h2,
{ADDRESS_NUMBER-11{1'b0}},
rtt_wr[1:0], // MR2.10_9
1'b0, // MR2.8
srt, // MR2.7
asr, // MR2.6
cwl[2:0], // MR2.5_3
3'b0}; // MR2.2_0
end
endfunction
function [ADDRESS_NUMBER+2:0] ddr3_mr3;
input mpr; // MPR mode: 0 - normal, 1 - dataflow from MPR
input [1:0] mpr_rf; // MPR read function:
// 2'b00: predefined pattern 0101...
// 2'b1x, 2'bx1 - reserved
begin
ddr3_mr3 = {
3'h3,
{ADDRESS_NUMBER-3{1'b0}},
mpr, // MR3.2
mpr_rf[1:0]}; // MR3.1_0
end
endfunction
task axi_set_same_delays; //SuppressThisWarning VEditor : may be unused
input [7:0] dq_idelay;
input [7:0] dq_odelay;
input [7:0] dqs_idelay;
input [7:0] dqs_odelay;
input [7:0] dm_odelay;
input [7:0] cmda_odelay;
begin
$display("SET DELAYS(0x%x,0x%x,0x%x,0x%x,0x%x,0x%x) @ %t",
dq_idelay,dq_odelay,dqs_idelay,dqs_odelay,dm_odelay,cmda_odelay,$time);
axi_set_dq_idelay(dq_idelay);
axi_set_dq_odelay(dq_odelay);
axi_set_dqs_idelay(dqs_idelay);
axi_set_dqs_odelay(dqs_odelay);
axi_set_dm_odelay(dm_odelay);
axi_set_cmda_odelay(cmda_odelay);
end
endtask
task axi_set_dqs_odelay_nominal; //SuppressThisWarning VEditor : may be unused
begin
// axi_set_dqs_idelay(
write_contol_register(LD_DLY_LANE0_ODELAY + 8, (DLY_LANE0_ODELAY >> (8<<3)) & 32'hff);
write_contol_register(LD_DLY_LANE1_ODELAY + 8, (DLY_LANE1_ODELAY >> (8<<3)) & 32'hff);
write_contol_register(DLY_SET,0);
end
endtask
task axi_set_dqs_idelay_nominal; //SuppressThisWarning VEditor : may be unused
begin
// axi_set_dqs_idelay(
write_contol_register(LD_DLY_LANE0_IDELAY + 8, (DLY_LANE0_IDELAY >> (8<<3)) & 32'hff);
write_contol_register(LD_DLY_LANE1_IDELAY + 8, (DLY_LANE1_IDELAY >> (8<<3)) & 32'hff);
write_contol_register(DLY_SET,0);
end
endtask
task axi_set_dqs_idelay_wlv; //SuppressThisWarning VEditor : may be unused
begin
write_contol_register(LD_DLY_LANE0_IDELAY + 8, DLY_LANE0_DQS_WLV_IDELAY);
write_contol_register(LD_DLY_LANE1_IDELAY + 8, DLY_LANE1_DQS_WLV_IDELAY);
write_contol_register(DLY_SET,0);
end
endtask
task axi_set_delays; // set all individual delays
integer i;
begin
for (i=0;i<10;i=i+1) begin
write_contol_register(LD_DLY_LANE0_ODELAY + i, (DLY_LANE0_ODELAY >> (i<<3)) & 32'hff);
end
for (i=0;i<9;i=i+1) begin
write_contol_register(LD_DLY_LANE0_IDELAY + i, (DLY_LANE0_IDELAY >> (i<<3)) & 32'hff);
end
for (i=0;i<10;i=i+1) begin
write_contol_register(LD_DLY_LANE1_ODELAY + i, (DLY_LANE1_ODELAY >> (i<<3)) & 32'hff);
end
for (i=0;i<9;i=i+1) begin
write_contol_register(LD_DLY_LANE1_IDELAY + i, (DLY_LANE1_IDELAY >> (i<<3)) & 32'hff);
end
for (i=0;i<32;i=i+1) begin
write_contol_register(LD_DLY_CMDA + i, (DLY_CMDA >> (i<<3)) & 32'hff);
end
// write_contol_register(DLY_SET,0);
axi_set_phase(DLY_PHASE); // also sets all delays
end
endtask
task axi_set_dq_idelay; // sets same delay to all dq idelay
input [7:0] delay;
begin
$display("SET DQ IDELAY=0x%x @ %t",delay,$time);
axi_set_multiple_delays(LD_DLY_LANE0_IDELAY, 8, delay);
axi_set_multiple_delays(LD_DLY_LANE1_IDELAY, 8, delay);
write_contol_register(DLY_SET,0); // set all delays
end
endtask
task axi_set_dq_odelay;
input [7:0] delay;
begin
$display("SET DQ ODELAY=0x%x @ %t",delay,$time);
axi_set_multiple_delays(LD_DLY_LANE0_ODELAY, 8, delay);
axi_set_multiple_delays(LD_DLY_LANE1_ODELAY, 8, delay);
write_contol_register(DLY_SET,0); // set all delays
end
endtask
task axi_set_dqs_idelay;
input [7:0] delay;
begin
$display("SET DQS IDELAY=0x%x @ %t",delay,$time);
axi_set_multiple_delays(LD_DLY_LANE0_IDELAY + 8, 1, delay);
axi_set_multiple_delays(LD_DLY_LANE1_IDELAY + 8, 1, delay);
write_contol_register(DLY_SET,0); // set all delays
end
endtask
task axi_set_dqs_odelay;
input [7:0] delay;
begin
$display("SET DQS ODELAY=0x%x @ %t",delay,$time);
axi_set_multiple_delays(LD_DLY_LANE0_ODELAY + 8, 1, delay);
axi_set_multiple_delays(LD_DLY_LANE1_ODELAY + 8, 1, delay);
write_contol_register(DLY_SET,0); // set all delays
end
endtask
task axi_set_dm_odelay;
input [7:0] delay;
begin
$display("SET DQM IDELAY=0x%x @ %t",delay,$time);
axi_set_multiple_delays(LD_DLY_LANE0_ODELAY + 9, 1, delay);
axi_set_multiple_delays(LD_DLY_LANE1_ODELAY + 9, 1, delay);
write_contol_register(DLY_SET,0); // set all delays
end
endtask
task axi_set_cmda_odelay;
input [7:0] delay;
begin
$display("SET COMMAND and ADDRESS ODELAY=0x%x @ %t",delay,$time);
axi_set_multiple_delays(LD_DLY_CMDA, 32, delay);
write_contol_register(DLY_SET,0); // set all delays
end
endtask
task axi_set_multiple_delays;
input [29:0] reg_addr;
input integer number;
input [7:0] delay;
integer i;
begin
for (i=0;i<number;i=i+1) begin
write_contol_register(reg_addr + i, {24'b0,delay}); // control regiter address
end
end
endtask
task axi_set_phase;
input [PHASE_WIDTH-1:0] phase;
begin
$display("SET CLOCK PHASE to 0x%x @ %t",phase,$time);
write_contol_register(LD_DLY_PHASE, {{(32-PHASE_WIDTH){1'b0}},phase}); // control regiter address
write_contol_register(DLY_SET,0);
target_phase <= phase;
end
endtask
task axi_set_wbuf_delay;
input [3:0] delay;
begin
$display("SET WBUF DELAY to 0x%x @ %t",delay,$time);
write_contol_register(MCONTR_PHY_16BIT_ADDR+MCONTR_PHY_16BIT_WBUF_DELAY, {28'h0, delay});
end
endtask
// set dq /dqs tristate on/off patterns
task axi_set_tristate_patterns;
begin
$display("SET TRISTATE PATTERNS @ %t",$time);
write_contol_register(MCONTR_PHY_16BIT_ADDR +MCONTR_PHY_16BIT_PATTERNS_TRI,
{16'h0, DQSTRI_LAST, DQSTRI_FIRST, DQTRI_LAST, DQTRI_FIRST});
end
endtask
task axi_set_dqs_dqm_patterns;
begin
$display("SET DQS+DQM PATTERNS @ %t",$time);
// set patterns for DM (always 0) and DQS - always the same (may try different for write lev.)
write_contol_register(MCONTR_PHY_16BIT_ADDR + MCONTR_PHY_16BIT_PATTERNS,
32'h0055);
end
endtask
task wait_ps_pio_ready; // wait PS PIO module can accept comamnds (fifo half empty)
input [1:0] mode;
begin
wait_status_condition (
MCNTRL_PS_STATUS_REG_ADDR,
MCNTRL_PS_ADDR+MCNTRL_PS_STATUS_CNTRL,
mode,
0,
2 << STATUS_2LSB_SHFT,
0);
end
endtask
task wait_ps_pio_done; // wait PS PIO module has no pending/running memory transaction
input [1:0] mode;
begin
wait_status_condition (
MCNTRL_PS_STATUS_REG_ADDR,
MCNTRL_PS_ADDR+MCNTRL_PS_STATUS_CNTRL,
mode,
0,
3 << STATUS_2LSB_SHFT,
0);
end
endtask
/*
localparam STATUS_SEQ_SHFT= 26; // bits [31:26] is the sequence number
localparam STATUS_2LSB_SHFT= 24; // bits [25:24] get the 2 LSB of the status (transmitted with the sequence number in the second byte)
localparam STATUS_MSB_RSHFT= 2; // status bits [25:2] are read through [23:0]
localparam STATUS_PSHIFTER_RDY_MASK = 1<<STATUS_2LSB_SHFT;
parameter MCONTR_PHY_STATUS_REG_ADDR= 'h0,//8 or less bits: status register address to use for memory controller phy
parameter MCONTR_TOP_STATUS_REG_ADDR= 'h1,//8 or less bits: status register address to use for memory controller
parameter MCNTRL_PS_STATUS_REG_ADDR= 'h2
parameter MCNTRL_SCANLINE_STATUS_REG_CHN2_ADDR='h4,
parameter MCNTRL_SCANLINE_STATUS_REG_CHN3_ADDR='h5,
parameter MCNTRL_TILED_STATUS_REG_CHN4_ADDR= 'h6,
parameter MCNTRL_TEST01_STATUS_REG_CHN2_ADDR= 'h3c, // status/readback register for channel 2
parameter MCNTRL_TEST01_STATUS_REG_CHN3_ADDR= 'h3d, // status/readback register for channel 3
parameter MCNTRL_TEST01_STATUS_REG_CHN4_ADDR= 'h3e // status/readback register for channel 4
*/
task wait_status_condition;
input [STATUS_DEPTH-1:0] status_address;
input [29:0] status_control_address;
input [1:0] status_mode;
input [25:0] pattern; // bits as in read registers
input [25:0] mask; // which bits to compare
input invert_match; // 0 - wait until match to pattern (all bits), 1 - wait until no match (any of bits differ)
reg match;
reg [5:0] seq_num;
begin
WAITING_STATUS = 1;
for (match=0; !match; match = invert_match ^ (((registered_rdata ^ {6'h0,pattern}) & {6'h0,mask})==0)) begin
read_and_wait_status(status_address);
write_contol_register(status_control_address, {24'b0,status_mode,registered_rdata[STATUS_SEQ_SHFT+:6] ^ 6'h20});
seq_num <= registered_rdata[STATUS_SEQ_SHFT+:6] ^ 6'h20;
read_and_wait_status(status_address);
while (((registered_rdata[STATUS_SEQ_SHFT+:6] ^ seq_num) & 6'h30)!=0) begin // match just 2 MSBs
read_and_wait_status(status_address);
end
end
WAITING_STATUS = 0;
end
endtask
task wait_phase_shifter_ready;
begin
WAITING_STATUS = 1;
read_and_wait_status(MCONTR_PHY_STATUS_REG_ADDR);
while (((registered_rdata & STATUS_PSHIFTER_RDY_MASK) == 0) || (((registered_rdata ^ {24'h0,target_phase}) & 'hff) != 0)) begin
read_and_wait_status(MCONTR_PHY_STATUS_REG_ADDR); // exits after negedge CLK
end
WAITING_STATUS = 0;
end
endtask
task read_all_status;
begin
read_and_wait_status (MCONTR_PHY_STATUS_REG_ADDR);
read_and_wait_status (MCONTR_TOP_STATUS_REG_ADDR);
read_and_wait_status (MCNTRL_PS_STATUS_REG_ADDR);
read_and_wait_status (MCNTRL_SCANLINE_STATUS_REG_CHN2_ADDR);
read_and_wait_status (MCNTRL_SCANLINE_STATUS_REG_CHN3_ADDR);
read_and_wait_status (MCNTRL_TILED_STATUS_REG_CHN4_ADDR);
read_and_wait_status (MCNTRL_TEST01_STATUS_REG_CHN2_ADDR);
read_and_wait_status (MCNTRL_TEST01_STATUS_REG_CHN3_ADDR);
read_and_wait_status (MCNTRL_TEST01_STATUS_REG_CHN4_ADDR);
end
endtask
task read_and_wait_status;
input [STATUS_DEPTH-1:0] address;
begin
read_and_wait_w(STATUS_ADDR + address ); // Will set: registered_rdata <= rdata;
end
endtask
task program_status_all;
input [1:0] mode;
input [5:0] seq_num;
begin
program_status (MCONTR_PHY_16BIT_ADDR, MCONTR_PHY_STATUS_CNTRL, mode,seq_num); //MCONTR_PHY_STATUS_REG_ADDR= 'h0,
program_status (MCONTR_TOP_16BIT_ADDR, MCONTR_TOP_16BIT_STATUS_CNTRL, mode,seq_num); //MCONTR_TOP_STATUS_REG_ADDR= 'h1,
program_status (MCNTRL_PS_ADDR, MCNTRL_PS_STATUS_CNTRL, mode,seq_num); //MCNTRL_PS_STATUS_REG_ADDR= 'h2,
program_status (MCNTRL_SCANLINE_CHN2_ADDR, MCNTRL_SCANLINE_STATUS_CNTRL, mode,seq_num); //MCNTRL_SCANLINE_STATUS_REG_CHN2_ADDR='h4,
program_status (MCNTRL_SCANLINE_CHN3_ADDR, MCNTRL_SCANLINE_STATUS_CNTRL, mode,seq_num); //MCNTRL_SCANLINE_STATUS_REG_CHN3_ADDR='h5,
program_status (MCNTRL_TILED_CHN4_ADDR, MCNTRL_TILED_STATUS_CNTRL, mode,seq_num); //MCNTRL_TILED_STATUS_REG_CHN4_ADDR= 'h6,
program_status (MCNTRL_TEST01_ADDR, MCNTRL_TEST01_CHN2_STATUS_CNTRL,mode,seq_num); //MCNTRL_TEST01_STATUS_REG_CHN2_ADDR= 'h3c,
program_status (MCNTRL_TEST01_ADDR, MCNTRL_TEST01_CHN3_STATUS_CNTRL,mode,seq_num); //MCNTRL_TEST01_STATUS_REG_CHN3_ADDR= 'h3d,
program_status (MCNTRL_TEST01_ADDR, MCNTRL_TEST01_CHN4_STATUS_CNTRL,mode,seq_num); //MCNTRL_TEST01_STATUS_REG_CHN4_ADDR= 'h3e,
end
endtask
task program_status;
input [29:0] base_addr;
input [7:0] reg_addr;
input [1:0] mode;
// mode bits:
// 0 disable status generation,
// 1 single status request,
// 2 - auto status, keep specified seq number,
// 3 - auto, inc sequence number
input [5:0] seq_number;
begin
// axi_write_single_w(CONTROL_ADDR+base_addr+reg_addr, {24'b0,mode,seq_number});
write_contol_register(base_addr + reg_addr, {24'b0,mode,seq_number});
end
endtask
task write_contol_register;
input [29:0] reg_addr;
// input [29:0] base_addr;
// input [7:0] reg_addr;
input [31:0] data;
begin
// axi_write_single_w(CONTROL_ADDR+base_addr+reg_addr, data);
axi_write_single_w(CONTROL_ADDR+reg_addr, data);
end
endtask
`
include
"includes/x393_tasks_mcntrl_en_dis_priority.vh"
`
include
"includes/x393_tasks_mcntrl_buffers.vh"
`
include
"includes/x393_tasks_pio_sequences.vh"
`
include
"includes/x393_tasks_mcntrl_timing.vh"
`
include
"includes/x393_tasks_ps_pio.vh"
`
include
"includes/x393_tasks_status.vh"
`
include
"includes/x393_tasks01.vh"
`
include
"includes/x393_tasks01.vh"
`
include
"includes/x393_mcontr_encode_cmd.vh"
`
include
"includes/x393_mcontr_encode_cmd.vh"
endmodule
endmodule
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment