123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703 |
- interface dram_bus;
- logic [1:0] prio;
- logic rst_n;
- logic clk;
- logic [24:0] addr;
- logic addr0;
- logic [15:0] rd;
- logic req;
- logic [1:0] rstrb;
- logic [31:0] wd;
- logic [3:0] wstrb;
- logic start;
- logic wrack;
-
- modport ustr (
- input prio,
- output rst_n,
- output clk,
- input addr,
- output addr0,
- output rd,
- input req,
- output rstrb,
- input wd,
- input wstrb,
- output start,
- output wrack
- );
-
- modport dstr (
- output prio,
- input rst_n,
- input clk,
- output addr,
- input addr0,
- input rd,
- output req,
- input rstrb,
- output wd,
- output wstrb,
- input start,
- input wrack
- );
- endinterface
- module dram_port
- #(parameter width = 32)
- (
- dram_bus.dstr bus,
- input [1:0] prio,
- input [24:0] addr,
- output reg [width-1:0] rd,
- input valid,
- output reg ready,
- input [width-1:0] wd,
- input [(width >> 3)-1:0] wstrb
- );
- reg started;
- assign bus.prio = prio;
- assign bus.addr = addr & ~((width - 1) >> 3);
- assign bus.req = valid & ~started;
- always_comb
- begin
- bus.wd = 32'hxxxx_xxxx;
- bus.wstrb = 4'b0000;
- if (width == 8)
- begin
- bus.wd[15:0] = { wd, wd };
- bus.wstrb[1:0] = { wstrb[0] & addr[0], wstrb[0] & ~addr[0] };
- end
- else
- begin
- bus.wd[width-1:0] = wd;
- bus.wstrb[(width >> 3)-1:0] = wstrb;
- end
- end
- always @(negedge bus.rst_n or posedge bus.clk)
- if (~bus.rst_n)
- begin
- ready <= 1'b0;
- started <= 1'b0;
- end
- else
- begin
- if (~valid)
- begin
- ready <= 1'b0;
- started <= 1'b0;
- end
- else if (bus.start)
- begin
- started <= 1'b1;
- ready <= bus.wrack;
- end
- else if (started & ~ready)
- begin
- ready <= bus.rstrb[(width - 1) >> 4];
- end
- end
- genvar i;
- generate
- for (i = 0; i < ((width + 15) >> 4); i++)
- begin : w
- always @(posedge bus.clk)
- if (started & ~ready & bus.rstrb[i])
- begin
- if (width == 8)
- rd <= bus.addr0 ? bus.rd[15:8] : bus.rd[7:0];
- else
- rd[i*16+15:i*16] <= bus.rd;
- end
- end
- endgenerate
- endmodule
- module dram_arbiter
- #(parameter port_count = 1)
- (
- dram_bus.ustr ustr [1:port_count],
- dram_bus.dstr dstr,
- input [1:0] rfsh_prio,
- output logic do_rfsh
- );
- logic [31:0] u_wd[1:port_count];
- logic [3:0] u_wstrb[1:port_count];
- logic [24:0] u_addr[1:port_count];
- logic [port_count:0] grant;
- assign grant[0] = 1'b0;
- reg [port_count:0] grant_q;
- always @(negedge dstr.rst_n or posedge dstr.clk)
- if (~dstr.rst_n)
- grant_q <= 'b0;
- else
- grant_q <= grant;
- generate
- genvar i;
- for (i = 1; i <= port_count; i++)
- begin : u
- assign ustr[i].rst_n = dstr.rst_n;
- assign ustr[i].clk = dstr.clk;
- assign ustr[i].addr0 = dstr.addr0;
- assign ustr[i].rd = dstr.rd;
- assign ustr[i].rstrb = dstr.rstrb;
- assign ustr[i].wrack = dstr.wrack;
- assign grant[i] = ~|grant[i-1:0] & ustr[i].req &
- (ustr[i].prio >= rfsh_prio);
- assign u_addr[i] = ustr[i].addr;
- assign u_wd[i] = ustr[i].wd;
- assign u_wstrb[i] = ustr[i].wstrb;
-
-
- assign ustr[i].start = grant_q[i] & dstr.start;
- end
- endgenerate
- always_comb
- begin
- dstr.addr = 'bx;
- dstr.wd = 'bx;
- dstr.wstrb = 4'b0;
- dstr.req = 1'b0;
- do_rfsh = |rfsh_prio;
- for (int j = 1; j <= port_count; j++)
- if (grant[j])
- begin
- dstr.addr = u_addr[j];
- dstr.wd = u_wd[j];
- dstr.wstrb = u_wstrb[j];
- dstr.req = 1'b1;
- do_rfsh = 1'b0;
- end
- end
- endmodule
- module sdram
- #( parameter
- port1_count = 1,
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- t_cl = 3,
- t_rcd = 3,
- t_rfc = 10,
- t_rp = 3,
- t_ras = 7,
- t_rc = 10,
- t_rrd = 2,
- t_wr = 2,
- t_mrd = 2,
- t_refi_lg2 = 10,
- t_p_lg2 = 15,
- burst_lg2 = 1
- )
- (
-
- input rst_n,
- input clk,
- input init_tmr,
- input rfsh_tmr,
-
- output sr_cs_n,
- output sr_ras_n,
- output sr_cas_n,
- output sr_we_n,
- output [1:0] sr_dqm,
- output [1:0] sr_ba,
- output [12:0] sr_a,
- inout [15:0] sr_dq,
-
- dram_bus.ustr port1 [1:port1_count],
-
- input [24:1] a2,
- input [15:0] wd2,
- input [1:0] wrq2,
- output reg wacc2,
-
- output [12:0] dirty_pg,
- output reg dirty_stb
- );
- `include "functions.sv" // For modelsim
-
- wire mrd_wburst = 1'b1;
- wire [2:0] mrd_cl = t_cl;
- wire [2:0] mrd_burst = burst_lg2;
- wire mrd_interleave = 1'b0;
- wire [12:0] mrd_val = { 3'b000,
- ~mrd_wburst,
- 2'b00,
- mrd_cl,
- mrd_interleave,
- mrd_burst };
-
-
- localparam t_pre_rd_when = max(t_ras, t_rcd + 1);
-
-
- localparam t_pre_wr_when = max(t_ras, t_rcd + t_wr);
-
- localparam burst_n = 1 << burst_lg2;
-
- localparam cmd_desl = 5'b0_1111;
- localparam cmd_nop = 5'b0_0111;
- localparam cmd_bst = 5'b0_0110;
- localparam cmd_rd = 5'b0_0101;
- localparam cmd_wr = 5'b0_0100;
- localparam cmd_act = 5'b0_0011;
- localparam cmd_pre = 5'b0_0010;
- localparam cmd_ref = 5'b1_0001;
- localparam cmd_mrd = 5'b0_0000;
- reg [4:0] dram_cmd;
- wire is_rfsh = dram_cmd[4];
- assign sr_cs_n = dram_cmd[3];
- assign sr_ras_n = dram_cmd[2];
- assign sr_cas_n = dram_cmd[1];
- assign sr_we_n = dram_cmd[0];
-
- reg [12:0] dram_a;
- assign sr_a = dram_a;
- reg [1:0] dram_ba;
- assign sr_ba = dram_ba;
- reg [1:0] dram_dqm;
- assign sr_dqm = dram_dqm;
- reg [15:0] dram_d;
- reg [15:0] dram_q;
- reg dram_d_en;
- assign sr_dq = dram_d_en ? dram_d : 16'hzzzz;
-
- reg rfsh_tmr_q;
- reg [1:0] rfsh_prio;
-
- dram_bus p1 ();
- wire do_rfsh;
- assign p1.rst_n = rst_n;
- assign p1.clk = clk;
- dram_arbiter #(.port_count(port1_count))
- arbiter (
- .ustr ( port1 ),
- .dstr ( p1.dstr ),
- .rfsh_prio ( rfsh_prio ),
- .do_rfsh ( do_rfsh )
- );
-
-
- typedef enum logic [3:0] {
- st_reset,
- st_init_rfsh,
- st_init_mrd,
- st_ready,
- st_rfsh,
- st_rd_wr_act,
- st_rd_wr,
- st_wr2_act,
- st_wr2
- } state_t;
- state_t state = st_reset;
- always @(posedge clk or negedge rst_n)
- if (~rst_n)
- begin
- rfsh_tmr_q <= 1'b0;
- rfsh_prio <= 2'b00;
- end
- else
- begin
- rfsh_tmr_q <= rfsh_tmr;
-
- if (is_rfsh)
- rfsh_prio <= 2'b00;
- else if (rfsh_tmr & ~rfsh_tmr_q)
- rfsh_prio <= rfsh_prio + (~&rfsh_prio);
- end
- reg [5:0] op_ctr;
- wire [3:0] op_cycle = op_ctr[3:0];
- wire [1:0] init_op_ctr = op_ctr[5:4];
- reg op_zero;
- reg [31:0] wdata_q;
- reg [ 3:0] be_q;
- reg [24:0] addr;
- reg wrq2_more;
- wire [12:0] row_addr = addr[24:12];
- wire [1:0] bank_addr = addr[11:10];
- wire [8:0] col_addr = addr[9:1];
- assign p1.addr0 = addr[0];
- assign p1.rd = dram_q;
-
- assign dirty_pg = addr[24:12];
-
-
-
-
-
-
-
-
- always @(posedge clk or negedge rst_n)
- if (~rst_n)
- begin
- dram_cmd <= cmd_desl;
- dram_a <= 13'hxxxx;
- dram_ba <= 2'bxx;
- dram_dqm <= 2'b00;
- dram_d <= 16'hxxxx;
- dram_q <= 16'hxxxx;
- dram_d_en <= 1'b1;
- op_ctr <= 6'h0;
- op_zero <= 1'b0;
- state <= st_reset;
- p1.start <= 1'b0;
- p1.wrack <= 1'bx;
- p1.rd <= 16'hxxxx;
- p1.rstrb <= 2'b00;
- wacc2 <= 1'b0;
- wrq2_more <= 1'bx;
- dirty_stb <= 1'b0;
- wdata_q <= 32'hxxxx_xxxx;
- be_q <= 4'bxxxx;
- addr <= 25'bx;
- end
- else
- begin
-
- dram_a <= 13'b0;
- dram_ba <= bank_addr;
- dram_dqm <= 2'b00;
- dram_d <= { 8'hAA, 3'b000, dram_cmd };
- dram_cmd <= cmd_nop;
- dram_d_en <= 1'b1;
- dram_q <= sr_dq;
- p1.rstrb <= 2'b00;
- wacc2 <= 1'b0;
- dirty_stb <= 1'b0;
- op_ctr <= op_ctr + 1'b1;
- op_zero <= &op_cycle;
- p1.start <= 1'b0;
- case (state)
- st_reset:
- begin
- op_ctr <= 6'b0;
- op_zero <= 1'b0;
- dram_a[10] <= 1'b1;
- dram_cmd <= cmd_nop;
- if (init_tmr)
- begin
- dram_cmd <= cmd_pre;
- state <= st_init_rfsh;
- end
- end
- st_init_rfsh:
- begin
- if (op_zero)
- begin
- dram_cmd <= cmd_ref;
- if (init_op_ctr == 2'b11)
- state <= st_init_mrd;
- end
- end
- st_init_mrd:
- begin
- dram_a <= mrd_val;
- dram_ba <= 2'b00;
- if (op_zero)
- if (init_op_ctr[0])
- state <= st_ready;
- else
- dram_cmd <= cmd_mrd;
- end
- st_ready:
- begin
- op_ctr <= 6'b0;
- op_zero <= 1'b0;
- dram_cmd <= cmd_desl;
- p1.wrack <= 1'bx;
- be_q <= 4'bxxxx;
- wdata_q <= 32'hxxxx_xxxx;
- addr <= 25'bx;
- dram_a <= 13'h1bb;
- dram_d <= 16'hbbbb;
-
-
-
- if (do_rfsh)
- begin
- state <= st_rfsh;
- end
- else if (p1.req)
- begin
- addr <= p1.addr;
- p1.wrack <= |p1.wstrb;
- dirty_stb <= |p1.wstrb;
- wdata_q <= p1.wd;
- be_q <= p1.wstrb;
- state <= st_rd_wr_act;
- p1.start <= 1'b1;
- end
- else if (wrq2[0])
- begin
-
- addr <= { a2, 1'b0 };
- state <= st_wr2_act;
- dirty_stb <= 1'b1;
- end
- end
- st_rfsh: begin
- if (op_cycle == 0)
- dram_cmd <= cmd_ref;
- else if (op_cycle == t_rfc-2)
- state <= st_ready;
- end
- st_rd_wr_act: begin
- op_ctr <= 6'b0;
- op_zero <= 1'b0;
- dram_cmd <= cmd_act;
- dram_a <= row_addr;
- dram_ba <= bank_addr;
- state <= st_rd_wr;
- end
- st_rd_wr:
- begin
- dram_d_en <= p1.wrack;
- dram_dqm <= {2{p1.wrack}};
- dram_d <= 16'hcccc ^ {16{p1.wrack}};
-
-
-
-
-
-
-
-
-
-
-
- case (op_cycle)
- 2: begin
- dram_a[10] <= 1'b0;
- dram_a[8:0] <= col_addr;
- dram_cmd <= p1.wrack ? cmd_wr : cmd_rd;
- dram_d <= wdata_q[15:0];
- dram_dqm <= {2{p1.wrack}} & ~be_q[1:0];
- end
- 3: begin
- dram_d <= wdata_q[31:16];
- dram_dqm <= {2{p1.wrack}} & ~be_q[3:2];
- end
- 6: begin
-
-
-
- dram_a[10] <= 1'b1;
- dram_cmd <= cmd_pre;
- end
-
-
- 7: begin
- p1.rstrb[0] <= ~p1.wrack;
- end
- 8: begin
- p1.rstrb[1] <= ~p1.wrack;
- state <= st_ready;
- end
- default: begin
-
- end
- endcase
- end
- st_wr2_act:
- begin
- op_ctr <= 6'b0;
- op_zero <= 1'b0;
- dram_a <= row_addr;
- dram_ba <= bank_addr;
- dram_cmd <= cmd_act;
- state <= st_wr2;
- end
- st_wr2:
- begin
-
-
-
- dram_d <= wd2;
- dram_a[10] <= 1'b0;
- dram_a[8:0] <= a2[9:1];
- dram_dqm <= 2'b11;
- case (op_cycle)
- 0, 1: begin
- wacc2 <= 1'b1;
- dram_dqm <= 2'b00;
- end
- 2: begin
- dram_cmd <= cmd_wr;
- wacc2 <= 1'b1;
- dram_dqm <= 2'b00;
- wrq2_more <= wrq2[1] & (~&a2[9:3]);
- end
- 3: begin
- wacc2 <= 1'b1;
- dram_dqm <= 2'b00;
- end
- 4: begin
- dram_cmd <= cmd_wr;
- dram_dqm <= 2'b00;
- if (wrq2_more & ~(p1.req | do_rfsh))
- begin
-
- wacc2 <= 1'b1;
- op_ctr[3:0] <= 4'd1;
- end
- end
- 5: begin
- dram_dqm <= 2'b00;
- end
- 6: begin
-
- end
- 7: begin
-
- dram_cmd <= cmd_pre;
- end
- 8: begin
-
- state <= st_ready;
- end
- default: begin
-
- end
- endcase
- end
- endcase
- end
- endmodule
|