Commit d899569e authored by Andrey Filippov's avatar Andrey Filippov

debugging/simulation

parent 9acfc5c3
......@@ -943,7 +943,7 @@ module ddr3 (
{1'bx, DIFF_BANK , REFRESH , PRECHARGE} ,
{1'bx, DIFF_BANK , REFRESH , ACTIVATE } ,
{1'bx, DIFF_BANK , REFRESH , ZQ } ,
{1'bx, DIFF_BANK , REFRESH , SELF_REF } : begin if ($time - tm_refresh < TRFC_MIN) $display ("%m: at time %t ERROR: tRFC violation during %s", $time, cmd_string[cmd]); end
{1'bx, DIFF_BANK , REFRESH , SELF_REF } : begin if ($time - tm_refresh < TRFC_MIN) $display ("%m: at time %t ERROR: tRFC violation during %s (%t < %t)", $time, cmd_string[cmd],$time - tm_refresh,TRFC_MIN); end
{1'bx, DIFF_BANK , REFRESH , PWR_DOWN } : begin if (ck_cntr - ck_refresh < TREFPDEN) $display ("%m: at time %t ERROR: tREFPDEN violation during %s", $time, cmd_string[cmd]); end
// precharge
......
......@@ -82,11 +82,8 @@ module mcntrl_ps_pio#(
wire channel_pgm_en=channel_pgm_en0 || channel_pgm_en1;
wire seq_done= seq_done0 || seq_done1;
// TODO: implement logic, move pages to command-based registers,
// Implement genearation of sequencer address specification, request/grant logic,
// Port memory buffer (4 pages each, R/W fixed, port 0 - AXI read from DDR, port 1 - AXI write to DDR
// generate 16-bit data commands (and set defaults to registers)
wire [4:0] cmd_a;
wire [4:0] cmd_a; // just to compare
wire [31:0] cmd_data;
wire cmd_we;
wire [1:0] status_data;
......@@ -102,7 +99,7 @@ module mcntrl_ps_pio#(
reg [1:0] en_reset;//
wire chn_rst = ~en_reset[0]; // resets command, including fifo;
wire chn_en = &en_reset[1]; // enable requests by channle (continue ones in progress)
reg mem_run; // sequencere pgm granted and set, waiting/executing memory transfer to/from buffur 0/1
reg mem_run; // sequencer pgm granted and set, waiting/executing memory transfer to/from buffur 0/1
wire busy;
wire start;
reg [1:0] page;
......@@ -147,7 +144,7 @@ module mcntrl_ps_pio#(
end
if (rst) mem_run <=0;
else if (chn_rst && seq_done) mem_run <=0;
else if (chn_rst || seq_done) mem_run <=0;
else if (channel_pgm_en) mem_run <=1;
if (rst) cmd_set <= 0;
......
This diff is collapsed.
......@@ -128,7 +128,8 @@ module mcontr_sequencer #(
// Controller run interface, posedge mclk
input [10:0] run_addr, // controller sequencer start address (0..11'h3ff - cmd0, 11'h400..11'h7ff - cmd1)
input [3:0] run_chn, // data channel to use
input run_seq, // start controller sequence (will and with !ddr_rst for stable mclk)
input run_refresh, // command is refresh (invalidates channel)
input run_seq, // start controller sequence (will end with !ddr_rst for stable mclk)
output run_done, // controller sequence finished
output run_busy, // controller sequence in progress
output mcontr_reset, // == ddr_reset that also resets sequencer
......@@ -146,6 +147,7 @@ module mcontr_sequencer #(
output ext_buf_rpage_nxt, // increment external buffer read address to next page start
// output [6:0] ext_buf_raddr, // valid with ext_buf_rd, 2 page MSB to be generated externally
output [3:0] ext_buf_rchn, // ==run_chn_d valid 1 cycle ahead opf ext_buf_rd!, maybe not needed - will be generated externally
output ext_buf_rrefresh, // was refresh, invalidates ext_buf_rchn
input [63:0] ext_buf_rdata, // Latency of ram_1kx32w_512x64r plus 2
// Interface to memory read channels (up to 16)
......@@ -154,7 +156,8 @@ module mcontr_sequencer #(
output ext_buf_wr,
output ext_buf_wpage_nxt, // increment external buffer write address to next page start
// output [6:0] ext_buf_waddr, // valid with ext_buf_wr
output [3:0] ext_buf_wchn, // ==run_chn_d valid 1 cycle ahead of ext_buf_wr!, maybe not needed - will be generated externally
output [3:0] ext_buf_wchn, // external buffer channel with timing matching buffer writes
output ext_buf_wrefresh, // was refresh, invalidates ext_buf_wchn
output [63:0] ext_buf_wdata, // valid with ext_buf_wr
// temporary debug data
output [11:0] tmp_debug
......@@ -244,9 +247,14 @@ module mcontr_sequencer #(
// reg [1:0] buf_page; // one of 4 pages in the channel buffer to use for R/W
// reg [15:0] buf_sel_1hot; // 1 hot channel buffer select
wire [3:0] run_chn_w_d; // run chn delayed to match buf_wr delay
wire run_refresh_w_d; // run refresh delayed to match buf_wr delay
reg [3:0] run_chn_d;
reg run_refresh_d;
reg [3:0] run_chn_w_d_negedge;
reg run_refresh_w_d_negedge;
// reg run_seq_d;
......@@ -275,12 +283,14 @@ module mcontr_sequencer #(
assign ext_buf_rpage_nxt=buf_raddr_reset;
// assign ext_buf_raddr= buf_raddr;
assign ext_buf_rchn= run_chn_d;
assign ext_buf_rrefresh= run_refresh_d;
assign buf_rdata[63:0] = ext_buf_rdata;
assign ext_buf_wr= buf_wr_negedge;
assign ext_buf_wpage_nxt=buf_waddr_reset_negedge;
// assign ext_buf_waddr= buf_waddr_negedge;
assign ext_buf_wchn= run_chn_w_d_negedge;
assign ext_buf_wrefresh= run_refresh_w_d_negedge;
assign ext_buf_wdata= buf_wdata_negedge;
// generation of the control signals from byte-serial channel
......@@ -445,6 +455,10 @@ module mcontr_sequencer #(
if (rst) run_chn_d <= 0;
else if (run_seq) run_chn_d <= run_chn;
if (rst) run_refresh_d <= 0;
else if (run_seq) run_refresh_d <= run_refresh;
// if (rst) run_seq_d <= 0;
// else run_seq_d <= run_seq;
......@@ -456,6 +470,7 @@ module mcontr_sequencer #(
buf_wr_negedge <= buf_wr;
buf_wdata_negedge <= buf_wdata;
run_chn_w_d_negedge <= run_chn_w_d; //run_chn_d;
run_refresh_w_d_negedge <= run_refresh_w_d;
end
// Command sequence memories:
......@@ -595,12 +610,12 @@ module mcontr_sequencer #(
);
assign wbuf_delay_m1=wbuf_delay-1;
dly_16 #(4) buf_wchn_dly_i (
dly_16 #(5) buf_wchn_dly_i (
.clk(mclk), // input
.rst(1'b0), // input
.dly(wbuf_delay_m1), //wbuf_delay[3:0]-1), // input[3:0]
.din(run_chn_d), // input
.dout(run_chn_w_d) // output reg
.din({run_refresh_d, run_chn_d}), // input
.dout({run_refresh_w_d,run_chn_w_d}) // output reg
);
//run_chn_w_d
endmodule
......
......@@ -21,52 +21,55 @@
`timescale 1ns/1ps
module scheduler16 #(
parameter width=16
parameter width=16, // counter number of bits
parameter n_chn=16 // number of channels
)(
input rst,
input clk,
input [width-1:0] chn_en, // channel enable mask
input [width-1:0] want_rq, // both want_rq and need_rq should go inactive after being granted
input [width-1:0] need_rq,
input [n_chn-1:0] chn_en, // channel enable mask
input [n_chn-1:0] want_rq, // both want_rq and need_rq should go inactive after being granted
input [n_chn-1:0] need_rq,
input en_schedul, // needs to be disabled before next access can be scheduled
output need, // granted access is "needed" one, not just "wanted"
output grant, // single-cycle granted channel access
output [3:0] grant_chn, // granted channel number, valid with grant, stays valid until en_schedul is deasserted
// todo: add programming sequencer address for software sequencer program? Or should it come from the channel?
input [3:0] pgm_addr, // channel address to program priority
input [width-1:0] pgm_data, // priority data for the channel
input pgm_en // enable programming priority data (use different clock?)
);
reg [width*16-1:0] pri_reg;
reg [15:0] want_conf, need_conf,need_want_conf;
wire [15:0] want_set,need_set;
reg [15:0] want_set_r,need_set_r;
reg need_r;
reg [width*16-1:0] sched_state;
wire need_some=|(need_rq & & chn_en);
wire [15:0] next_want_conf,next_need_conf;
wire [3:0] index; // channel index to select
wire index_valid; // selected index valid ("needed" or "wanted")
reg grant_r; // 1 cycle long
reg grant_sent; // turns on after grant, until en_schedul is de-asserted
reg [3:0] grant_chn_r;
wire grant_w;
assign next_want_conf=(want_conf & want_rq & chn_en) | want_set;
assign next_need_conf=(need_conf & need_rq & chn_en) | need_set;
reg [width*n_chn-1:0] pri_reg; // priorities for each channel (start values for priority counters)
reg [n_chn-1:0] want_conf, need_conf,need_want_conf,need_want_conf_d;
wire [n_chn-1:0] want_set,need_set;
// reg [n_chn-1:0] want_set_r,need_set_r;
reg [n_chn-1:0] want_need_set_r;
reg need_r, need_r2;
reg [width*n_chn-1:0] sched_state; // priority counters for each channel
wire need_some=|(need_rq & chn_en);
wire [n_chn-1:0] next_want_conf,next_need_conf;
wire [n_chn-1:0] need_want_conf_w;
wire [3:0] index; // channel index to select
wire index_valid; // selected index valid ("needed" or "wanted")
reg grant_r; // 1 cycle long
reg grant_sent; // turns on after grant, until en_schedul is de-asserted
reg [3:0] grant_chn_r;
wire grant_w;
assign grant=grant_r;
assign grant_chn=grant_chn_r;
assign grant_w=en_schedul && index_valid && !grant_sent;
assign grant_w=en_schedul && index_valid && !grant_sent && !grant;
// Setting priority for each channel
generate
genvar i;
for (i=0;i<16;i=i+1) begin: pri_reg_block
for (i=0;i<n_chn;i=i+1) begin: pri_reg_block
always @ (posedge rst or posedge clk) begin
if (rst) pri_reg[width*i +: width] <= 0;
if (rst) pri_reg[width*i +: width] <= 0;
else if (pgm_en && (pgm_addr==i)) pri_reg[width*i +: width] <= pgm_data;
end
end
endgenerate
pri1hot16 i_pri1hot16_want(
// priority 1-hot encoders to make sure only one want/need request is "confirmed" in each clock cycle
// TODO: Make pri1hot16 parameter-configurable to be able to change priorities later
pri1hot16 i_pri1hot16_want( // priority encoder, 1-hot output (lowest bit has highest priority)
.in(want_rq & ~want_conf & chn_en),
.out(want_set),
.some());
......@@ -75,6 +78,9 @@ module scheduler16 #(
.out(need_set),
.some());
assign next_want_conf= (want_conf & want_rq & chn_en) | want_set;
assign next_need_conf= (need_conf & need_rq & chn_en) | need_set;
assign need_want_conf_w=need_some? next_need_conf: next_want_conf;
always @(posedge rst or posedge clk) begin
if (rst) begin
want_conf <= 0;
......@@ -82,13 +88,16 @@ module scheduler16 #(
end else begin
want_conf <= next_want_conf;
need_conf <= next_need_conf;
need_want_conf<= need_some? next_need_conf: next_want_conf;
need_want_conf <= need_want_conf_w; // need_some? next_need_conf: next_want_conf;
need_want_conf_d <= need_want_conf & need_want_conf_w; // delay for on, no delay for off
end
end
always @ (posedge clk) begin
want_set_r<=want_set;
need_set_r<=need_set;
need_r<= need_some;
// want_set_r<=want_set;
// need_set_r<=need_set;
want_need_set_r <= want_set | need_set;
need_r <= need_some;
need_r2 <= need_r;
end
// TODO: want remains, need is removed (both need and want should be deactivated on grant!)
// Block that sets initial process state and increments it on every change of the requests
......@@ -96,24 +105,26 @@ module scheduler16 #(
genvar i1;
for (i1=0;i1<16;i1=i1+1) begin: sched_state_block
always @ (posedge rst or posedge clk) begin
if (rst) pri_reg[width*i1 +: width] <= 0; // not needed?
else begin
if (want_set_r[i1] || need_set_r[i1]) sched_state[width*i1 +: width] <= pri_reg[width*i1 +: width];
// if (rst) sched_state[width*i1 +: width] <= 0; // not needed?
// else
begin
// if (want_set_r[i1] || need_set_r[i1]) sched_state[width*i1 +: width] <= pri_reg[width*i1 +: width];
if (want_need_set_r[i1]) sched_state[width*i1 +: width] <= pri_reg[width*i1 +: width];
// increment, but do not roll over
else if (&sched_state[width*i1 +: width] == 0) sched_state[width*i1 +: width]<=sched_state[width*i1 +: width]+1;
else if (&sched_state[width*i1 +: width] == 0) sched_state[width*i1 +: width] <= sched_state[width*i1 +: width]+1;
end
end
end
endgenerate
// Select the process to run
index_max_16 #(width) i_index_max_16(
.clk(clk),
.values(sched_state),
.mask(need_want_conf),
.need_in(need_r),
.index(index[3:0]),
.valid(index_valid),
.need_out(need));
.clk (clk),
.values (sched_state),
.mask (need_want_conf_d),
.need_in (need_r2),
.index (index[3:0]),
.valid (index_valid),
.need_out (need));
always @(posedge rst or posedge clk) begin
if (rst) begin
grant_r <=0;
......
......@@ -35,11 +35,19 @@ module index_max_16 #(
wire [width-1:0] max0001020304050607,max0809101112131415;
wire sel0001,sel0203,sel0405,sel0607,sel0809,sel1011,sel1213,sel1415,sel00010203,sel04050607;
wire sel08091011, sel12131415, sel0001020304050607,sel0809101112131415, sel;
wire msk0001,msk0203,msk0405,msk0607,msk0809,msk1011,msk1213,msk1415,msk00010203,msk04050607;
wire msk08091011, msk12131415, msk0001020304050607,msk0809101112131415; //, msk;
reg sel0001_r,sel0203_r,sel0405_r,sel0607_r,sel0809_r,sel1011_r,sel1213_r,sel1415_r;
reg [1:0] sel00010203_r,sel04050607_r,sel08091011_r, sel12131415_r;
reg [2:0] sel0001020304050607_r,sel0809101112131415_r;
reg [3:0] valid_dly;
reg [3:0] need_dly;
reg [15:0] mask_prev; // previous value of mask (invalidate if mask changes)
wire mask_changed;
// assign mask_changed= mask!=mask_prev;
assign mask_changed= |(~mask &mask_prev); // only invalidate if any bit goes off (granted)
// 1-st layer
masked_max_reg #(width) i_masked_max_reg0001(
......@@ -49,7 +57,8 @@ module index_max_16 #(
.b(values[width*1 +: width]),
.mask_b(mask[1]),
.max(max0001),
.s(sel0001));
.s(sel0001),
.valid(msk0001));
masked_max_reg #(width) i_masked_max_reg0203(
.clk(clk),
.a(values[width*2 +: width]),
......@@ -57,7 +66,8 @@ module index_max_16 #(
.b(values[width*3 +: width]),
.mask_b(mask[3]),
.max(max0203),
.s(sel0203));
.s(sel0203),
.valid(msk0203));
masked_max_reg #(width) i_masked_max_reg0405(
.clk(clk),
.a(values[width*4 +: width]),
......@@ -65,7 +75,8 @@ module index_max_16 #(
.b(values[width*5 +: width]),
.mask_b(mask[5]),
.max(max0405),
.s(sel0405));
.s(sel0405),
.valid(msk0405));
masked_max_reg #(width) i_masked_max_reg0607(
.clk(clk),
.a(values[width*6 +: width]),
......@@ -73,7 +84,8 @@ module index_max_16 #(
.b(values[width*7 +: width]),
.mask_b(mask[7]),
.max(max0607),
.s(sel0607));
.s(sel0607),
.valid(msk0607));
masked_max_reg #(width) i_masked_max_reg0809(
.clk(clk),
.a(values[width*8 +: width]),
......@@ -81,7 +93,8 @@ module index_max_16 #(
.b(values[width*9 +: width]),
.mask_b(mask[9]),
.max(max0809),
.s(sel0809));
.s(sel0809),
.valid(msk0809));
masked_max_reg #(width) i_masked_max_reg1011(
.clk(clk),
.a(values[width*10 +: width]),
......@@ -89,7 +102,8 @@ module index_max_16 #(
.b(values[width*11 +: width]),
.mask_b(mask[11]),
.max(max1011),
.s(sel1011));
.s(sel1011),
.valid(msk1011));
masked_max_reg #(width) i_masked_max_reg1213(
.clk(clk),
.a(values[width*12 +: width]),
......@@ -97,7 +111,8 @@ module index_max_16 #(
.b(values[width*13 +: width]),
.mask_b(mask[13]),
.max(max1213),
.s(sel1213));
.s(sel1213),
.valid(msk1213));
masked_max_reg #(width) i_masked_max_reg1415(
.clk(clk),
.a(values[width*14 +: width]),
......@@ -105,67 +120,75 @@ module index_max_16 #(
.b(values[width*15 +: width]),
.mask_b(mask[15]),
.max(max1415),
.s(sel1415));
.s(sel1415),
.valid(msk1415));
// 2-nd layer
masked_max_reg #(width) i_masked_max_reg00010203(
.clk(clk),
.a(max0001),
.mask_a(&mask[1:0]),
.mask_a(msk0001),
.b(max0203),
.mask_b(&mask[3:2]),
.mask_b(msk0203),
.max(max00010203),
.s(sel00010203));
.s(sel00010203),
.valid(msk00010203));
masked_max_reg #(width) i_masked_max_reg04050607(
.clk(clk),
.a(max0405),
.mask_a(&mask[5:4]),
.mask_a(msk0405),
.b(max0607),
.mask_b(&mask[7:6]),
.mask_b(msk0607),
.max(max04050607),
.s(sel04050607));
.s(sel04050607),
.valid(msk04050607));
masked_max_reg #(width) i_masked_max_reg08091011(
.clk(clk),
.a(max0809),
.mask_a(&mask[9:8]),
.mask_a(msk0809),
.b(max1011),
.mask_b(&mask[11:10]),
.mask_b(msk1011),
.max(max08091011),
.s(sel08091011));
.s(sel08091011),
.valid(msk08091011));
masked_max_reg #(width) i_masked_max_reg12131415(
.clk(clk),
.a(max1213),
.mask_a(&mask[13:12]),
.mask_a(msk1213),
.b(max1415),
.mask_b(&mask[15:14]),
.mask_b(msk1415),
.max(max12131415),
.s(sel12131415));
.s(sel12131415),
.valid(msk12131415));
// 3-nd layer
masked_max_reg #(width) i_masked_max_reg0001020304050607(
.clk(clk),
.a(max00010203),
.mask_a(&mask[3:0]),
.mask_a(msk00010203),
.b(max04050607),
.mask_b(&mask[7:4]),
.mask_b(msk04050607),
.max(max0001020304050607),
.s(sel0001020304050607));
.s(sel0001020304050607),
.valid(msk0001020304050607));
masked_max_reg #(width) i_masked_max_reg0809101112131415(
.clk(clk),
.a(max08091011),
.mask_a(&mask[11:8]),
.mask_a(msk08091011),
.b(max12131415),
.mask_b(&mask[15:12]),
.mask_b(msk12131415),
.max(max0809101112131415),
.s(sel0809101112131415));
.s(sel0809101112131415),
.valid(msk0809101112131415));
// 4-th layer
masked_max_reg #(width) i_masked_max_reg(
.clk(clk),
.a(max0001020304050607),
.mask_a(&mask[7:0]),
.mask_a(msk0001020304050607),
.b(max0809101112131415),
.mask_b(&mask[15:8]),
.mask_b(msk0809101112131415),
.max(),
.s(sel));
.s(sel),
.valid()); //msk));
always @ (posedge clk) begin
sel0001_r<=sel0001;
sel0203_r<=sel0203;
......@@ -181,14 +204,16 @@ module index_max_16 #(
sel12131415_r[1:0]<={sel12131415,sel12131415?sel1415_r:sel1213_r};
sel0001020304050607_r[2:0]<={sel0001020304050607,sel0001020304050607?sel04050607_r[1:0]:sel00010203_r[1:0]};
sel0809101112131415_r[2:0]<={sel0809101112131415,sel0809101112131415?sel12131415_r[1:0]:sel08091011_r[1:0]};
valid_dly[3:0] <= {valid_dly[2:0],|mask[15:0]};
valid_dly[3:0] <= {valid_dly[2:0],|mask[15:0] & ~mask_changed}; // invalidate when mask changed (or only if new is zero?
need_dly[3:0] <= {need_dly[2:0],need_in};
mask_prev <= mask;
end
assign index[3:0]={
sel,
sel?sel0809101112131415_r[2:0]:sel0001020304050607_r[2:0]};
assign valid=valid_dly[3];
//assign valid=valid_dly[3];
assign valid=&valid_dly; // need && |mask ?
assign need_out=need_dly[3];
endmodule
......@@ -29,16 +29,21 @@ module masked_max_reg#(
input [width-1:0] b,
input mask_b,
output [width-1:0] max,
output s
output s,
output valid // at least one of the inputs was valid (matches outputs)
);
reg [width-1:0] max_r;
reg s_r;
reg valid_r;
assign s=s_r;
assign max=max_r;
wire s_w= mask_b && ((mask_a && (b>a)) || !mask_a);
assign valid=valid_r;
// wire s_w= mask_b && ((mask_a && (b>a)) || !mask_a);
wire s_w= mask_b && (!mask_a || (b>a));
always @ (posedge clk) begin
s_r <= s_w;
max_r <= (mask_a || mask_b)? (s_w?b:a): 0;
max_r <= (mask_a || mask_b)? (s_w?b:a): {width{1'b0}};
valid_r <= mask_a || mask_b;
end
endmodule
......@@ -26,6 +26,7 @@ module mcont_common_chnbuf_reg #(
input rst,
input clk,
input [3:0] ext_buf_rchn, // ==run_chn_d valid 1 cycle ahead opf ext_buf_rd!, maybe not needed - will be generated externally
input ext_buf_rrefresh,
input ext_buf_rpage_nxt,
input seq_done, // sequence done
output reg buf_done, // sequence done for the specified channel
......@@ -34,12 +35,12 @@ module mcont_common_chnbuf_reg #(
reg buf_chn_sel;
always @ (posedge rst or posedge clk) begin
if (rst) buf_chn_sel <= 0;
else buf_chn_sel <= (ext_buf_rchn==CHN_NUMBER);
else buf_chn_sel <= (ext_buf_rchn==CHN_NUMBER) && !ext_buf_rrefresh;
if (rst) buf_done <= 0;
else buf_done <= buf_chn_sel && seq_done;
end
always @ (posedge clk) rpage_nxt <= ext_buf_rpage_nxt && (ext_buf_rchn==CHN_NUMBER);
always @ (posedge clk) rpage_nxt <= ext_buf_rpage_nxt && (ext_buf_rchn==CHN_NUMBER) && !ext_buf_rrefresh;
endmodule
......@@ -29,6 +29,7 @@ module mcont_from_chnbuf_reg #(
input ext_buf_rd,
// input ext_buf_raddr_rst,
input [3:0] ext_buf_rchn, // ==run_chn_d valid 1 cycle ahead opf ext_buf_rd!, maybe not needed - will be generated externally
input ext_buf_rrefresh,
// input seq_done, // sequence done
// output reg buf_done, // sequence done for the specified channel
output reg [63:0] ext_buf_rdata, // Latency of ram_1kx32w_512x64r plus 2
......@@ -40,7 +41,7 @@ module mcont_from_chnbuf_reg #(
reg [CHN_LATENCY:0] latency_reg=0;
always @ (posedge rst or posedge clk) begin
if (rst) buf_chn_sel <= 0;
else buf_chn_sel <= (ext_buf_rchn==CHN_NUMBER);
else buf_chn_sel <= (ext_buf_rchn==CHN_NUMBER) && !ext_buf_rrefresh;
if (rst) buf_rd_chn <= 0;
else buf_rd_chn <= buf_chn_sel && ext_buf_rd;
......
......@@ -27,7 +27,8 @@ parameter CHN_NUMBER=0
input clk,
input ext_buf_wr,
input ext_buf_wpage_nxt,
input [3:0] ext_buf_wchn, // ==run_chn_d valid 1 cycle ahead opf ext_buf_wr!, maybe not needed - will be generated externally
input [3:0] ext_buf_wchn, //
input ext_buf_wrefresh,
input [63:0] ext_buf_wdata, // valid with ext_buf_wr
// input seq_done, // sequence done
// output reg buf_done, // @ posedge mclk sequence done for the specified channel
......@@ -38,7 +39,7 @@ parameter CHN_NUMBER=0
reg buf_chn_sel;
always @ (posedge rst or negedge clk) begin
if (rst) buf_chn_sel <= 0;
else buf_chn_sel <= (ext_buf_wchn==CHN_NUMBER);
else buf_chn_sel <= (ext_buf_wchn==CHN_NUMBER) && !ext_buf_wrefresh;
if (rst) buf_wr_chn <= 0;
else buf_wr_chn <= buf_chn_sel && ext_buf_wr;
......@@ -50,7 +51,7 @@ parameter CHN_NUMBER=0
// end
always @ (negedge clk) begin
buf_wpage_nxt_chn <= ext_buf_wpage_nxt && (ext_buf_wchn==CHN_NUMBER);
buf_wpage_nxt_chn <= ext_buf_wpage_nxt && (ext_buf_wchn==CHN_NUMBER) && !ext_buf_wrefresh;
end
always @ (negedge clk) if (buf_chn_sel && ext_buf_wr) begin
......
This diff is collapsed.
......@@ -202,7 +202,8 @@ always #(CLKIN_PERIOD/2) CLK <= ~CLK;
axi_set_b_lag(0); //(1);
axi_set_rd_lag(0);
program_status_all(3,'h2a); // mode auto with sequence number increment
//...
enable_memcntrl(1); // enable memory controller
set_up;
wait_phase_shifter_ready;
......@@ -217,6 +218,23 @@ always #(CLKIN_PERIOD/2) CLK <= ~CLK;
repeat (16) @(posedge CLK) ;
enable_cke(1);
repeat (16) @(posedge CLK) ;
// enable_memcntrl(1); // enable memory controller
enable_memcntrl_channels(16'h0003); // only channel 0 and 1 are enabled
configure_channel_priority(0,0); // lowest priority channel 0
configure_channel_priority(1,0); // lowest priority channel 1
enable_reset_ps_pio(1,0); // enable, no reset
schedule_ps_pio ( // shedule software-control memory operation (may need to check FIFO status first)
INITIALIZE_OFFSET, // input [9:0] seq_addr; // sequence start address
0, // input [1:0] page; // buffer page number
0, // input urgent; // high priority request (only for competion wityh other channels, wiil not pass in this FIFO)
0); // input chn; // channel buffer to use: 0 - memory read, 1 - memory write
repeat (32) @(posedge CLK) ; // what delay is needed to be sure? Add to PS_PIO?
enable_refresh(1);
/*
run_mrs;
......@@ -231,7 +249,7 @@ always #(CLKIN_PERIOD/2) CLK <= ~CLK;
#2000;
#20000;
$finish;
end
// protect from never end
......@@ -866,10 +884,49 @@ endtask
task enable_refresh;
input en;
begin
write_contol_register(MCONTR_PHY_0BIT_ADDR + MCONTR_TOP_0BIT_REFRESH_EN + en, 0);
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
begin
write_contol_register(MCNTRL_PS_ADDR + MCNTRL_PS_CMD, {18'b0,chn,urgent,page,seq_addr});
end
endtask
task write_block_buf;
integer i, j;
......@@ -1219,8 +1276,8 @@ task set_refresh;
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_PHY_16BIT_ADDR + MCONTR_TOP_16BIT_REFRESH_ADDRESS, REFRESH_OFFSET);
write_contol_register(MCONTR_PHY_16BIT_ADDR + MCONTR_TOP_16BIT_REFRESH_PERIOD, {24'h0,t_refi});
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
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment