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 |