Line 78... |
Line 78... |
o_wb_ack, o_wb_stall, o_wb_data,
|
o_wb_ack, o_wb_stall, o_wb_data,
|
o_ddr_reset_n, o_ddr_cke,
|
o_ddr_reset_n, o_ddr_cke,
|
o_ddr_cs_n, o_ddr_ras_n, o_ddr_cas_n, o_ddr_we_n,
|
o_ddr_cs_n, o_ddr_ras_n, o_ddr_cas_n, o_ddr_we_n,
|
o_ddr_dqs, o_ddr_dm, o_ddr_odt, o_ddr_bus_oe,
|
o_ddr_dqs, o_ddr_dm, o_ddr_odt, o_ddr_bus_oe,
|
o_ddr_addr, o_ddr_ba, o_ddr_data, i_ddr_data);
|
o_ddr_addr, o_ddr_ba, o_ddr_data, i_ddr_data);
|
parameter CKREFI4 = 13'd6240, // 4 * 7.8us at 200 MHz clock
|
parameter CKRBITS = 13, // Bits in CKREFI4
|
|
CKREFI4 = 13'd6240, // 4 * 7.8us at 200 MHz clock
|
CKRFC = 320,
|
CKRFC = 320,
|
CKWR = 3,
|
CKWR = 3,
|
CKXPR = CKRFC+5+2; // Clocks per tXPR timeout
|
CKXPR = CKRFC+5+2; // Clocks per tXPR timeout
|
input i_clk, i_reset;
|
input i_clk, i_reset;
|
// Wishbone inputs
|
// Wishbone inputs
|
Line 98... |
Line 99... |
// Control outputs
|
// Control outputs
|
output wire o_ddr_cs_n, o_ddr_ras_n, o_ddr_cas_n,o_ddr_we_n;
|
output wire o_ddr_cs_n, o_ddr_ras_n, o_ddr_cas_n,o_ddr_we_n;
|
// DQS outputs:set to 3'b010 when data is active, 3'b100 (i.e. 2'bzz) ow
|
// DQS outputs:set to 3'b010 when data is active, 3'b100 (i.e. 2'bzz) ow
|
output wire o_ddr_dqs;
|
output wire o_ddr_dqs;
|
output reg o_ddr_dm;
|
output reg o_ddr_dm;
|
output wire o_ddr_odt, o_ddr_bus_oe;
|
output reg o_ddr_odt;
|
|
output wire o_ddr_bus_oe;
|
// Address outputs
|
// Address outputs
|
output wire [13:0] o_ddr_addr;
|
output wire [13:0] o_ddr_addr;
|
output wire [2:0] o_ddr_ba;
|
output wire [2:0] o_ddr_ba;
|
// And the data inputs and outputs
|
// And the data inputs and outputs
|
output reg [31:0] o_ddr_data;
|
output reg [31:0] o_ddr_data;
|
Line 491... |
Line 493... |
refresh_ztimer <= 1'b0;
|
refresh_ztimer <= 1'b0;
|
refresh_counter <= refresh_instruction[16:0];
|
refresh_counter <= refresh_instruction[16:0];
|
end
|
end
|
|
|
wire [16:0] w_ckREFIn, w_ckREFRst;
|
wire [16:0] w_ckREFIn, w_ckREFRst;
|
assign w_ckREFIn[ 12: 0] = CKREFI4-5*CKRFC-2-10;
|
assign w_ckREFIn[(CKRBITS-1): 0] = CKREFI4-5*CKRFC-2-10;
|
assign w_ckREFIn[ 16:13] = 4'h0;
|
assign w_ckREFIn[ 16:(CKRBITS)] = 0;
|
assign w_ckREFRst[12: 0] = CKRFC-2-12;
|
assign w_ckREFRst = CKRFC-2-12;
|
assign w_ckREFRst[16:13] = 4'h0;
|
|
|
|
always @(posedge i_clk)
|
always @(posedge i_clk)
|
if (reset_override)
|
if (reset_override)
|
refresh_cmd <= { `DDR_NOOP, w_ckREFIn };
|
refresh_cmd <= { `DDR_NOOP, w_ckREFIn };
|
else if (refresh_ztimer)
|
else if (refresh_ztimer)
|
Line 538... |
Line 539... |
//
|
//
|
// Let's track: when will our bus be active? When will we be reading or
|
// Let's track: when will our bus be active? When will we be reading or
|
// writing?
|
// writing?
|
//
|
//
|
//
|
//
|
reg [`BUSNOW:0] bus_active, bus_read, bus_new;
|
reg [`BUSNOW:0] bus_active, bus_read, bus_new, bus_ack;
|
reg [1:0] bus_subaddr [`BUSNOW:0];
|
reg [1:0] bus_subaddr [`BUSNOW:0];
|
initial bus_active = 0;
|
initial bus_active = 0;
|
always @(posedge i_clk)
|
always @(posedge i_clk)
|
begin
|
begin
|
bus_active[`BUSNOW:0] <= { bus_active[(`BUSNOW-1):0], 1'b0 };
|
bus_active[`BUSNOW:0] <= { bus_active[(`BUSNOW-1):0], 1'b0 };
|
bus_read[`BUSNOW:0] <= { bus_read[(`BUSNOW-1):0], 1'b0 }; // Drive the d-bus?
|
bus_read[`BUSNOW:0] <= { bus_read[(`BUSNOW-1):0], 1'b0 }; // Drive the d-bus?
|
// Is this a new command? i.e., the start of a transaction?
|
// Is this a new command? i.e., the start of a transaction?
|
bus_new[`BUSNOW:0] <= { bus_new[(`BUSNOW-1):0], 1'b0 };
|
bus_new[`BUSNOW:0] <= { bus_new[(`BUSNOW-1):0], 1'b0 };
|
|
// Will this position on the bus get a wishbone acknowledgement?
|
|
bus_ack[`BUSNOW:0] <= { bus_ack[(`BUSNOW-1):0], 1'b0 };
|
//bus_mask[8:0] <= { bus_mask[7:0], 1'b1 }; // Write this value?
|
//bus_mask[8:0] <= { bus_mask[7:0], 1'b1 }; // Write this value?
|
bus_subaddr[8] <= bus_subaddr[7];
|
bus_subaddr[8] <= bus_subaddr[7];
|
bus_subaddr[7] <= bus_subaddr[6];
|
bus_subaddr[7] <= bus_subaddr[6];
|
bus_subaddr[6] <= bus_subaddr[5];
|
bus_subaddr[6] <= bus_subaddr[5];
|
bus_subaddr[5] <= bus_subaddr[4];
|
bus_subaddr[5] <= bus_subaddr[4];
|
bus_subaddr[4] <= bus_subaddr[3];
|
bus_subaddr[4] <= bus_subaddr[3];
|
bus_subaddr[3] <= bus_subaddr[2];
|
bus_subaddr[3] <= bus_subaddr[2];
|
bus_subaddr[2] <= bus_subaddr[1];
|
bus_subaddr[2] <= bus_subaddr[1];
|
bus_subaddr[1] <= bus_subaddr[0];
|
bus_subaddr[1] <= bus_subaddr[0];
|
bus_subaddr[0] <= 2'h3;
|
bus_subaddr[0] <= 2'h3;
|
|
|
|
bus_ack[5] <= (bus_ack[4])&&
|
|
((bus_subaddr[5] != bus_subaddr[4])
|
|
||(bus_new[4]));
|
if (w_this_rw_move)
|
if (w_this_rw_move)
|
begin
|
begin
|
bus_active[3:0]<= 4'hf; // Once per clock
|
bus_active[3:0]<= 4'hf; // Once per clock
|
bus_read[3:0] <= 4'hf; // These will be reads
|
|
bus_subaddr[3] <= 2'h0;
|
bus_subaddr[3] <= 2'h0;
|
bus_subaddr[2] <= 2'h1;
|
bus_subaddr[2] <= 2'h1;
|
bus_subaddr[1] <= 2'h2;
|
bus_subaddr[1] <= 2'h2;
|
bus_new[{ 2'b0, rw_sub }] <= 1'b1;
|
bus_new[{ 2'b0, rw_sub }] <= 1'b1;
|
|
bus_ack[{ 2'b0, rw_sub }] <= 1'b1;
|
|
|
bus_read[3:0] <= (rw_we)? 4'h0:4'hf;
|
bus_read[3:0] <= (rw_we)? 4'h0:4'hf;
|
|
end else if ((s_pending)&&(!pipe_stall))
|
|
begin
|
|
if (bus_subaddr[3] == s_sub)
|
|
bus_ack[4] <= 1'b1;
|
|
if (bus_subaddr[2] == s_sub)
|
|
bus_ack[3] <= 1'b1;
|
|
if (bus_subaddr[1] == s_sub)
|
|
bus_ack[2] <= 1'b1;
|
end
|
end
|
end
|
end
|
|
|
|
// Need to set o_wb_dqs high one clock prior to any read.
|
always @(posedge i_clk)
|
always @(posedge i_clk)
|
drive_dqs <= (~bus_read[`BUSREG])&&(|bus_active[`BUSREG]);
|
drive_dqs <= (|bus_active[`BUSREG:(`BUSREG-1)])
|
|
&&(~(|bus_read[`BUSREG:(`BUSREG-1)]));
|
|
|
//
|
//
|
//
|
//
|
// Now, let's see, can we issue a read command?
|
// Now, let's see, can we issue a read command?
|
//
|
//
|
Line 786... |
Line 803... |
last_maybe_open <= 1'b1;
|
last_maybe_open <= 1'b1;
|
end else
|
end else
|
cmd <= { `DDR_NOOP, rw_cmd[(`DDR_WEBIT-1):0] };
|
cmd <= { `DDR_NOOP, rw_cmd[(`DDR_WEBIT-1):0] };
|
end
|
end
|
|
|
`define LGFIFOLN 4
|
`define LGFIFOLN 3
|
`define FIFOLEN 16
|
`define FIFOLEN 8
|
reg [(`LGFIFOLN-1):0] bus_fifo_head, bus_fifo_tail;
|
reg [(`LGFIFOLN-1):0] bus_fifo_head, bus_fifo_tail;
|
reg [31:0] bus_fifo_data [0:(`FIFOLEN-1)];
|
reg [31:0] bus_fifo_data [0:(`FIFOLEN-1)];
|
reg [1:0] bus_fifo_sub [0:(`FIFOLEN-1)];
|
reg [1:0] bus_fifo_sub [0:(`FIFOLEN-1)];
|
reg bus_fifo_new [0:(`FIFOLEN-1)];
|
reg bus_fifo_new [0:(`FIFOLEN-1)];
|
reg pre_ack;
|
reg pre_ack;
|
|
|
// The bus R/W FIFO
|
// The bus R/W FIFO
|
wire w_bus_fifo_read_next_transaction;
|
wire w_bus_fifo_read_next_transaction;
|
assign w_bus_fifo_read_next_transaction =
|
assign w_bus_fifo_read_next_transaction = (bus_ack[`BUSREG]);
|
(bus_fifo_sub[bus_fifo_tail]==bus_subaddr[`BUSREG])
|
|
&&(bus_fifo_tail != bus_fifo_head)
|
|
&&(bus_active[`BUSREG])
|
|
&&(bus_new[`BUSREG] == bus_fifo_new[bus_fifo_tail]);
|
|
always @(posedge i_clk)
|
always @(posedge i_clk)
|
begin
|
begin
|
pre_ack <= 1'b0;
|
pre_ack <= 1'b0;
|
o_ddr_dm <= 1'b0;
|
o_ddr_dm <= 1'b0;
|
if ((i_reset)||(reset_override))
|
if (reset_override)
|
begin
|
begin
|
bus_fifo_head <= 4'h0;
|
bus_fifo_head <= {(`LGFIFOLN){1'b0}};
|
bus_fifo_tail <= 4'h0;
|
bus_fifo_tail <= {(`LGFIFOLN){1'b0}};
|
o_ddr_dm <= 1'b0;
|
o_ddr_dm <= 1'b0;
|
end else begin
|
end else begin
|
if
|
if ((s_pending)&&(!pipe_stall))
|
//((w_this_rw_move)||((s_pending)&&(s_match)&&(!pipe_stall)))
|
bus_fifo_head <= bus_fifo_head + 1'b1;
|
((s_pending)&&(!pipe_stall))
|
|
bus_fifo_head <= bus_fifo_head + 4'h1;
|
|
|
|
o_ddr_dm <= (bus_active[`BUSREG])&&(!bus_read[`BUSREG]);
|
o_ddr_dm <= (bus_active[`BUSREG])&&(!bus_read[`BUSREG]);
|
if (w_bus_fifo_read_next_transaction)
|
if (w_bus_fifo_read_next_transaction)
|
begin
|
begin
|
bus_fifo_tail <= bus_fifo_tail + 4'h1;
|
bus_fifo_tail <= bus_fifo_tail + 1'b1;
|
pre_ack <= 1'b1;
|
pre_ack <= 1'b1;
|
o_ddr_dm <= 1'b0;
|
o_ddr_dm <= 1'b0;
|
end
|
end
|
end
|
end
|
bus_fifo_data[bus_fifo_head] <= s_data;
|
bus_fifo_data[bus_fifo_head] <= s_data;
|
bus_fifo_sub[bus_fifo_head] <= s_sub;
|
bus_fifo_sub[bus_fifo_head] <= s_sub;
|
bus_fifo_new[bus_fifo_head] <= w_this_rw_move;
|
bus_fifo_new[bus_fifo_head] <= w_this_rw_move;
|
|
|
|
//
|
|
// if ((s_pending)&&(!pipe_stall)&&(!nxt_valid))
|
|
// nxt_fifo_data <= s_data;
|
|
// nxt_fifo_sub <= s_sub;
|
|
// nxt_fifo_new <= w_this_rw_move;
|
|
// nxt_valid <= 1'b1;
|
|
// bus_fifo_head <= bus_fifo_head+1;
|
|
// bus_fifo_tail <= bus_fifo_tail+1;
|
|
// else if (w_bus_fifo_read_next_transaction)
|
|
// nxt_fifo_data <= bus_fifo_data[bus_fifo_tail]
|
|
// nxt_fifo_sub <= bus_fifo_data[bus_fifo_tail]
|
|
// nxt_fifo_new <= bus_fifo_data[bus_fifo_tail]
|
|
// nxt_valid <= (bus_fifo_tail+1 == bus_fifo_head);
|
|
//
|
|
// if ((!valid)||(w_bus_fifo_next_read_transaction))
|
|
// nxt_ <= bus_fifo_x
|
end
|
end
|
|
|
|
|
assign o_ddr_cs_n = cmd[`DDR_CSBIT];
|
assign o_ddr_cs_n = cmd[`DDR_CSBIT];
|
assign o_ddr_ras_n = cmd[`DDR_RASBIT];
|
assign o_ddr_ras_n = cmd[`DDR_RASBIT];
|
Line 842... |
Line 870... |
always @(posedge i_clk)
|
always @(posedge i_clk)
|
o_ddr_data <= bus_fifo_data[bus_fifo_tail];
|
o_ddr_data <= bus_fifo_data[bus_fifo_tail];
|
assign w_precharge_all = (cmd[`DDR_CSBIT:`DDR_WEBIT]==`DDR_PRECHARGE)
|
assign w_precharge_all = (cmd[`DDR_CSBIT:`DDR_WEBIT]==`DDR_PRECHARGE)
|
&&(o_ddr_addr[10]); // 5 bits
|
&&(o_ddr_addr[10]); // 5 bits
|
|
|
// Need to set o_wb_dqs high one clock prior to any read.
|
assign o_ddr_bus_oe = drive_dqs; // ~bus_read[`BUSNOW];
|
// As per spec, ODT = 0 during reads
|
|
assign o_ddr_bus_oe = ~bus_read[`BUSNOW];
|
|
|
|
// ODT must be in high impedence while reset_n=0, then it can be set
|
// ODT must be in high impedence while reset_n=0, then it can be set
|
// to low or high.
|
// to low or high. As per spec, ODT = 0 during reads
|
assign o_ddr_odt = o_ddr_bus_oe;
|
always @(posedge i_clk)
|
|
o_ddr_odt <= (bus_active[`BUSREG-3])&&(!bus_read[`BUSREG-3])
|
|
||(bus_active[`BUSREG-4])&&(!bus_read[`BUSREG-4])
|
|
||((w_this_rw_move)&&(rw_we));
|
|
|
always @(posedge i_clk)
|
always @(posedge i_clk)
|
o_wb_ack <= pre_ack;
|
o_wb_ack <= pre_ack;
|
always @(posedge i_clk)
|
always @(posedge i_clk)
|
o_wb_data <= i_ddr_data;
|
o_wb_data <= i_ddr_data;
|