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

Subversion Repositories hpdmc

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /
    from Rev 3 to Rev 4
    Reverse comparison

Rev 3 → Rev 4

/trunk/test/tb_hpdmc.v
262,6 → 262,32
end
endtask
 
task wbwrite;
input [31:0] address;
input [63:0] data;
integer i;
begin
wb_adr_i = address;
wb_dat_i = data;
wb_cyc_i = 1'b1;
wb_stb_i = 1'b1;
wb_sel_i = 8'hff;
wb_we_i = 1'b1;
wb_cti_i = 3'b000;
i = 0;
#1;
while(~wb_ack_o) begin
i = i+1;
waitclock;
end
wb_cyc_i = 1'b0;
wb_stb_i = 1'b0;
wb_we_i = 1'b0;
$display("Memory Write : %x=%x acked in %d clocks", address, data, i);
waitclock;
end
endtask
 
always begin
$dumpfile("hpdmc.vcd");
 
380,7 → 406,7
/*
* Try some transfers.
*/
/*
wb_nextadr = 32'h00000020;
wb_nextadr_valid = 1'b1;
wbreadburst(32'h00);
389,9 → 415,11
wb_nextadr = 32'h00000060;
wbreadburst(32'h40);
wb_nextadr_valid = 1'b0;
wbreadburst(32'h60);
wbreadburst(32'h60);*/
waitclock;
wbwrite(32'h00000000, 64'h1111222233334444);
waitnclock(10);
wbreadburst(32'h00);
$finish;
end
/trunk/rtl/hpdmc.v
179,7 → 179,8
 
wire op_write;
wire op_read;
wire buffer_w_load;
wire buffer_w_next;
wire buffer_w_nextburst;
wire buffer_r_next;
wire buffer_r_nextburst;
 
191,7 → 192,8
.op_write(op_write),
.op_read(op_read),
.buffer_w_load(buffer_w_load),
.buffer_w_next(buffer_w_next),
.buffer_w_nextburst(buffer_w_nextburst),
.buffer_w_mask(~wb_sel_i),
.buffer_w_dat(wb_dat_i),
240,7 → 242,8
.op_write(op_write),
.op_read(op_read),
.buffer_w_load(buffer_w_load),
.buffer_w_next(buffer_w_next),
.buffer_w_nextburst(buffer_w_nextburst),
.buffer_w_mask(buffer_w_mask),
.buffer_w_dat(buffer_w_dat),
/trunk/rtl/hpdmc_ddrio.v
32,7 → 32,8
input op_write,
input op_read,
input buffer_w_load,
input buffer_w_next,
input buffer_w_nextburst,
input [7:0] buffer_w_mask,
input [63:0] buffer_w_dat,
63,12 → 64,26
always @(posedge rst, posedge clk) begin
if(rst)
wfifo_produce <= 2'b00;
else if(buffer_w_load) begin
wfifo_produce <= wfifo_produce + 1;
wfifomask1[wfifo_produce] <= buffer_w_mask[7:4];
wfifomask0[wfifo_produce] <= buffer_w_mask[3:0];
wfifo1[wfifo_produce] <= buffer_w_dat[63:32];
wfifo0[wfifo_produce] <= buffer_w_dat[31:0];
else begin
if(buffer_w_nextburst) begin
wfifo_produce <= 2'b00;
wfifomask1[0] <= 4'b1111;
wfifomask1[1] <= 4'b1111;
wfifomask1[2] <= 4'b1111;
wfifomask1[3] <= 4'b1111;
wfifomask0[0] <= 4'b1111;
wfifomask0[1] <= 4'b1111;
wfifomask0[2] <= 4'b1111;
wfifomask0[3] <= 4'b1111;
end else if(buffer_w_next)
wfifo_produce <= wfifo_produce + 1;
if(buffer_w_next) begin
$display("Pushing into Write FIFO Mask %h", buffer_w_mask);
wfifomask1[wfifo_produce] <= buffer_w_mask[7:4];
wfifomask0[wfifo_produce] <= buffer_w_mask[3:0];
wfifo1[wfifo_produce] <= buffer_w_dat[63:32];
wfifo0[wfifo_produce] <= buffer_w_dat[31:0];
end
end
end
 
113,7 → 128,7
 
 
/*
* Read FIFO, 8-word deep
* Read FIFO, 8-word deep
*/
 
reg read_enable;
/trunk/rtl/hpdmc_scheduler.v
58,7 → 58,8
output op_write,
output op_read,
output buffer_w_load,
output reg buffer_w_next,
output reg buffer_w_nextburst,
output [7:0] buffer_w_mask,
output [63:0] buffer_w_dat,
70,6 → 71,7
/* Fetch queue */
 
reg wishbone_req;
reg wishbone_we;
reg [sdram_depth-3-1:0] wishbone_adr;
reg prefetch_req;
reg [sdram_depth-3-1:0] prefetch_adr;
79,7 → 81,8
wishbone_req <= 1'b0;
prefetch_req <= 1'b0;
end else begin
wishbone_req <= wb_cyc_i & wb_stb_i & ~wb_we_i & ~wb_ack_o;
wishbone_req <= wb_cyc_i & wb_stb_i & ~wb_ack_o;
wishbone_we <= wb_we_i;
wishbone_adr <= wb_adr_i[sdram_depth-1:3];
prefetch_req <= wb_nextadr_valid;
prefetch_adr <= wb_nextadr[sdram_depth-1:3];
87,24 → 90,30
end
 
reg next_address_valid;
reg next_address_we;
reg [sdram_depth-3-1:0] next_address;
reg address_valid;
/* if the address_we bit is set to 1, this means that the WB is waiting on write ;
* it is safe to send the Write command immediately as the bus will be
* able to supply the data.
*/
reg address_we;
reg [sdram_depth-3-1:0] address;
reg fetched_address_valid;
reg write_valid;
reg [sdram_depth-3-1:0] fetched_address;
 
wire wishbone_req_valid = wishbone_req
& ((wishbone_adr != next_address) | ~next_address_valid)
& ((wishbone_adr != address) | ~address_valid)
& ((wishbone_adr != fetched_address) | ~fetched_address_valid);
& ((wishbone_adr != next_address) | (wishbone_we != next_address_we) | ~next_address_valid)
& ((wishbone_adr != address) | (wishbone_we != address_we) | ~address_valid)
& ((wishbone_adr != fetched_address) | (wishbone_we != write_valid) | ~(fetched_address_valid|write_valid));
 
wire prefetch_req_valid = prefetch_req
& ((prefetch_adr != next_address) | ~next_address_valid)
& ((prefetch_adr != address) | ~address_valid)
& ((prefetch_adr != next_address) | ~next_address_valid)
& ((prefetch_adr != address) | ~address_valid)
& ((prefetch_adr != fetched_address) | ~fetched_address_valid);
 
reg fq_clearfetch;
reg fq_clear;
reg fq_next;
 
always @(posedge sdram_rst, posedge sys_clk) begin
112,60 → 121,56
next_address_valid <= 1'b0;
address_valid <= 1'b0;
fetched_address_valid <= 1'b0;
write_valid <= 1'b0;
end else begin
if(fq_clear) begin
if(fq_next) begin
fetched_address_valid <= address_valid & ~address_we;
write_valid <= address_valid & address_we;
fetched_address <= address;
end else if(fq_clearfetch)
fetched_address_valid <= 1'b0;
if(fq_next) begin
next_address_valid <= 1'b0;
address_valid <= 1'b0;
fetched_address_valid <= 1'b0;
next_address_we <= 1'b0;
address_valid <= next_address_valid;
address_we <= next_address_we;
address <= next_address;
end else begin
if(fq_next) begin
$display("FQ Next");
$display("Fetched addr %x (valid %b)", address, address_valid);
fetched_address_valid <= address_valid;
fetched_address <= address;
end else if(fq_clearfetch)
fetched_address_valid <= 1'b0;
if(fq_next) begin
next_address_valid <= 1'b0;
address_valid <= next_address_valid;
address <= next_address;
end else begin
case({next_address_valid, address_valid, wishbone_req_valid, prefetch_req_valid})
4'b0001: begin
$display("********** PREFETCH in current address");
address_valid <= 1'b1;
address <= prefetch_adr;
end
4'b0010: begin
$display("********** WISHBONE in current address");
$display("Fetched addr %x (valid %b)", fetched_address, fetched_address_valid);
address_valid <= 1'b1;
address <= wishbone_adr;
end
4'b0011: begin
$display("********** WISHBONE+PREFETCH");
next_address_valid <= 1'b1;
next_address <= prefetch_adr;
address_valid <= 1'b1;
address <= wishbone_adr;
end
4'b0101: begin
$display("********** PREFETCH in next address");
next_address_valid <= 1'b1;
next_address <= prefetch_adr;
end
4'b0110: begin
$display("********** WISHBONE in next address");
next_address_valid <= 1'b1;
next_address <= wishbone_adr;
end
4'b0111: begin
$display("********** WISHBONE in next address/2");
next_address_valid <= 1'b1;
next_address <= wishbone_adr;
end
endcase
end
case({next_address_valid, address_valid, wishbone_req_valid, prefetch_req_valid})
4'b0001: begin
address_valid <= 1'b1;
address_we <= 1'b0;
address <= prefetch_adr;
end
4'b0010: begin
address_valid <= 1'b1;
address_we <= wishbone_we;
address <= wishbone_adr;
end
4'b0011: begin
next_address_valid <= 1'b1;
next_address_we <= 1'b0;
next_address <= prefetch_adr;
address_valid <= 1'b1;
address_we <= wishbone_we;
address <= wishbone_adr;
end
4'b0101: begin
next_address_valid <= 1'b1;
next_address_we <= 1'b0;
next_address <= prefetch_adr;
end
4'b0110: begin
next_address_valid <= 1'b1;
next_address_we <= wishbone_we;
next_address <= wishbone_adr;
end
4'b0111: begin
next_address_valid <= 1'b1;
next_address_we <= wishbone_we;
next_address <= wishbone_adr;
end
endcase
end
end
end
195,10 → 200,6
if(sdram_rst) begin
has_openrow = 4'h0;
end else begin
if(has_openrow != ((has_openrow | track_open) & ~track_close)) begin
$display("openrows: %b->%b", has_openrow, ((has_openrow | track_open) & ~track_close));
$display("open: %b close %b", track_open, track_close);
end
has_openrow = (has_openrow | track_open) & ~track_close;
if(track_open[0]) openrows[0] <= row_address;
296,6 → 297,39
autorefresh_counter <= autorefresh_counter - 4'd1;
end
 
/* Control the DDRIO block */
 
wire start_ddrio_read = (cas_counter == 2'd1);
reg [1:0] readburst_counter;
wire readburst_done = (readburst_counter == 2'd0);
always @(posedge sdram_rst, posedge sys_clk) begin
if(sdram_rst)
readburst_counter <= 2'd0;
else begin
if(start_ddrio_read)
readburst_counter <= 2'd3;
else if(~readburst_done)
readburst_counter <= readburst_counter - 2'd1;
end
end
assign op_read = ~readburst_done;
 
reg start_ddrio_write;
reg [2:0] writeburst_counter;
wire writeburst_done = (writeburst_counter == 3'd0);
always @(posedge sdram_rst, posedge sys_clk) begin
if(sdram_rst)
writeburst_counter <= 3'd0;
else begin
if(start_ddrio_write)
writeburst_counter <= 3'd4;
else if(~writeburst_done)
writeburst_counter <= writeburst_counter - 3'd1;
end
end
assign op_write = ~writeburst_done;
 
 
/* FSM that pushes commands into the SDRAM */
 
reg [3:0] state;
302,10 → 336,12
reg [3:0] next_state;
 
parameter IDLE = 4'd0;
parameter ACTIVATE_BEFORE_READ = 4'd1;
parameter ACTIVATE = 4'd1;
parameter READ = 4'd2;
parameter AUTOREFRESH = 4'd3;
parameter AUTOREFRESH_WAIT = 4'd4;
parameter WRITE = 4'd3;
parameter PRECHARGEALL = 4'd4;
parameter AUTOREFRESH = 4'd5;
parameter AUTOREFRESH_WAIT = 4'd6;
 
always @(posedge sdram_rst, posedge sys_clk) begin
if(sdram_rst)
334,38 → 370,46
sdram_adr_loadcol = 1'b0;
sdram_adr_loadA10 = 1'b0;
fq_clear = 1'b0;
fq_next = 1'b0;
track_close = 4'b0000;
track_open = 4'b0000;
start_ddrio_write = 1'b0;
 
case(state)
IDLE: begin
if(must_refresh) begin
/* Precharge All */
sdram_cs = 1'b1;
sdram_ras = 1'b1;
sdram_cas = 1'b0;
sdram_we = 1'b1;
sdram_adr_loadA10 = 1'b1;
reload_precharge_counter = 1'b1;
next_state = AUTOREFRESH;
end else begin
if(must_refresh)
next_state = PRECHARGEALL;
else begin
if(address_valid) begin
if(page_hit) begin
/* Read */
if(~fetched_address_valid | fq_clearfetch) begin
sdram_cs = 1'b1;
sdram_ras = 1'b0;
sdram_cas = 1'b1;
sdram_we = 1'b0;
sdram_adr_loadcol = 1'b1;
reload_cas_counter = 1'b1;
fq_next = 1'b1;
if(address_we) begin
if(readburst_done & (~write_valid | fq_clearfetch)) begin
/* Write */
sdram_cs = 1'b1;
sdram_ras = 1'b0;
sdram_cas = 1'b1;
sdram_we = 1'b1;
sdram_adr_loadcol = 1'b1;
start_ddrio_write = 1'b1;
fq_next = 1'b1;
end
end else begin
if(writeburst_done & (~fetched_address_valid | fq_clearfetch)) begin
/* Read */
sdram_cs = 1'b1;
sdram_ras = 1'b0;
sdram_cas = 1'b1;
sdram_we = 1'b0;
sdram_adr_loadcol = 1'b1;
reload_cas_counter = 1'b1;
fq_next = 1'b1;
end
end
end else begin
if(bank_open) begin
377,7 → 421,7
track_close[bank_address] = 1'b1;
reload_precharge_counter = 1'b1;
next_state = ACTIVATE_BEFORE_READ;
next_state = ACTIVATE;
end else begin
/* Activate */
sdram_cs = 1'b1;
388,7 → 432,10
track_open[bank_address] = 1'b1;
reload_activate_counter = 1'b1;
next_state = READ;
if(address_we)
next_state = WRITE;
else
next_state = READ;
end
end
end
395,7 → 442,7
end
end
ACTIVATE_BEFORE_READ: begin
ACTIVATE: begin
if(precharge_done) begin
sdram_cs = 1'b1;
sdram_ras = 1'b1;
409,20 → 456,52
end
end
READ: begin
if(activate_done & (~fetched_address_valid | fq_clearfetch)) begin
sdram_cs = 1'b1;
sdram_ras = 1'b0;
sdram_cas = 1'b1;
sdram_we = 1'b0;
sdram_adr_loadcol = 1'b1;
reload_cas_counter = 1'b1;
fq_next = 1'b1;
next_state = IDLE;
if(activate_done) begin
if(must_refresh)
next_state = PRECHARGEALL;
else if(writeburst_done & (~fetched_address_valid | fq_clearfetch)) begin
sdram_cs = 1'b1;
sdram_ras = 1'b0;
sdram_cas = 1'b1;
sdram_we = 1'b0;
sdram_adr_loadcol = 1'b1;
reload_cas_counter = 1'b1;
fq_next = 1'b1;
next_state = IDLE;
end
end
end
WRITE: begin
if(activate_done) begin
if(must_refresh)
next_state = PRECHARGEALL;
else if(readburst_done & (~write_valid | fq_clearfetch)) begin
sdram_cs = 1'b1;
sdram_ras = 1'b0;
sdram_cas = 1'b1;
sdram_we = 1'b1;
sdram_adr_loadcol = 1'b1;
start_ddrio_write = 1'b1;
fq_next = 1'b1;
next_state = IDLE;
end
end
end
PRECHARGEALL: begin
sdram_cs = 1'b1;
sdram_ras = 1'b1;
sdram_cas = 1'b0;
sdram_we = 1'b1;
sdram_adr_loadA10 = 1'b1;
reload_precharge_counter = 1'b1;
next_state = AUTOREFRESH;
end
AUTOREFRESH: begin
track_close = 4'b1111;
if(precharge_done) begin
443,19 → 522,6
endcase
end
 
/* Control the DDRIO block */
 
wire start_ddrio_read = (cas_counter == 2'd1);
reg [1:0] readburst_counter;
wire readburst_done = (readburst_counter == 2'd0);
always @(posedge sys_clk) begin
if(start_ddrio_read)
readburst_counter <= 2'd3;
else if(~readburst_done)
readburst_counter <= readburst_counter - 2'd1;
end
assign op_read = ~readburst_done;
 
/* Service WISHBONE requests */
 
reg [3:0] wstate;
465,6 → 531,7
parameter WPROCESS_READ = 4'd1;
parameter WBURST_READ = 4'd2;
parameter WPROCESS_WRITE = 4'd3;
parameter WBURST_WRITE = 4'd4;
 
always @(posedge sdram_rst, posedge sys_clk) begin
if(sdram_rst)
507,9 → 574,13
fq_clearfetch = 1'b0;
buffer_r_next = 1'b0;
buffer_r_nextburst = 1'b0;
buffer_w_next = 1'b0;
buffer_w_nextburst = 1'b0;
case(wstate)
WIDLE: begin
buffer_w_nextburst = 1'b1;
buffer_r_nextburst = 1'b1;
if(wb_cyc_i & wb_stb_i) begin
if(wb_we_i)
next_wstate = WPROCESS_WRITE;
525,12 → 596,10
wb_ack_o = 1'b1;
buffer_r_next = 1'b1;
reload_maxburst_counter = 1'b1;
if(burst_on) begin
if(burst_on)
next_wstate = WBURST_READ;
end else begin
buffer_r_nextburst = 1'b1;
else
next_wstate = WIDLE;
end
end
end
end
538,15 → 607,27
WBURST_READ: begin
wb_ack_o = 1'b1;
buffer_r_next = 1'b1;
if(~burst_on | maxburst_done) begin
buffer_r_nextburst = 1'b1;
if(~burst_on | maxburst_done)
next_wstate = WIDLE;
end
end
WPROCESS_WRITE: begin
fq_clearfetch = 1'b1;
if(write_valid) begin
wb_ack_o = 1'b1;
buffer_w_next = 1'b1;
reload_maxburst_counter = 1'b1;
if(burst_on)
next_wstate = WBURST_WRITE;
else
next_wstate = WIDLE;
end
end
WBURST_WRITE: begin
wb_ack_o = 1'b1;
next_wstate = WIDLE;
buffer_w_next = 1'b1;
if(~burst_on | maxburst_done)
next_wstate = WIDLE;
end
endcase
end

powered by: WebSVN 2.1.0

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