|
@@ -18,13 +18,12 @@
|
|
|
//
|
|
|
// Two ports are provided: port 0 is single byte per transaction,
|
|
|
// and has highest priority; it is intended for transactions from the
|
|
|
-// ABC-bus. Port 1 does 4-byte accesses with arbitrary alignment and
|
|
|
-// byte enables.
|
|
|
+// ABC-bus. Port 1 does aligned 4-byte accesses with byte enables.
|
|
|
//
|
|
|
// All signals are in the sdram clock domain.
|
|
|
//
|
|
|
// [rw]ack is asserted at the beginning of a read- or write cycle and
|
|
|
-// deasserted afterwards; rvalid is asserted once all data is read and
|
|
|
+// deasserted afterwards; rready is asserted once all data is read and
|
|
|
// the read data (rdX port) is valid; it remains asserted after the
|
|
|
// transaction is complete and rack is deasserted.
|
|
|
//
|
|
@@ -63,7 +62,7 @@ module sdram
|
|
|
t_refi_lg2 = 10, // 1024 cycles
|
|
|
t_p_lg2 = 15, // 32768 cycles
|
|
|
|
|
|
- burst_lg2 = 1 // Burst length on port 1
|
|
|
+ burst_lg2 = 1 // log2(burst length)
|
|
|
)
|
|
|
(
|
|
|
// Reset and clock
|
|
@@ -88,7 +87,7 @@ module sdram
|
|
|
output reg [7:0] rd0, // Data from SDRAM
|
|
|
input rrq0, // Read request
|
|
|
output reg rack0, // Read ack (transaction started)
|
|
|
- output reg rvalid0, // Read data valid
|
|
|
+ output reg rready0, // Read data valid
|
|
|
|
|
|
input [7:0] wd0, // Data to SDRAM
|
|
|
input wrq0, // Write request
|
|
@@ -96,20 +95,21 @@ module sdram
|
|
|
|
|
|
// Port 1
|
|
|
input [24:2] a1,
|
|
|
- input [7:0] be1, // Write byte enable
|
|
|
|
|
|
output reg [31:0] rd1,
|
|
|
input rrq1,
|
|
|
output reg rack1,
|
|
|
- output reg rvalid1,
|
|
|
+ output reg rready1,
|
|
|
|
|
|
input [31:0] wd1,
|
|
|
- input wrq1,
|
|
|
+ input [3:0] wstrb1,
|
|
|
output reg wack1
|
|
|
);
|
|
|
|
|
|
`include "functions.sv" // For modelsim
|
|
|
|
|
|
+ wire wrq1 = |wstrb1;
|
|
|
+
|
|
|
// Mode register data
|
|
|
wire mrd_wburst = 1'b1; // Write bursts enabled
|
|
|
wire [2:0] mrd_cl = t_cl;
|
|
@@ -203,7 +203,8 @@ module sdram
|
|
|
st_idle, // Idle state: all banks precharged
|
|
|
st_rfsh,
|
|
|
st_rd,
|
|
|
- st_wr
|
|
|
+ st_wr,
|
|
|
+ st_pre_idle
|
|
|
} state_t;
|
|
|
state_t state = st_reset;
|
|
|
|
|
@@ -236,22 +237,9 @@ module sdram
|
|
|
reg op_zero; // op_cycle wrap around
|
|
|
reg [1:0] init_op_ctr; // op_cycle extension for init states
|
|
|
|
|
|
- // Handle bank wraparound
|
|
|
- reg last_dword; // This is the last dword in this bank
|
|
|
- reg [14:0] next_bank; // Row:bank for the next bank
|
|
|
- reg [11:2] col_addr; // Current bank:column
|
|
|
-
|
|
|
- always @(posedge clk)
|
|
|
- begin
|
|
|
- if (op_cycle == 0)
|
|
|
- begin
|
|
|
- next_bank <= { dram_a, dram_ba } + 1'b1;
|
|
|
- last_dword <= &col_addr[9:2]; // last dword in bank?
|
|
|
- end
|
|
|
- end // else: !if(~rst_n)
|
|
|
-
|
|
|
reg [31:0] wdata_q;
|
|
|
- reg [ 7:0] be_q;
|
|
|
+ reg [ 3:0] be_q;
|
|
|
+ reg [ 9:0] col_addr;
|
|
|
|
|
|
//
|
|
|
// Careful with the timing here... there is one cycle between
|
|
@@ -275,32 +263,36 @@ module sdram
|
|
|
state <= st_reset;
|
|
|
|
|
|
rack0 <= 1'b0;
|
|
|
- rvalid0 <= 1'b0;
|
|
|
+ rready0 <= 1'b0;
|
|
|
wack0 <= 1'b0;
|
|
|
|
|
|
rack1 <= 1'b0;
|
|
|
- rvalid1 <= 1'b0;
|
|
|
+ rready1 <= 1'b0;
|
|
|
wack1 <= 1'b0;
|
|
|
|
|
|
wdata_q <= 32'hxxxx_xxxx;
|
|
|
- be_q <= 8'hxx;
|
|
|
+ be_q <= 4'bxxxx;
|
|
|
end
|
|
|
else
|
|
|
begin
|
|
|
dram_cke <= 1'b1; // Always true once out of reset
|
|
|
|
|
|
// Default values
|
|
|
- dram_ba <= 2'bxx;
|
|
|
+ // Note: dram_ba are preserved
|
|
|
+ dram_a <= 13'hxxxx;
|
|
|
dram_dqm <= 2'b00;
|
|
|
dram_d <= 16'hxxxx;
|
|
|
dram_cmd <= cmd_nop;
|
|
|
|
|
|
dram_d_en <= 1'b1; // Don't float except during read
|
|
|
|
|
|
- rack0 <= 1'b0;
|
|
|
- wack0 <= 1'b0;
|
|
|
- rack1 <= 1'b0;
|
|
|
- wack1 <= 1'b0;
|
|
|
+ if (state != st_rd && state != st_wr)
|
|
|
+ begin
|
|
|
+ rack0 <= 1'b0;
|
|
|
+ wack0 <= 1'b0;
|
|
|
+ rack1 <= 1'b0;
|
|
|
+ wack1 <= 1'b0;
|
|
|
+ end
|
|
|
|
|
|
if (state == st_reset || state == st_idle)
|
|
|
op_cycle <= 1'b0;
|
|
@@ -318,6 +310,7 @@ module sdram
|
|
|
if (init_ctr[t_p_lg2])
|
|
|
state <= st_init_rfsh;
|
|
|
end
|
|
|
+
|
|
|
st_init_rfsh:
|
|
|
begin
|
|
|
dram_a[10] <= 1'b1; // Refresh all banks
|
|
@@ -330,6 +323,7 @@ module sdram
|
|
|
state <= st_init_mrd;
|
|
|
end
|
|
|
end
|
|
|
+
|
|
|
st_init_mrd:
|
|
|
begin
|
|
|
dram_a <= mrd_val;
|
|
@@ -339,6 +333,7 @@ module sdram
|
|
|
else
|
|
|
dram_cmd <= cmd_mrd;
|
|
|
end
|
|
|
+
|
|
|
st_idle:
|
|
|
begin
|
|
|
// A data transaction starts with ACTIVE command;
|
|
@@ -355,19 +350,20 @@ module sdram
|
|
|
dram_cmd <= cmd_act;
|
|
|
dram_a <= a0[24:12];
|
|
|
dram_ba <= a0[11:10];
|
|
|
- col_addr <= a0[11:2];
|
|
|
- be_q <= 1'b1 << a0[1:0];
|
|
|
+ col_addr <= a0[9:0];
|
|
|
if ( wrq0 )
|
|
|
begin
|
|
|
state <= st_wr;
|
|
|
wack0 <= 1'b1;
|
|
|
- wdata_q <= {4{wd0}};
|
|
|
+ wdata_q <= {16'hxxxx, wd0, wd0};
|
|
|
+ be_q <= {2'b00, a0[0], ~a0[0]};
|
|
|
end
|
|
|
else
|
|
|
begin
|
|
|
state <= st_rd;
|
|
|
rack0 <= 1'b1;
|
|
|
- rvalid0 <= 1'b0;
|
|
|
+ rready0 <= 1'b0;
|
|
|
+ be_q <= 4'b1111;
|
|
|
end
|
|
|
end
|
|
|
4'b010?:
|
|
@@ -376,19 +372,20 @@ module sdram
|
|
|
dram_cmd <= cmd_act;
|
|
|
dram_a <= a1[24:12];
|
|
|
dram_ba <= a1[11:10];
|
|
|
- col_addr <= a1[11:2];
|
|
|
- be_q <= be1;
|
|
|
+ col_addr <= { a1[9:2], 2'b00 };
|
|
|
if ( wrq1 )
|
|
|
begin
|
|
|
state <= st_wr;
|
|
|
wack1 <= 1'b1;
|
|
|
wdata_q <= wd1;
|
|
|
+ be_q <= wstrb1;
|
|
|
end
|
|
|
else
|
|
|
begin
|
|
|
state <= st_rd;
|
|
|
rack1 <= 1'b1;
|
|
|
- rvalid1 <= 1'b0;
|
|
|
+ rready1 <= 1'b0;
|
|
|
+ be_q <= 4'b1111;
|
|
|
end
|
|
|
end
|
|
|
4'b0?1?, 4'b0001:
|
|
@@ -402,19 +399,18 @@ module sdram
|
|
|
dram_cmd <= cmd_desl;
|
|
|
state <= st_idle;
|
|
|
end
|
|
|
- endcase // casez ( {rrq0|wrq0, rrq1|wrq1, rfsh_ctr[t_ref:t_ref-1]} )
|
|
|
+ endcase // casez ( {rrq0|wrq0, rrq1|wrq1, rfsh_prio} )
|
|
|
end // case: st_idle
|
|
|
+
|
|
|
st_rfsh:
|
|
|
begin
|
|
|
if (op_cycle == t_rfc-2)
|
|
|
state <= st_idle;
|
|
|
end
|
|
|
- st_rd:
|
|
|
- begin
|
|
|
- rack0 <= rack0;
|
|
|
- rack1 <= rack1;
|
|
|
|
|
|
- dram_d_en <= 1'b0; // Tristate data bus
|
|
|
+ st_rd, st_wr:
|
|
|
+ begin
|
|
|
+ dram_d_en <= (state == st_wr);
|
|
|
|
|
|
// Commands
|
|
|
//
|
|
@@ -423,123 +419,46 @@ module sdram
|
|
|
// rRRD = 2
|
|
|
// CL = 3
|
|
|
// tRC = 10
|
|
|
- case (op_cycle)
|
|
|
- 1: begin
|
|
|
- dram_a <= next_bank[14:2];
|
|
|
- dram_ba <= next_bank[1:0];
|
|
|
- dram_cmd <= last_dword ? cmd_act : cmd_nop;
|
|
|
- end
|
|
|
- 2, 4: begin
|
|
|
- dram_a[12:9] <= 4'b0000;
|
|
|
- dram_a[8:1] <= col_addr[9:2];
|
|
|
- dram_a[0] <= 1'b0;
|
|
|
- dram_cmd <= cmd_rd;
|
|
|
- col_addr <= col_addr + 1'b1;
|
|
|
- end
|
|
|
- 8: begin
|
|
|
- // Precharge all banks
|
|
|
- dram_a[12:9] <= 4'b0010;
|
|
|
- dram_cmd <= cmd_pre;
|
|
|
- end
|
|
|
- 10: begin
|
|
|
- state <= st_idle;
|
|
|
- rack0 <= 1'b0;
|
|
|
- rack1 <= 1'b0;
|
|
|
- end
|
|
|
- endcase // case (op_cycle)
|
|
|
-
|
|
|
- // +2 for bus turnaround latencies
|
|
|
- // Assert rvalid in the same cycle the last requested
|
|
|
- // data byte (as given by byte enables) is latched.
|
|
|
-
|
|
|
- if (op_cycle >= 2+t_cl+2)
|
|
|
- begin
|
|
|
- if (rack0)
|
|
|
- begin
|
|
|
- rvalid0 <= ~|be_q[7:2];
|
|
|
-
|
|
|
- if (be_q[0])
|
|
|
- rd0 <= dram_q[7:0];
|
|
|
- if (be_q[1])
|
|
|
- rd0 <= dram_q[15:8];
|
|
|
- end
|
|
|
- if (rack1)
|
|
|
- begin
|
|
|
- rvalid1 <= ~|be_q[7:2];
|
|
|
-
|
|
|
- if (op_cycle[0] ^ ((2+t_cl+2) & 1'b1))
|
|
|
- begin
|
|
|
- // Odd word
|
|
|
- if (be_q[0])
|
|
|
- rd1[23:16] <= dram_q[ 7:0];
|
|
|
- if (be_q[1])
|
|
|
- rd1[31:24] <= dram_q[15:8];
|
|
|
- end
|
|
|
- else
|
|
|
- begin
|
|
|
- // Even word
|
|
|
- if (be_q[0])
|
|
|
- rd1[ 7:0] <= dram_q[ 7:0];
|
|
|
- if (be_q[1])
|
|
|
- rd1[15:8] <= dram_q[15:8];
|
|
|
- end // else: !if(op_cycle[0] ^ ((t_rcd-1+t_cl+2) & 1'b1))
|
|
|
- end // if (rack1)
|
|
|
-
|
|
|
- be_q <= be_q >> 2;
|
|
|
- end // if (op_cycle >= 2+t_cl+2)
|
|
|
- end // case: st_rd
|
|
|
-
|
|
|
- st_wr:
|
|
|
- begin
|
|
|
- wack0 <= wack0;
|
|
|
- wack1 <= wack1;
|
|
|
-
|
|
|
- dram_dqm <= 2'b11; // Mask data bytes unless we mean it
|
|
|
-
|
|
|
- // Commands
|
|
|
//
|
|
|
- // This assumes:
|
|
|
- // tRCD = 3
|
|
|
- // tRRD = 2
|
|
|
- // CL = 3
|
|
|
- // tRC = 10
|
|
|
- // tWR = 2
|
|
|
- // tRP = 3
|
|
|
case (op_cycle)
|
|
|
- 1: begin
|
|
|
- dram_a <= next_bank[14:2];
|
|
|
- dram_ba <= next_bank[1:0];
|
|
|
- dram_cmd <= last_dword ? cmd_act : cmd_nop;
|
|
|
+ 2: begin
|
|
|
+ dram_a[10] <= 1'b1; // Auto precharge
|
|
|
+ dram_a[8:0] <= col_addr[9:1];
|
|
|
+ dram_cmd <= (state == st_wr) ? cmd_wr : cmd_rd;
|
|
|
+ dram_d <= wdata_q[15:0];
|
|
|
+ wdata_q <= { 16'hxxxx, wdata_q[31:16] };
|
|
|
+ dram_dqm <= ~be_q[1:0];
|
|
|
+ be_q <= { 2'bxx, be_q[3:2] };
|
|
|
end
|
|
|
- 2, 4: begin
|
|
|
- dram_a[12:9] <= 4'b0000;
|
|
|
- dram_a[8:1] <= col_addr[9:2];
|
|
|
- dram_a[0] <= 1'b0;
|
|
|
- dram_cmd <= cmd_wr;
|
|
|
- col_addr <= col_addr + 1'b1;
|
|
|
+ 3: begin
|
|
|
+ dram_d <= wdata_q[15:0];
|
|
|
+ dram_dqm <= ~be_q[1:0];
|
|
|
+ wdata_q <= 32'hxxxx_xxxx;
|
|
|
+ be_q <= 4'bxxxx;
|
|
|
end
|
|
|
+ // CL+2 cycles after the read command
|
|
|
7: begin
|
|
|
- // Precharge all banks
|
|
|
- dram_a[12:9] <= 4'b0010;
|
|
|
- dram_cmd <= cmd_pre;
|
|
|
+ if (rack0)
|
|
|
+ rd0 <= col_addr[0] ? dram_q[15:8] : dram_q[7:0];
|
|
|
+ rready0 <= rready0 | rack0;
|
|
|
+ if (rack1)
|
|
|
+ rd1[15:0] <= dram_q;
|
|
|
end
|
|
|
- 10: begin
|
|
|
- state <= st_idle;
|
|
|
- wack0 <= 1'b0;
|
|
|
- wack1 <= 1'b0;
|
|
|
+ 8: begin
|
|
|
+ if (rack1)
|
|
|
+ rd1[31:16] <= dram_q;
|
|
|
+ rready1 <= rready1 | rack1;
|
|
|
+ // Last cycle before tRC is a separate state
|
|
|
+ // so that rack/wack will be cleared
|
|
|
+ state <= st_pre_idle;
|
|
|
end
|
|
|
endcase // case (op_cycle)
|
|
|
+ end // case: st_rd, st_wr
|
|
|
|
|
|
- if (op_cycle >= 2)
|
|
|
- begin
|
|
|
- dram_d <= wdata_q[15:0];
|
|
|
- // Flip data between odd and even words
|
|
|
- wdata_q <= { wdata_q[15:0], wdata_q[31:16] };
|
|
|
- dram_dqm <= ~be_q[1:0];
|
|
|
-
|
|
|
- be_q <= be_q >> 2;
|
|
|
- end
|
|
|
- end // case: st_wr
|
|
|
+ st_pre_idle:
|
|
|
+ begin
|
|
|
+ state <= st_idle;
|
|
|
+ end
|
|
|
endcase // case(state)
|
|
|
end // else: !if(~rst_n)
|
|
|
endmodule // dram
|