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

Subversion Repositories versatile_mem_ctrl

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /versatile_mem_ctrl/trunk
    from Rev 105 to Rev 106
    Reverse comparison

Rev 105 → Rev 106

/bench/tb.v
24,29 → 24,29
`endif
parameter wb_clk_period = 20;
wire [31:0] wbm_a_dat_o [1:nr_of_wbm];
wire [3:0] wbm_a_sel_o [1:nr_of_wbm];
wire [31:0] wbm_a_adr_o [1:nr_of_wbm];
wire [2:0] wbm_a_cti_o [1:nr_of_wbm];
wire [1:0] wbm_a_bte_o [1:nr_of_wbm];
wire wbm_a_we_o [1:nr_of_wbm];
wire wbm_a_cyc_o [1:nr_of_wbm];
wire wbm_a_stb_o [1:nr_of_wbm];
wire [31:0] wbm_a_dat_i [1:nr_of_wbm];
wire wbm_a_ack_i [1:nr_of_wbm];
reg wbm_a_clk [1:nr_of_wbm];
reg wbm_a_rst [1:nr_of_wbm];
wire [31:0] wbm_a_dat_o;
wire [3:0] wbm_a_sel_o;
wire [31:0] wbm_a_adr_o;
wire [2:0] wbm_a_cti_o;
wire [1:0] wbm_a_bte_o;
wire wbm_a_we_o ;
wire wbm_a_cyc_o;
wire wbm_a_stb_o;
wire [31:0] wbm_a_dat_i;
wire wbm_a_ack_i;
reg wbm_a_clk ;
reg wbm_a_rst ;
 
wire [31:0] wbm_b_dat_o [1:nr_of_wbm];
wire [3:0] wbm_b_sel_o [1:nr_of_wbm];
wire [31:2] wbm_b_adr_o [1:nr_of_wbm];
wire [2:0] wbm_b_cti_o [1:nr_of_wbm];
wire [1:0] wbm_b_bte_o [1:nr_of_wbm];
wire wbm_b_we_o [1:nr_of_wbm];
wire wbm_b_cyc_o [1:nr_of_wbm];
wire wbm_b_stb_o [1:nr_of_wbm];
wire [31:0] wbm_b_dat_i [1:nr_of_wbm];
wire wbm_b_ack_i [1:nr_of_wbm];
wire [31:0] wbm_b_dat_o;
wire [3:0] wbm_b_sel_o;
wire [31:2] wbm_b_adr_o;
wire [2:0] wbm_b_cti_o;
wire [1:0] wbm_b_bte_o;
wire wbm_b_we_o ;
wire wbm_b_cyc_o;
wire wbm_b_stb_o;
wire [31:0] wbm_b_dat_i;
wire wbm_b_ack_i;
 
wire [31:0] wb_sdram_dat_i;
wire [3:0] wb_sdram_sel_i;
61,7 → 61,7
reg wb_sdram_clk;
reg wb_sdram_rst;
wire [1:nr_of_wbm] wbm_OK;
wire wbm_OK;
genvar i;
74,13 → 74,26
wire dq_oe;
wire [1:0] dqm, dqm_pad;
wire cke, cke_pad, cs_n, cs_n_pad, ras, ras_pad, cas, cas_pad, we, we_pad;
vl_o_dff # ( .width(20), .reset_value({2'b00, 13'h0,3'b111,2'b11})) o0(
.d_i({ba,a,ras,cas,we,dqm}),
.o_pad({ba_pad,a_pad,ras_pad, cas_pad, we_pad, dqm_pad}),
.clk(wb_sdram_clk),
.rst(wb_sdram_rst));
/*
assign #1 {ba_pad,a_pad} = {ba,a};
assign #1 {ras_pad, cas_pad, we_pad} = {ras,cas,we};
assign #1 dqm_pad = dqm;
assign #1 dqm_pad = dqm;*/
assign #1 cke_pad = cke;
assign cs_n_pad = cs_n;
vl_io_dff_oe # ( .width(16)) io0 (
.d_i(dq_i),
.d_o(dq_o),
.oe(dq_oe),
.io_pad(dq_pad),
.clk(wb_sdram_clk),
.rst(wb_sdram_rst));
mt48lc16m16a2 mem(
.Dq(dq_pad),
.Addr(a_pad),
92,22 → 105,22
.Cas_n(cas_pad),
.We_n(we_pad),
.Dqm(dqm_pad));
assign #1 dq_pad = (dq_oe) ? dq_o : {`SDR{1'bz}};
assign #1 dq_i = dq_pad;
`DUT DUT(
 
`DUT
# (.tRFC(9), .cl(3))
DUT(
// wisbone i/f
.dat_i(wb_sdram_dat_i),
.adr_i({wb_sdram_adr_i[24:2],1'b0}),
.sel_i(wb_sdram_sel_i),
.cti_i(wb_sdram_cti_i),
.bte_i(wb_sdram_bte_i),
.we_i (wb_sdram_we_i),
.cyc_i(wb_sdram_cyc_i),
.stb_i(wb_sdram_stb_i),
.dat_o(wb_sdram_dat_o),
.ack_o(wb_sdram_ack_o),
.dat_i(wbm_b_dat_o),
.adr_i({wbm_b_adr_o[24:2],1'b0}),
.sel_i(wbm_b_sel_o),
`ifndef NO_BURST
.bte_i(wbm_b_bte_o),
`endif
.we_i (wbm_b_we_o),
.cyc_i(wbm_b_cyc_o),
.stb_i(wbm_b_stb_o),
.dat_o(wbm_b_dat_i),
.ack_o(wbm_b_ack_i),
// SDR SDRAM
.ba(ba),
.a(a),
123,95 → 136,73
`endif
 
// wishbone master(s)
generate
for (i=1; i <= nr_of_wbm; i=i+1) begin: wb_master
// wishbone master
wbm wbmi(
.adr_o(wbm_a_adr_o[i]),
.bte_o(wbm_a_bte_o[i]),
.cti_o(wbm_a_cti_o[i]),
.dat_o(wbm_a_dat_o[i]),
.sel_o(wbm_a_sel_o[i]),
.we_o (wbm_a_we_o[i]),
.cyc_o(wbm_a_cyc_o[i]),
.stb_o(wbm_a_stb_o[i]),
.dat_i(wbm_a_dat_i[i]),
.ack_i(wbm_a_ack_i[i]),
.clk(wbm_a_clk[i]),
.reset(wbm_a_rst[i]),
.OK(wbm_OK[i])
wbm wbmi(
.adr_o(wbm_a_adr_o),
.bte_o(wbm_a_bte_o),
.cti_o(wbm_a_cti_o),
.dat_o(wbm_a_dat_o),
.sel_o(wbm_a_sel_o),
.we_o (wbm_a_we_o),
.cyc_o(wbm_a_cyc_o),
.stb_o(wbm_a_stb_o),
.dat_i(wbm_a_dat_i),
.ack_i(wbm_a_ack_i),
.clk(wbm_a_clk),
.reset(wbm_a_rst),
.OK(wbm_OK)
);
 
wb3wb3_bridge wbwb_bridgei (
vl_wb3wb3_bridge wbwb_bridgei (
// wishbone slave side
.wbs_dat_i(wbm_a_dat_o[i]),
.wbs_adr_i(wbm_a_adr_o[i][31:2]),
.wbs_sel_i(wbm_a_sel_o[i]),
.wbs_bte_i(wbm_a_bte_o[i]),
.wbs_cti_i(wbm_a_cti_o[i]),
.wbs_we_i (wbm_a_we_o[i]),
.wbs_cyc_i(wbm_a_cyc_o[i]),
.wbs_stb_i(wbm_a_stb_o[i]),
.wbs_dat_o(wbm_a_dat_i[i]),
.wbs_ack_o(wbm_a_ack_i[i]),
.wbs_clk(wbm_a_clk[i]),
.wbs_rst(wbm_a_rst[i]),
.wbs_dat_i(wbm_a_dat_o),
.wbs_adr_i(wbm_a_adr_o[31:2]),
.wbs_sel_i(wbm_a_sel_o),
.wbs_bte_i(wbm_a_bte_o),
.wbs_cti_i(wbm_a_cti_o),
.wbs_we_i (wbm_a_we_o),
.wbs_cyc_i(wbm_a_cyc_o),
.wbs_stb_i(wbm_a_stb_o),
.wbs_dat_o(wbm_a_dat_i),
.wbs_ack_o(wbm_a_ack_i),
.wbs_clk(wbm_a_clk),
.wbs_rst(wbm_a_rst),
// wishbone master side
.wbm_dat_o(wbm_b_dat_o[i]),
.wbm_adr_o(wbm_b_adr_o[i]),
.wbm_sel_o(wbm_b_sel_o[i]),
.wbm_bte_o(wbm_b_bte_o[i]),
.wbm_cti_o(wbm_b_cti_o[i]),
.wbm_we_o (wbm_b_we_o[i]),
.wbm_cyc_o(wbm_b_cyc_o[i]),
.wbm_stb_o(wbm_b_stb_o[i]),
.wbm_dat_i(wbm_b_dat_i[i]),
.wbm_ack_i(wbm_b_ack_i[i]),
.wbm_dat_o(wbm_b_dat_o),
.wbm_adr_o(wbm_b_adr_o),
.wbm_sel_o(wbm_b_sel_o),
.wbm_bte_o(wbm_b_bte_o),
.wbm_cti_o(wbm_b_cti_o),
.wbm_we_o (wbm_b_we_o),
.wbm_cyc_o(wbm_b_cyc_o),
.wbm_stb_o(wbm_b_stb_o),
.wbm_dat_i(wbm_b_dat_i),
.wbm_ack_i(wbm_b_ack_i),
.wbm_clk(wb_sdram_clk),
.wbm_rst(wb_sdram_rst));
end
endgenerate
 
`define SINGLE_WB
`ifdef SINGLE_WB
assign wb_sdram_dat_i=wbm_b_dat_o[1];
assign wb_sdram_sel_i=wbm_b_sel_o[1];
assign wb_sdram_adr_i=wbm_b_adr_o[1];
assign wb_sdram_we_i =wbm_b_we_o[1];
assign wb_sdram_bte_i=wbm_b_bte_o[1];
assign wb_sdram_cti_i=wbm_b_cti_o[1];
assign wb_sdram_cyc_i=wbm_b_cyc_o[1];
assign wb_sdram_stb_i=wbm_b_stb_o[1];
assign wbm_b_dat_i[1]=wb_sdram_dat_o;
assign wbm_b_ack_i[1]=wb_sdram_ack_o;
`endif
 
assign OK = &wbm_OK;
assign OK = wbm_OK;
 
generate
for (i=1; i <= nr_of_wbm; i=i+1) begin: wb_reset
 
// Wishbone reset
initial
begin
#0 wbm_a_rst[i] = 1'b1;
#200 wbm_a_rst[i] = 1'b0;
#0 wbm_a_rst = 1'b1;
#200 wbm_a_rst = 1'b0;
end
 
// Wishbone clock
initial
begin
#0 wbm_a_clk[i] = 1'b0;
#0 wbm_a_clk = 1'b0;
forever
#(wb_clk_period/2) wbm_a_clk[i] = !wbm_a_clk[i];
#(wb_clk_period/2) wbm_a_clk = !wbm_a_clk;
end
 
 
end
endgenerate
 
// SDRAM reset
initial
/bench/wbm.v
30,8 → 30,8
parameter [32+2+3+32+4+1+1+1:1] inst_rom [0:instructions-1]= {
{32'h0,linear,classic,32'h0,4'b1111,1'b0,1'b0,1'b0},
{32'h100,linear,classic,32'h12345678,4'b1111,1'b1,1'b1,1'b1},
{32'h100,linear,classic,32'h0,4'b1111,1'b0,1'b1,1'b1},
{32'h100,linear,classic,32'h12345678,4'b1111,1'b1,1'b1,1'b1}, // write 0x12345678 @ 0x100
{32'h100,linear,classic,32'h0,4'b1111,1'b0,1'b1,1'b1}, // read @ 0x100
{32'h0,linear,classic,32'h0,4'b1111,1'b0,1'b0,1'b0},
126,9 → 126,12
else
if (ack_i & !we_o & (dat_i != dat[i])) begin
OK <= 1'b0;
$display ("wrong read value %h at %t", dat_i, $time);
end
$display ("wrong read value %h @ %h at %t", dat_i, adr_o, $time);
end else if (ack_i & !we_o & (dat_i == dat[i]))
$display ("read value %h @ %h at %t", dat_i, adr_o, $time);
else if (ack_i)
$display ("write value %h %b @ %h at %t", dat_o, sel_o, adr_o, $time);
// always @ (posedge clk or posedge reset)
// if (reset)
// state <= idle;
/bench/mt48lc16m16a2.v
119,7 → 119,7
// Write Burst Mode
wire Write_burst_mode = Mode_reg[9];
 
wire Debug = 1'b1; // Debug messages : 1 = On
wire Debug = 1'b0; // Debug messages : 1 = On
wire Dq_chk = Sys_clk & Data_in_enable; // Check setup/hold time for DQ
assign Dq = Dq_reg; // DQ buffer
/rtl/verilog/sdr_sdram_16_ctrl.v
1,16 → 1,27
`timescale 1ns/1ns
module sdr_sdram_16_ctrl (
// wisbone i/f
dat_i, adr_i, sel_i, cti_i, bte_i, we_i, cyc_i, stb_i, dat_o, ack_o,
`ifdef NO_BURST
dat_i, adr_i, sel_i, we_i, cyc_i, stb_i, dat_o, ack_o,
`else
dat_i, adr_i, sel_i, bte_i, we_i, cyc_i, stb_i, dat_o, ack_o,
`endif
// SDR SDRAM
ba, a, cmd, cke, cs_n, dqm, dq_i, dq_o, dq_oe,
// system
clk, rst);
 
// memory geometry parameters
parameter ba_size = 2;
parameter row_size = 13;
parameter col_size = 9;
parameter cl = 2;
 
// memory timing parameters
parameter tRFC = 9;
parameter tRP = 2;
parameter tRCD = 2;
parameter tMRD = 2;
// LMR
// [12:10] reserved
// [9] WB, write burst; 0 - programmed burst length, 1 - single location
19,7 → 30,7
// [3] BT, Burst Type; 1'b0 - sequential, 1'b1 - interleaved
// [2:0] Burst length; 3'b000 - 1, 3'b001 - 2, 3'b010 - 4, 3'b011 - 8, 3'b111 - full page
parameter init_wb = 1'b0;
parameter init_cl = 3'b010;
parameter init_cl = (cl==2) ? 3'b010 : 3'b011;
parameter init_bt = 1'b0;
parameter init_bl = 3'b001;
26,8 → 37,9
input [31:0] dat_i;
input [ba_size+col_size+row_size:1] adr_i;
input [3:0] sel_i;
input [2:0] cti_i;
`ifndef NO_BURST
input [1:0] bte_i;
`endif
input we_i, cyc_i, stb_i;
output [31:0] dat_o;
output ack_o;
34,10 → 46,10
 
output reg [ba_size-1:0] ba;
output reg [12:0] a;
output reg [2:0] cmd;
output reg [2:0] cmd; // {ras,cas,we}
output cke, cs_n;
output reg [1:0] dqm;
output reg [15:0] dq_o;
output [15:0] dq_o;
output reg dq_oe;
input [15:0] dq_i;
 
47,13 → 59,25
wire [row_size-1:0] row;
wire [col_size-1:0] col;
wire [12:0] col_a10_fix;
`ifdef BEAT16
parameter col_reg_width = 5;
reg [4:0] col_reg;
`else
`ifdef BEAT8
parameter col_reg_width = 4;
reg [3:0] col_reg;
`else
`ifdef BEAT4
parameter col_reg_width = 3;
reg [2:0] col_reg;
`endif
`endif
`endif
wire [0:31] shreg;
wire count0;
wire stall; // active if write burst need data
wire ref_cnt_zero;
reg refresh_req;
reg wb_flag;
 
wire ack_rd, rd_ack_emptyflag;
wire ack_wr;
62,7 → 86,7
reg [row_size-1:0] open_row[0:3];
reg [0:3] open_ba;
reg current_bank_closed, current_row_open;
 
`ifndef RFR_WRAP_VALUE
parameter rfr_length = 10;
parameter rfr_wrap_value = 1010;
89,18 → 113,6
cmd_rfr = 3'b001,
cmd_lmr = 3'b000;
 
// LMR
// [12:10] reserved
// [9] WB, write burst; 0 - programmed burst length, 1 - single location
// [8:7] OP Mode, 2'b00
// [6:4] CAS Latency; 3'b010 - 2, 3'b011 - 3
// [3] BT, Burst Type; 1'b0 - sequential, 1'b1 - interleaved
// [2:0] Burst length; 3'b000 - 1, 3'b001 - 2, 3'b010 - 4, 3'b011 - 8, 3'b111 - full page
`define INIT_WB 1'b0
`define INIT_CL 3'b010
`define INIT_BT 1'b0
`define INIT_BL 3'b001
 
// ctrl FSM
`define FSM_INIT 3'b000
`define FSM_IDLE 3'b001
108,7 → 120,6
`define FSM_ADR 3'b011
`define FSM_PCH 3'b100
`define FSM_ACT 3'b101
//`define FSM_WAIT 3'b110
`define FSM_RW 3'b111
 
assign cke = 1'b1;
150,23 → 161,28
next = state;
case (state)
`FSM_INIT:
if (shreg[31]) next = `FSM_IDLE;
if (shreg[3+tRP+tRFC+tRFC+tMRD]) next = `FSM_IDLE;
`FSM_IDLE:
if (refresh_req) next = `FSM_RFR;
else if (cyc_i & stb_i & rd_ack_emptyflag) next = `FSM_ADR;
`FSM_RFR:
if (shreg[8]) next = `FSM_IDLE; // tRFC=60ns, AREF@2
if (shreg[tRP+tRFC-2]) next = `FSM_IDLE; // take away two cycles because no cmd will be issued in idle and adr
`FSM_ADR:
if (current_bank_closed) next = `FSM_ACT;
else if (current_row_open) next = `FSM_RW;
else next = `FSM_PCH;
`FSM_PCH:
if (shreg[1]) next = `FSM_ACT;
if (shreg[tRP]) next = `FSM_ACT;
`FSM_ACT:
if (shreg[2]) next = `FSM_RW;
if (shreg[tRCD]) next = `FSM_RW;
`FSM_RW:
`ifdef NO_BURST
if (shreg[1]) next = `FSM_IDLE;
`else
if (bte_i==linear & shreg[1]) next = `FSM_IDLE;
`ifdef BEAT4
else if (bte_i==beat4 & shreg[7]) next = `FSM_IDLE;
`endif
`ifdef BEAT8
else if (bte_i==beat8 & shreg[15]) next = `FSM_IDLE;
`endif
173,6 → 189,7
`ifdef BEAT16
else if (bte_i==beat16 & shreg[31]) next = `FSM_IDLE;
`endif
`endif
endcase
end
 
183,7 → 200,7
vl_cnt_shreg_ce_clear # ( .length(32))
cnt0 (
.cke(!stall),
.clear(!(state==next)),
.clear(state!=next),
.q(shreg),
.rst(rst),
.clk(clk));
192,7 → 209,7
dff_count0 (
.d(!count0),
.ce(!stall),
.clear(!(state==next)),
.clear(state!=next),
.q(count0),
.rst(rst),
.clk(clk));
199,79 → 216,102
 
// ba, a, cmd
// col_reg_a10 has bit [10] set to zero to disable auto precharge
assign col_a10_fix = a10_fix({col[col_size-1:5],col_reg});
`ifdef NO_BURST
assign col_a10_fix = a10_fix(col);
`else
assign col_a10_fix = a10_fix({col[col_size-1:col_reg_width],col_reg});
`endif
 
// outputs dependent on state vector
always @ (posedge clk or posedge rst)
begin
if (rst) begin
{ba,a,cmd} <= {2'b00,13'd0,cmd_nop};
dqm <= 2'b11;
dq_oe <= 1'b0;
col_reg <= 5'b000;
{open_ba,open_row[0],open_row[1],open_row[2],open_row[3]} <= {4'b0000,{row_size*4{1'b0}}};
end else begin
{ba,a,cmd} <= {2'b00,13'd0,cmd_nop};
dqm <= 2'b11;
dq_oe <= 1'b0;
always @ (*)
begin
{a,cmd} = {13'd0,cmd_nop};
dqm = 2'b11;
dq_oe = 1'b0;
case (state)
`FSM_INIT:
if (shreg[3]) begin
{ba,a,cmd} <= {2'b00, 13'b0010000000000, cmd_pch};
open_ba[bank] <= 1'b0;
end else if (shreg[7] | shreg[19])
{ba,a,cmd} <= {2'b00, 13'd0, cmd_rfr};
else if (shreg[31])
{ba,a,cmd} <= {2'b00,3'b000,init_wb,2'b00,init_cl,init_bt,init_bl,cmd_lmr};
{a,cmd} = {13'b0010000000000, cmd_pch};
end else if (shreg[3+tRP] | shreg[3+tRP+tRFC])
{a,cmd} = {13'd0, cmd_rfr};
else if (shreg[3+tRP+tRFC+tRFC])
{a,cmd} = {3'b000,init_wb,2'b00,init_cl,init_bt,init_bl,cmd_lmr};
`FSM_RFR:
if (shreg[0]) begin
{ba,a,cmd} <= {2'b00, 13'b0010000000000, cmd_pch};
open_ba <= 4'b0000;
end else if (shreg[2])
{ba,a,cmd} <= {2'b00, 13'd0, cmd_rfr};
`FSM_IDLE:
col_reg <= col[4:0];
if (shreg[0])
{a,cmd} = {13'b0010000000000, cmd_pch};
else if (shreg[tRP])
{a,cmd} = {13'd0, cmd_rfr};
`FSM_PCH:
if (shreg[0]) begin
{ba,a,cmd} <= {ba,13'd0,cmd_pch};
open_ba[bank] <= 1'b0;
end
if (shreg[0])
{a,cmd} = {13'd0,cmd_pch};
`FSM_ACT:
if (shreg[0]) begin
{ba,a,cmd} <= {bank,(13'd0 | row),cmd_act};
{open_ba[bank],open_row[bank]} <= {1'b1,row};
end
if (shreg[0])
{a[row_size-1:0],cmd} = {row,cmd_act};
`FSM_RW:
begin
if (we_i & !count0)
cmd <= cmd_wr;
cmd = cmd_wr;
else if (!count0)
cmd <= cmd_rd;
cmd = cmd_rd;
else
cmd <= cmd_nop;
cmd = cmd_nop;
if (we_i & !count0)
dqm <= ~sel_i[3:2];
dqm = ~sel_i[3:2];
else if (we_i & count0)
dqm <= ~sel_i[1:0];
dqm = ~sel_i[1:0];
else
dqm <= 2'b00;
dqm = 2'b00;
if (we_i)
dq_oe <= 1'b1;
dq_oe = 1'b1;
if (~stall)
case (bte_i)
linear: {ba,a} <= {bank,col_a10_fix};
beat4: {ba,a,col_reg[2:0]} <= {bank,col_a10_fix, col_reg[2:0] + 3'd1};
a = col_a10_fix;
end
endcase
end
 
assign ba = bank;
// precharge individual bank A10=0
// precharge all bank A10=1
genvar i;
generate
for (i=0;i<2<<ba_size-1;i=i+1) begin
always @ (posedge clk or posedge rst)
if (rst)
{open_ba[i],open_row[i]} <= {1'b0,{row_size{1'b0}}};
else
if (cmd==cmd_pch & (a[10] | bank==i))
open_ba[i] <= 1'b0;
else if (cmd==cmd_act & bank==i)
{open_ba[i],open_row[i]} <= {1'b1,row};
 
end
endgenerate
 
`ifndef NO_BURST
always @ (posedge clk or posedge rst)
if (rst)
col_reg <= {col_reg_width{1'b0}};
else
case (state)
`FSM_IDLE:
col_reg <= col[col_reg_width-1:0];
`FSM_RW:
if (~stall)
case (bte_i)
`ifdef BEAT4
beat4: col_reg[2:0] <= col_reg[2:0] + 3'd1;
`endif
`ifdef BEAT8
beat8: {ba,a,col_reg[3:0]} <= {bank,col_a10_fix, col_reg[3:0] + 4'd1};
beat8: col_reg[3:0] <= col_reg[3:0] + 4'd1;
`endif
`ifdef BEAT16
beat16: {ba,a,col_reg[4:0]} <= {bank,col_a10_fix, col_reg[4:0] + 5'd1};
beat16: col_reg[4:0] <= col_reg[4:0] + 5'd1;
`endif
endcase
end
endcase
endcase
end
end
`endif
 
// bank and row open ?
always @ (posedge clk or posedge rst)
293,7 → 333,8
refresh_req <= 1'b0;
 
vl_dff # ( .width(32)) wb_dat_dff ( .d({dat_o[15:0],dq_i}), .q(dat_o), .clk(clk), .rst(rst));
assign dat_o[15:0] = dq_i;
vl_dff # ( .width(16)) wb_dat_dff ( .d(dat_o[15:0]), .q(dat_o[31:16]), .clk(clk), .rst(rst));
assign ack_wr = (state==`FSM_RW & count0 & we_i);
301,14 → 342,6
 
assign ack_o = ack_rd | ack_wr;
 
// output dq_o mux and dffs
always @ (posedge clk or posedge rst)
if (rst)
dq_o <= 16'h0000;
else
if (~count0)
dq_o <= dat_i[31:16];
else
dq_o <= dat_i[15:0];
assign dq_o = (!count0) ? dat_i[31:16] : dat_i[15:0];
 
endmodule
/doc/src/tRCD.png Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream
doc/src/tRCD.png Property changes : Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: doc/src/versatile_mem_ctrl.texi =================================================================== --- doc/src/versatile_mem_ctrl.texi (revision 105) +++ doc/src/versatile_mem_ctrl.texi (revision 106) @@ -60,269 +60,255 @@ This design implements a versatile memory controller. If used in combination with the versitale library, available from OpenCores, different types of system can easily be designed, including use cases where the system bus is in one clock domain and the memory controller in an other. + +@section Dependencies to other IP cores + +This design uses the following IP coreas available from OpenCores project verstile library. +@itemize @bullet +@item vl_cnt_shreg_ce_clear +@item vl_dff_ce_clear +@item vl_cnt_lfsr_zq +@item vl_dff +@item vl_o_dff +@item vl_io_dff_oe +@end itemize + @node Block diagram @chapter Block Diagram @cindex Block diagram -@section Clock domains -@value{DESIGN} contains the following clock domains -@itemize -@item Wishbone slave clock domain -@item Wishbone master clock domain -@item RX GMII clock domain -@item TX GMII clock domain -@end itemize +@section Synchronous design +@image{block-sdram} +Synchronous design where wishbone clock domain is equal to SDRAM and SDRAM controller clock domain. -@node Configuration registers -@chapter Configuration registers +@section Asynchronous design +@image{block-sdram-wbwb} +Asynchronous design where wishbone and SDRAM clock domain are independant. A wishbone rev B3 compatilble bridge +is available in project versatile_library from OpenCores, http://www.opencores.org. -@section Register memory map -@multitable @columnfractions .2 .1 .1 .1 .5 -@headitem Name @tab Address @tab Width @tab Access @tab Description -@item MODER @tab @value{MODER} @tab 32 @tab RW @tab Mode register -@item INT_SOURCE @tab @value{INT_SOURCE} @tab 32 @tab RW @tab Interrupt source register -@item INT_MASK @tab @value{INT_MASK} @tab 32 @tab RW @tab Interrupt mask register -@item TX_BD_NUM @tab @value{TX_BD_NUM} @tab 32 @tab RW @tab Transmit Buffer Descriptor number -@item MIIMODER @tab @value{MIIMODER} @tab 32 @tab RW @tab MII Mode Register -@item MIICOMMAND @tab @value{MIICOMMAND} @tab 32 @tab RW @tab MII Command Register -@item MIIADDRESS @tab @value{MIIADDRESS} @tab 32 @tab RW @tab MII Address Register -@item MIITX_DATA @tab @value{MIITX_DATA} @tab 32 @tab RW @tab MII Transmit Data -@item MIIRX_DATA @tab @value{MIIRX_DATA} @tab 32 @tab RW @tab MII Receive Data -@item MIISTATUS @tab @value{MIISTATUS} @tab 32 @tab RW @tab MII Status Register -@item MAC_ADDR0 @tab @value{MAC_ADDR0} @tab 32 @tab RW @tab MAC address, LSB four bytes -@item MAC_ADDR1 @tab @value{MAC_ADDR1} @tab 32 @tab RW @tab MAC address, MSB two bytes -@end multitable +@section Asynchronous design with multiple wishbone interfaces +@image{block-sdram-wbwb-arbiter} +Asynchronous design where wishbone and SDRAM clock domain are independant. Multiple wishbone port with use of a wishbone arbiter. -@page +@node SDR SDRAM controller +@chapter SDR SDRAM controller -@subsection MODER -@multitable @columnfractions .1 .1 .2 .6 -@headitem Bit @tab Access @tab Description @tab -@item 31-17 @tab @tab Reserved -@item 16 @tab RW @tab RECSMALL @tab Receive small packets -@item 15 @tab RW @tab PAD @tab Padding enabled -@item 14 @tab RW @tab HUGEN @tab Huge Packets Enable -@item 13 @tab RW @tab CRCEN @tab CRC enable -@item 12-8 @tab @tab Reserved -@item 7 @tab RW @tab LOOPBCK @tab Loopback -@item 6 @tab RW @tab Resrved -@item 5 @tab RW @tab PRO @tab Promiscuous -@item 4 @tab @tab Reserved -@item 3 @tab RW @tab BRO @tab Broadcast Address -@item 2 @tab @tab Reserved -@item 1 @tab RW @tab TXEN @tab Transmit Enable -@item 0 @tab RW @tab RXEN @tab Receive Enable +@section Module defines +@multitable @columnfractions .2 .8 +@headitem Name @tab Description +@item NO_BURST @tab Define if burst cycles not used +@item WRAP4 @tab Define to support 4 word wrap burst +@item WRAP8 @tab Define to support 8 word wrap burst +@item WRAP16 @tab Define to support 16 word wrap burst @end multitable -@example -Reset value: -MODER: 0x0000A000 -@end example -@page +@section Module parameters -@subsection INT_SOURCE -@multitable @columnfractions .1 .1 .2 .6 -@headitem Bit @tab Access @tab Description @tab -@item 31-7 @tab @tab Reserved -@item 4 @tab RW @tab BUSY @tab Busy@* This bit indicates that a buffer was received and discarded due to a lack of buffers. It is cleared by writing 1 to it. This bit appears regardless to the IRQ bits in the Receive or Transmit Buffer Descriptors. -@item 3 @tab RW @tab RXE @tab Receive error@* This bit indicates that an error occurred while receiving data. It is cleared by writing 1 to it. This bit appears only when IRQ bit is set in the Receive Buffer Descriptor. -@item 2 @tab RW @tab RXB @tab Receive buffer@* This bit indicates that a frame was received. It is cleared by writing 1 to it. This bit appears only when IRQ bit is set in the Receive Buffer Descriptor. If a control frame is received, then RXC bit is set instead of the RXB bit. -@item 1 @tab RW @tab TXE @tab Transmit error@* This bit indicates that a buffer was not transmitted due to a transmit error. It is cleared by writing 1 to it. This bit appears only when IRQ bit is set in the Receive Buffer Descriptor. This bit appears only when IRQ bit is set in the Transmit Buffer Descriptor. -@item 0 @tab RW @tab TXB @tab Transmit buffer@* This bit indicates that a buffer has been transmitted. It is cleared by writing 1 to it. This bit appears only when IRQ bit is set in the Transmit Buffer Descriptor. +@multitable @columnfractions .2 .1 .7 +@headitem Name @tab Default value @tab Description +@item ba_size @tab 2 @tab Bank adress vector size +@item row_size @tab 13 @tab Row adress vector size +@item col_size @tab 9 @tab Column adress vector size +@item cl @tab 2 @tab CAS latency @end multitable -@example -Reset value: -INT_SOURCE: 0x00000000 -@end example -@page -@subsection INT_MASK -@multitable @columnfractions .1 .1 .2 .6 -@headitem Bit @tab Access @tab Description @tab -@item 31-7 @tab @tab Reserved -@item 4 @tab RW @tab BUSY_M @tab Busy mask@* -@item 3 @tab RW @tab RXE_M @tab Receive error@* Receive error mask -@item 2 @tab RW @tab RXB_M @tab Receive buffer@* Receive buffer mask -@item 1 @tab RW @tab TXE_M @tab Transmit error@* Transmit error mask -@item 0 @tab RW @tab TXB_M @tab Transmit buffer@* Transmit buffer mask -@end multitable -@example -Reset value: -INT_MASK: 0x00000000 -@*@* -0 -> event masked -1 -> event causes an interrupt -@end example +Parameters ba_size, col_size and row_size should be set depending on memory configuration. The following +table holds figures for some SDRAM memories. -@page -@subsection TX_BD_NUM -@multitable @columnfractions .1 .1 .2 .6 -@headitem Bit @tab Access @tab Description @tab -@item 31-8 @tab @tab Reserved -@item 7-0 @tab RW @tab TX_BD_NUM @tab Transmit Buffer Descriptor Number@* Number of the Tx BD. Number of the Rx BD equals to the (0x80 – Tx BD number). Maximum number of the Tx BD is 0x80. Values greater then 0x80 cannot be written to this register (ignored). +@multitable @columnfractions .15 .25 .1 .1 .1 .3 +@headitem Manufacturer @tab Partnumber @tab ba_size @tab row_size @tab col_size @tab Memory size +@item Micron @tab MT48LC4M16 @tab 2 @tab 12 @tab 8 @tab 8Mbyte +@item Micron @tab MT48LC8M16 @tab 2 @tab 12 @tab 9 @tab 16Mbyte +@item Micron @tab MT48LC16M16 @tab 2 @tab 13 @tab 9 @tab 32Mbyte +@item Micron @tab MT48LC32M16 @tab 2 @tab 13 @tab 10 @tab 64Mbyte @end multitable -@example -Reset value: -TX_BD_NUM: 0x00000040 -@end example -@page -@subsection MIIMODER -@multitable @columnfractions .1 .1 .2 .6 -@headitem Bit @tab Access @tab Description @tab -@item 31-9 @tab @tab Reserved -@item 8 @tab RW @tab MIINOPRE @tab No Preamble@* 0 = 32 bit preamble sent@* 1 = No preamble sent -@item 7-0 @tab RW @tab CLKDIV @tab Clock divider The field is a host clock divider factor. The host clock can be divided by an even number, greater then 1. The default value is 0x64 (100). -@end multitable -@example -Reset value: -MIIMODER: 0x00000064 -@end example +Parameter cl should be set to either 2 or 3 depending on SDRAM clock. -@subsection MIICOMMAND -@multitable @columnfractions .1 .1 .2 .6 -@headitem Bit @tab Access @tab Description @tab -@item 31-3 @tab @tab Reserved -@item 2 @tab RW @tab WCTRLDATA @tab Write control data -@item 1 @tab RW @tab RSTAT @tab Read status -@item 0 @tab RW @tab SCANSTAT @tab Scan status +@section Module IO signals +@subsection Wishbone signals +@multitable @columnfractions .2 .1 .1 .6 +@headitem Name @tab Dir @tab Width @tab Description +@item dat_i @tab I @tab 32 @tab Input data vector +@item adr_i @tab I @tab @tab Adress vector +@item sel_i @tab I @tab 4 @tab Byte select signals +@item bte_i @tab I @tab 2 @tab Bus tag identifier +@item we_i @tab I @tab 1 @tab Write enable +@item cyc_i @tab I @tab 1 @tab Active cycle indicator +@item stb_i @tab I @tab 1 @tab Strobe +@item dat_o @tab O @tab 32 @tab Output data vector +@item ack_o @tab O @tab 1 @tab Acknowledge signal @end multitable -@example -Reset value: -MIICOMMAND: 0x00000000 -@end example -@subsection MIIADDRESS -@multitable @columnfractions .1 .1 .2 .6 -@headitem Bit @tab Access @tab Description @tab -@item 31-13 @tab @tab Reserved -@item 12-8 @tab RW @tab RGAD @tab Register address -@item 7-5 @tab RW @tab Reserved @tab -@item 4-0 @tab RW @tab FIAD @tab PHY address +Wishbone signal bte_i is optional and is only used for designs supporting burst transfer. +@subsection SDRAM signals +@multitable @columnfractions .2 .1 .1 .6 +@headitem Name @tab Dir @tab Width @tab Description +@item ba @tab O @tab ba_size @tab Bank adress vector +@item a @tab O @tab 13 @tab Adress vector +@item cmd @tab O @tab 3 @tab SDRAM command, {ras_n, cas_n, we_n} +@item cke @tab O @tab 1 @tab Clock enable +@item cs_n @tab O @tab 1 @tab Chip select, active low +@item dqm @tab O @tab 2 @tab Data mask +@item dq_i @tab I @tab 16 @tab Data input vector +@item dq_o @tab O @tab 16 @tab Data output vector +@item dq_oe @tab O @tab 1 @tab Data output enable @end multitable -@example -Reset value: -MIIADDRESS: 0x00000000 -@end example -@subsection MIITX_DATA -@multitable @columnfractions .1 .1 .2 .6 -@headitem Bit @tab Access @tab Description @tab -@item 31-16 @tab @tab Reserved -@item 15-0 @tab RW @tab CTRLDATA @tab Data to be written to the PHY +@subsection System signals +@multitable @columnfractions .2 .1 .1 .6 +@headitem Name @tab Dir @tab Width @tab Description +@item clk @tab I @tab 1 @tab SDRAM system clock +@item rst @tab I @tab 1 @tab Asynchronous reset, active hig @end multitable -@example -Reset value: -MIITX_DATA: 0x00000000 -@end example -@subsection MIIRX_DATA -@multitable @columnfractions .1 .1 .2 .6 -@headitem Bit @tab Access @tab Description @tab -@item 31-16 @tab @tab Reserved -@item 15-0 @tab R @tab PRSD @tab Data read from the PHY -@end multitable -@example -Reset value: -MIIRX_DATA: 0x00000000 -@end example +@node SDR SDRAM 16 bit data bus controller +@chapter SDR SDRAM 16 bit data bus controller +@cindex SDR SDRAM 16 bit data bus controller -@subsection MIISTATUS -@multitable @columnfractions .1 .1 .2 .6 -@headitem Bit @tab Access @tab Description @tab -@item 31-3 @tab @tab Reserved -@item 2 @tab R @tab NVALID @tab Invalid@* 0 = The data in the MSTATUS register is valid.@* 1 = The data in the MSTATUS register is invalid.@* This bit is only valid when the scan status operation is active. -@item 1 @tab R @tab BUSY @tab 0 = The MII is ready.@* 1 = The MII is busy (operation in progress). -@item 0 @tab R @tab LINKFAIL @tab 0 = The link is OK.@*1 = The link failed.@*The Link fail condition occurred (now the link might be OK). Another status read gets a new status. -@end multitable -@example -Reset value: -MIISTATUS: 0x00000000 -@end example +@section State machine implementation -@page -@subsection MAC_ADDR0 -@multitable @columnfractions .1 .1 .8 -@headitem Bit @tab Access @tab Description @tab -@item 31-24 @tab RW @tab Byte 2 of the Ethernet MAC address -@item 23-16 @tab RW @tab Byte 3 of the Ethernet MAC address -@item 15-8 @tab RW @tab Byte 4 of the Ethernet MAC address -@item 7-0 @tab RW @tab Byte 5 of the Ethernet MAC address -@end multitable -@example -Reset value: -MAC_ADDR0: 0x00000000 -@end example +Design is based on a state machine as described below. -@subsection MAC_ADDR1 -@multitable @columnfractions .1 .1 .8 -@headitem Bit @tab Access @tab Description @tab -@item 31-16 @tab @tab Reserved -@item 15-8 @tab RW @tab Byte 0 of the Ethernet MAC address -@item 7-0 @tab RW @tab Byte 1 of the Ethernet MAC address -@end multitable -@example -Reset value: -MAC_ADDR1: 0x00000000 -@end example +@image{sdr_sdram_16,14cm,16cm,,.png} -@node MDIO -@chapter Management Data Input/Output - -The MDIO interface is implemented by two lines: +A counter is incremented on each cycle the state machine reside in any given state. +When changing state a counter clear is issued. The counter state vector is used for +two things @itemize -@item a MDC clock line -@item an MDIO data line +@item controlling outputs, ie defining cmd and other control signals +@item to make sure timing reqiurements are fulfilled, ie define time from precharge to activate @end itemize -The clock line is driven by the MAC device. The data line is bidirectional: the PHY drives it to provide register data at the end of a read operation. -@*@* -The bus has a single MAC master, but can have up to 32 PHY slaves. -@*@* -The MDC clock can be aperiodic, with a minimum period of 400 ns, which corresponds to a maximal frequency of 2.5 MHz. Newer chips, however, allow faster acesses. -@*@* -The MDIO data line has a pull-up of 1.5 kOhm in the PHY, allowing the MAC to determine if one or more PHYs are attached. The MAC should have a 2 kOhm pull-down on that same line. +@subsection State - init -@section Bus timing -@subsection Read operation -A read operation has the following phases +The init state is responsible to make sure that a proper start-up and initialization of the SDRAM is +performed. The following sequence should be applied: +@enumerate +@item assert CKE low +@item provide stable clock +@item bring CKE high +@item perform PRECHARGE ALL command and wait for tRP +@item issue AUTO RERFESH and wait for tRFC +@item issue AUTO RERFESH and wait for tRFC +@item LOAD MODE REGISTER and wait for tMR +@end enumerate +After this state machine advances to idle state + +@subsection State - idle + +In state idle implementation awaits two different condition, appearing in order of priority +@enumerate +@item refresh request => next state is rfr +@item cyc_i & stb_i => next state is adr +@end enumerate + + +@subsection State - adr + +Depending on status of open bank and open rows choice is taken whether to precharge and activate, activate or go +directly to read write state. Reason for this as a separate state is to be able to have comparison result as a +registered signal to achive an higher clock frequency. + +@subsection State - pch + +Open row in current bank is deactivated. State machine waits in pch state to fulfill tRP. + +@subsection State - act + +Row in current bank is activated. State machine waits in act state to fulfill tRCD. + +@subsection State - rw + +A two word read or write burst is started. If wishbone cycle is of type burst column will get incremented +with possible wrap around and a new burst started for each 32 bit word. + +@section Timing + +The follwoing timing requirements must be fulfilled: + @itemize -@item Preamble with 32 ones -@item Start sequence, 01 -@item Opcode read, 10 -@item PHY adress -@item REG adress -@item Bus turnaround -@item Register data +@item tMR - Load Mode Register period +@item tRCD - Active to read/write delay +@item tRP - Precharge command period +@item tRFC - Auto refresh period +@item tREF - refresh period @end itemize -@image{MDIO_rd,15cm,2.54cm} -@subsection Write operation -A write operation has the following phases +In the SDRAM datasheet the above timing figures will be given in ns and should be +converted to number of clock cycles. All of the above timing figures, except tREF, are implemented as parameters +in the design and should be set depending on SDRAM figures and actual clock period. All +parameters have default values of 2 clock cycles. + +@subsection Bank/Row activation - tRCD + +@image{tRCD,15cm,5cm,,.png} + +Minimum time between activation of and read or write command. +@subsection Auto refresh mode + +@image{aref,15cm,15cm,,.png} + +Minumum time between precharge and auto refresh and active command. + +@subsection Refresh period - tREF + +The auto refresh period, tREF must be met. During auto refresh an internal address counter +is used and adress signals are treated as don't care. During the refresh period each row must +be refreshed. @* +For example consider a SDRAM with tREF = 64 ms and row size of 8K. An auto refresh command +should be issued once every 64 ms / 8192 = 7.813 us.@* +The refresh interval counter is implemented as an LFSR style counter for minimal area and maximum +performance. To accurately set the wrap value for this counter use the application VersatileCounter found +in the versatile library project at opencores. This program gives the wrap value for a given vector length. +Assuming an SDRAM clock frequency of 133 MHz which equals a period time of 7.5 ns we should issue an auto +refresh every 7.813 us / 7.5 ns = 1041 cycle. We need a state vector of 11 bits in the counter.@* +To get the wrap value we use the application@* +@command{./VersatileCounter.php 11 1041@*11111110101} + +@node Example: Timing setup +@chapter Example: Timing setup + +@section Requirements + +SDRAM device to use: @itemize -@item Preamble with 32 ones -@item Start sequence, 01 -@item Opcode read, 01 -@item PHY adress -@item REG adress -@item Bus turnaround -@item Register data +@item Micron MT48LC32M16-7E @end itemize -@image{MDIO_wr,15cm,2.54cm} -@node Ingress and Egress FIFO -@chapter Ingress and Egress FIFO +@multitable @columnfractions .4 .2 .1 .1 .1 .1 +@headitem Parameter @tab Symbol @tab Min @tab Max @tab Unit +@item Auto refresh period @tab tRFC @tab 66 @tab - @tab ns +@item Precharge command period @tab tRP @tab 15 @tab - @tab ns +@item Active to read or write delay @tab tRCD @tab 15 @tab - @tab ns +@item Load mode register command to active or refresh @tab tMRD @tab 2 @tab - @tab tCK +@item Refresh periods (8192 rows) @tab tREF @tab 66 @tab -@tab ms +@end multitable -@section FIFO implementation -Both ingress and egress FIFO implementation uses a generic asynchronous FIFO design -available from OpenCores.@*@* -@uref{http://opencores.org/project,versatile_library} +Intended operating frequency is 75 MHz, tCK = 13.333 ns +@section Parameter settings + +@multitable @columnfractions .2 .8 +@headitem Symbol @tab Value +@item tRFC @tab 5 +@item tRP @tab 2 +@item tRCD @tab 2 +@item tMRD @tab 2 +@end multitable +@* +Refresh rate is 66 ms / 8192 = 8.057 us@* +Number of clock cycles between refresh request 8.057 us / 13.333 ns = 604@* +@* +To get the wrap value we use the application from Versatile Library@* +@command{./VersatileCounter.php 10 604@*0101001110} + + @c **************************************************************************** @c End bits @c **************************************************************************** -@node GNU Free Documentation License +@node GNU Free Documentation License @chapter GNU Free Documentation License @cindex license for @value{DESIGN}
/doc/src/aref.png Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream
doc/src/aref.png Property changes : Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: doc/src/sdr_sdram_16.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: doc/src/sdr_sdram_16.png =================================================================== --- doc/src/sdr_sdram_16.png (nonexistent) +++ doc/src/sdr_sdram_16.png (revision 106)
doc/src/sdr_sdram_16.png Property changes : Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: doc/src/sdr_sdram_16.fsm =================================================================== --- doc/src/sdr_sdram_16.fsm (nonexistent) +++ doc/src/sdr_sdram_16.fsm (revision 106) @@ -0,0 +1,75 @@ + + + + + s_out7,s_out6,s_out5,s_out4,s_out3,s_out2,s_out1,s_out0 + i_7,i_6,i_5,i_4,i_3,i_2,i_1,i_0 + o_7,o_6,o_5,o_4,o_3,o_2,o_1,o_0 + + init + idle + rfr + adr + rw + pch + act + + 0 + 1 + init_done + + + + 1 + 2 + refresh_req + + + + 1 + 3 + cyc&stb + + + + 2 + 1 + tRFC + + + + 3 + 6 + current_bank_closed + + + + 3 + 4 + current_row_open + + + + 3 + + + + + 5 + 6 + tRP + + + + 6 + 4 + tRCD + + + + 1 + end_of_cycle + + + + Index: doc/src/Makefile =================================================================== --- doc/src/Makefile (revision 105) +++ doc/src/Makefile (revision 106) @@ -4,5 +4,6 @@ texinfo: texi2pdf versatile_mem_ctrl.texi + mv versatile_mem_ctrl.pdf ../ all: texinfo
/doc/versatile_mem_ctrl.pdf Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream
doc/versatile_mem_ctrl.pdf Property changes : Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property

powered by: WebSVN 2.1.0

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