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
- from Rev 49 to Rev 50
- ↔ Reverse comparison
Rev 49 → Rev 50
/trunk/rtl/verilog/versatile_mem_ctrl_ip.v
1,3 → 1,1636
////////////////////////////////////////////////////////////////////// |
//// //// |
//// Versatile memory controller //// |
//// //// |
//// Description //// |
//// A modular wishbone compatible memory controller with support//// |
//// for various types of memory configurations //// |
//// //// |
//// To Do: //// |
//// - add support for additional SDRAM variants //// |
//// //// |
//// Author(s): //// |
//// - Michael Unneback, unneback@opencores.org //// |
//// ORSoC AB //// |
//// //// |
////////////////////////////////////////////////////////////////////// |
//// //// |
//// Copyright (C) 2009 Authors and OPENCORES.ORG //// |
//// //// |
//// This source file may be used and distributed without //// |
//// restriction provided that this copyright statement is not //// |
//// removed from the file and that any derivative work contains //// |
//// the original copyright notice and the associated disclaimer. //// |
//// //// |
//// This source file is free software; you can redistribute it //// |
//// and/or modify it under the terms of the GNU Lesser General //// |
//// Public License as published by the Free Software Foundation; //// |
//// either version 2.1 of the License, or (at your option) any //// |
//// later version. //// |
//// //// |
//// This source is distributed in the hope that it will be //// |
//// useful, but WITHOUT ANY WARRANTY; without even the implied //// |
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// |
//// PURPOSE. See the GNU Lesser General Public License for more //// |
//// details. //// |
//// //// |
//// You should have received a copy of the GNU Lesser General //// |
//// Public License along with this source; if not, download it //// |
//// from http://www.opencores.org/lgpl.shtml //// |
//// //// |
////////////////////////////////////////////////////////////////////// |
////////////////////////////////////////////////////////////////////// |
//// //// |
//// Versatile counter //// |
//// //// |
//// Description //// |
//// Versatile counter, a reconfigurable binary, gray or LFSR //// |
//// counter //// |
//// //// |
//// To Do: //// |
//// - add LFSR with more taps //// |
//// //// |
//// Author(s): //// |
//// - Michael Unneback, unneback@opencores.org //// |
//// ORSoC AB //// |
//// //// |
////////////////////////////////////////////////////////////////////// |
//// //// |
//// Copyright (C) 2009 Authors and OPENCORES.ORG //// |
//// //// |
//// This source file may be used and distributed without //// |
//// restriction provided that this copyright statement is not //// |
//// removed from the file and that any derivative work contains //// |
//// the original copyright notice and the associated disclaimer. //// |
//// //// |
//// This source file is free software; you can redistribute it //// |
//// and/or modify it under the terms of the GNU Lesser General //// |
//// Public License as published by the Free Software Foundation; //// |
//// either version 2.1 of the License, or (at your option) any //// |
//// later version. //// |
//// //// |
//// This source is distributed in the hope that it will be //// |
//// useful, but WITHOUT ANY WARRANTY; without even the implied //// |
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// |
//// PURPOSE. See the GNU Lesser General Public License for more //// |
//// details. //// |
//// //// |
//// You should have received a copy of the GNU Lesser General //// |
//// Public License along with this source; if not, download it //// |
//// from http://www.opencores.org/lgpl.shtml //// |
//// //// |
////////////////////////////////////////////////////////////////////// |
|
module versatile_fifo_async_cmp ( wptr, rptr, fifo_empty, fifo_full, wclk, rclk, rst ); |
|
parameter ADDR_WIDTH = 4; |
parameter N = ADDR_WIDTH-1; |
|
parameter Q1 = 2'b00; |
parameter Q2 = 2'b01; |
parameter Q3 = 2'b11; |
parameter Q4 = 2'b10; |
|
parameter going_empty = 1'b0; |
parameter going_full = 1'b1; |
|
input [N:0] wptr, rptr; |
output reg fifo_empty; |
output fifo_full; |
input wclk, rclk, rst; |
|
wire direction; |
reg direction_set, direction_clr; |
|
wire async_empty, async_full; |
wire fifo_full2; |
reg fifo_empty2; |
|
// direction_set |
always @ (wptr[N:N-1] or rptr[N:N-1]) |
case ({wptr[N:N-1],rptr[N:N-1]}) |
{Q1,Q2} : direction_set <= 1'b1; |
{Q2,Q3} : direction_set <= 1'b1; |
{Q3,Q4} : direction_set <= 1'b1; |
{Q4,Q1} : direction_set <= 1'b1; |
default : direction_set <= 1'b0; |
endcase |
|
// direction_clear |
always @ (wptr[N:N-1] or rptr[N:N-1] or rst) |
if (rst) |
direction_clr <= 1'b1; |
else |
case ({wptr[N:N-1],rptr[N:N-1]}) |
{Q2,Q1} : direction_clr <= 1'b1; |
{Q3,Q2} : direction_clr <= 1'b1; |
{Q4,Q3} : direction_clr <= 1'b1; |
{Q1,Q4} : direction_clr <= 1'b1; |
default : direction_clr <= 1'b0; |
endcase |
|
`ifndef GENERATE_DIRECTION_AS_LATCH |
dff_sr dff_sr_dir( .aclr(direction_clr), .aset(direction_set), .clock(1'b1), .data(1'b1), .q(direction)); |
`endif |
|
`ifdef GENERATE_DIRECTION_AS_LATCH |
always @ (posedge direction_set or posedge direction_clr) |
if (direction_clr) |
direction <= going_empty; |
else |
direction <= going_full; |
`endif |
|
assign async_empty = (wptr == rptr) && (direction==going_empty); |
assign async_full = (wptr == rptr) && (direction==going_full); |
|
dff_sr dff_sr_empty0( .aclr(rst), .aset(async_full), .clock(wclk), .data(async_full), .q(fifo_full2)); |
dff_sr dff_sr_empty1( .aclr(rst), .aset(async_full), .clock(wclk), .data(fifo_full2), .q(fifo_full)); |
|
/* |
always @ (posedge wclk or posedge rst or posedge async_full) |
if (rst) |
{fifo_full, fifo_full2} <= 2'b00; |
else if (async_full) |
{fifo_full, fifo_full2} <= 2'b11; |
else |
{fifo_full, fifo_full2} <= {fifo_full2, async_full}; |
*/ |
always @ (posedge rclk or posedge async_empty) |
if (async_empty) |
{fifo_empty, fifo_empty2} <= 2'b11; |
else |
{fifo_empty,fifo_empty2} <= {fifo_empty2,async_empty}; |
|
endmodule // async_comp |
module vfifo_dual_port_ram_dc_dw |
( |
d_a, |
q_a, |
adr_a, |
we_a, |
clk_a, |
q_b, |
adr_b, |
d_b, |
we_b, |
clk_b |
); |
parameter DATA_WIDTH = 32; |
parameter ADDR_WIDTH = 8; |
input [(DATA_WIDTH-1):0] d_a; |
input [(ADDR_WIDTH-1):0] adr_a; |
input [(ADDR_WIDTH-1):0] adr_b; |
input we_a; |
output [(DATA_WIDTH-1):0] q_b; |
input [(DATA_WIDTH-1):0] d_b; |
output reg [(DATA_WIDTH-1):0] q_a; |
input we_b; |
input clk_a, clk_b; |
reg [(DATA_WIDTH-1):0] q_b; |
reg [DATA_WIDTH-1:0] ram [(1<<ADDR_WIDTH)-1:0] ; |
always @ (posedge clk_a) |
begin |
q_a <= ram[adr_a]; |
if (we_a) |
ram[adr_a] <= d_a; |
end |
always @ (posedge clk_b) |
begin |
q_b <= ram[adr_b]; |
if (we_b) |
ram[adr_b] <= d_b; |
end |
endmodule |
////////////////////////////////////////////////////////////////////// |
//// //// |
//// Versatile counter //// |
//// //// |
//// Description //// |
//// Versatile counter, a reconfigurable binary, gray or LFSR //// |
//// counter //// |
//// //// |
//// To Do: //// |
//// - add LFSR with more taps //// |
//// //// |
//// Author(s): //// |
//// - Michael Unneback, unneback@opencores.org //// |
//// ORSoC AB //// |
//// //// |
////////////////////////////////////////////////////////////////////// |
//// //// |
//// Copyright (C) 2009 Authors and OPENCORES.ORG //// |
//// //// |
//// This source file may be used and distributed without //// |
//// restriction provided that this copyright statement is not //// |
//// removed from the file and that any derivative work contains //// |
//// the original copyright notice and the associated disclaimer. //// |
//// //// |
//// This source file is free software; you can redistribute it //// |
//// and/or modify it under the terms of the GNU Lesser General //// |
//// Public License as published by the Free Software Foundation; //// |
//// either version 2.1 of the License, or (at your option) any //// |
//// later version. //// |
//// //// |
//// This source is distributed in the hope that it will be //// |
//// useful, but WITHOUT ANY WARRANTY; without even the implied //// |
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// |
//// PURPOSE. See the GNU Lesser General Public License for more //// |
//// details. //// |
//// //// |
//// You should have received a copy of the GNU Lesser General //// |
//// Public License along with this source; if not, download it //// |
//// from http://www.opencores.org/lgpl.shtml //// |
//// //// |
////////////////////////////////////////////////////////////////////// |
|
// LFSR counter |
module ctrl_counter ( clear, cke, zq, rst, clk); |
|
parameter length = 5; |
input clear; |
input cke; |
output reg zq; |
input rst; |
input clk; |
|
parameter clear_value = 0; |
parameter set_value = 0; |
parameter wrap_value = 31; |
|
reg [length:1] qi; |
reg lfsr_fb; |
wire [length:1] q_next; |
reg [32:1] polynom; |
integer i; |
|
always @ (qi) |
begin |
case (length) |
2: polynom = 32'b11; // 0x3 |
3: polynom = 32'b110; // 0x6 |
4: polynom = 32'b1100; // 0xC |
5: polynom = 32'b10100; // 0x14 |
6: polynom = 32'b110000; // 0x30 |
7: polynom = 32'b1100000; // 0x60 |
8: polynom = 32'b10111000; // 0xb8 |
9: polynom = 32'b100010000; // 0x110 |
10: polynom = 32'b1001000000; // 0x240 |
11: polynom = 32'b10100000000; // 0x500 |
12: polynom = 32'b100000101001; // 0x829 |
13: polynom = 32'b1000000001100; // 0x100C |
14: polynom = 32'b10000000010101; // 0x2015 |
15: polynom = 32'b110000000000000; // 0x6000 |
16: polynom = 32'b1101000000001000; // 0xD008 |
17: polynom = 32'b10010000000000000; // 0x12000 |
18: polynom = 32'b100000010000000000; // 0x20400 |
19: polynom = 32'b1000000000000100011; // 0x40023 |
20: polynom = 32'b10000010000000000000; // 0x82000 |
21: polynom = 32'b101000000000000000000; // 0x140000 |
22: polynom = 32'b1100000000000000000000; // 0x300000 |
23: polynom = 32'b10000100000000000000000; // 0x420000 |
24: polynom = 32'b111000010000000000000000; // 0xE10000 |
25: polynom = 32'b1001000000000000000000000; // 0x1200000 |
26: polynom = 32'b10000000000000000000100011; // 0x2000023 |
27: polynom = 32'b100000000000000000000010011; // 0x4000013 |
28: polynom = 32'b1100100000000000000000000000; // 0xC800000 |
29: polynom = 32'b10100000000000000000000000000; // 0x14000000 |
30: polynom = 32'b100000000000000000000000101001; // 0x20000029 |
31: polynom = 32'b1001000000000000000000000000000; // 0x48000000 |
32: polynom = 32'b10000000001000000000000000000011; // 0x80200003 |
default: polynom = 32'b0; |
endcase |
lfsr_fb = qi[length]; |
for (i=length-1; i>=1; i=i-1) begin |
if (polynom[i]) |
lfsr_fb = lfsr_fb ~^ qi[i]; |
end |
end |
assign q_next = clear ? {length{1'b0}} :{qi[length-1:1],lfsr_fb}; |
|
always @ (posedge clk or posedge rst) |
if (rst) |
qi <= {length{1'b0}}; |
else |
if (cke) |
qi <= q_next; |
|
|
|
always @ (posedge clk or posedge rst) |
if (rst) |
zq <= 1'b1; |
else |
if (cke) |
zq <= q_next == {length{1'b0}}; |
endmodule |
`include "versatile_mem_ctrl_defines.v" |
|
module fifo |
( |
// A side |
input [35:0] a_dat_i, |
input a_we_i, |
input [2:0] a_fifo_sel_i, |
output [7:0] a_fifo_full_o, |
input a_clk, |
// B side |
output [35:0] b_dat_o, |
input b_re_i, |
input [2:0] b_fifo_sel_i, |
output [7:0] b_fifo_empty_o, |
input b_clk, |
// Common |
input rst |
); |
|
wire [4:0] wadr0, radr0; |
wire [4:0] wadr1, radr1; |
wire [4:0] wadr2, radr2; |
wire [4:0] wadr3, radr3; |
wire [4:0] wadr4, radr4; |
wire [4:0] wadr5, radr5; |
wire [4:0] wadr6, radr6; |
wire [4:0] wadr7, radr7; |
|
`ifdef PORT0 |
wire [4:0] wptr0, rptr0; |
`endif |
`ifdef PORT1 |
wire [4:0] wptr1, rptr1; |
`endif |
`ifdef PORT2 |
wire [4:0] wptr2, rptr2; |
`endif |
`ifdef PORT3 |
wire [4:0] wptr3, rptr3; |
`endif |
`ifdef PORT4 |
wire [4:0] wptr4, rptr4; |
`endif |
`ifdef PORT5 |
wire [4:0] wptr5, rptr5; |
`endif |
`ifdef PORT6 |
wire [4:0] wptr6, rptr6; |
`endif |
`ifdef PORT7 |
wire [4:0] wptr7, rptr7; |
`endif |
|
wire [7:0] dpram_a_a, dpram_a_b; |
|
// WB#0 |
`ifdef PORT0 |
fifo_adr_counter wptr0_cnt |
( |
.q(wptr0), |
.q_bin(wadr0), |
.cke(a_we_i & (a_fifo_sel_i==3'h0)), |
.clk(a_clk), |
.rst(rst) |
); |
|
fifo_adr_counter rptr0_cnt |
( |
.q(rptr0), |
.q_bin(radr0), |
.cke(b_re_i & (b_fifo_sel_i==3'h0)), |
.clk(b_clk), |
.rst(rst) |
); |
|
versatile_fifo_async_cmp |
# |
( |
.ADDR_WIDTH(5) |
) |
cmp0 |
( |
.wptr(wptr0), |
.rptr(rptr0), |
.fifo_empty(b_fifo_empty_o[0]), |
.fifo_full(a_fifo_full_o[0]), |
.wclk(a_clk), |
.rclk(b_clk), |
.rst(rst) |
); |
`else // !`ifdef PORT0 |
assign wptr0 = 5'h0; |
assign wadr0 = 5'h0; |
assign rptr0 = 5'h0; |
assign radr0 = 5'h0; |
assign a_fifo_full_o[0] = 1'b0; |
assign b_fifo_empty_o[0] = 1'b1; |
`endif // !`ifdef PORT0 |
|
// WB#1 |
`ifdef PORT1 |
fifo_adr_counter wptr1_cnt |
( |
.q(wptr1), |
.q_bin(wadr1), |
.cke(a_we_i & (a_fifo_sel_i==3'h1)), |
.clk(a_clk), |
.rst(rst) |
); |
|
fifo_adr_counter rptr1_cnt |
( |
.q(rptr1), |
.q_bin(radr1), |
.cke(b_re_i & (b_fifo_sel_i==3'h1)), |
.clk(b_clk), |
.rst(rst) |
); |
|
versatile_fifo_async_cmp |
# |
( |
.ADDR_WIDTH(5) |
) |
cmp1 |
( |
.wptr(wptr1), |
.rptr(rptr1), |
.fifo_empty(b_fifo_empty_o[1]), |
.fifo_full(a_fifo_full_o[1]), |
.wclk(a_clk), |
.rclk(b_clk), |
.rst(rst) |
); |
`else // !`ifdef PORT1 |
assign wptr1 = 5'h0; |
assign wadr1 = 5'h0; |
assign rptr1 = 5'h0; |
assign radr1 = 5'h0; |
assign a_fifo_full_o[1] = 1'b0; |
assign b_fifo_empty_o[1] = 1'b1; |
`endif // !`ifdef PORT1 |
|
// WB#2 |
`ifdef PORT2 |
fifo_adr_counter wptr2_cnt |
( |
.q(wptr2), |
.q_bin(wadr2), |
.cke(a_we_i & (a_fifo_sel_i==3'h2)), |
.clk(a_clk), |
.rst(rst) |
); |
|
fifo_adr_counter rptr2_cnt |
( |
.q(rptr2), |
.q_bin(radr2), |
.cke(b_re_i & (b_fifo_sel_i==3'h2)), |
.clk(b_clk), |
.rst(rst) |
); |
|
versatile_fifo_async_cmp |
# |
( |
.ADDR_WIDTH(5) |
) |
cmp2 |
( |
.wptr(wptr2), |
.rptr(rptr2), |
.fifo_empty(b_fifo_empty_o[2]), |
.fifo_full(a_fifo_full_o[2]), |
.wclk(a_clk), |
.rclk(b_clk), |
.rst(rst) |
); |
`else // !`ifdef PORT2 |
assign wptr2 = 5'h0; |
assign wadr2 = 5'h0; |
assign rptr2 = 5'h0; |
assign radr2 = 5'h0; |
assign a_fifo_full_o[2] = 1'b0; |
assign b_fifo_empty_o[2] = 1'b1; |
`endif // !`ifdef PORT2 |
|
// WB#3 |
`ifdef PORT3 |
fifo_adr_counter wptr3_cnt |
( |
.q(wptr3), |
.q_bin(wadr3), |
.cke(a_we_i & (a_fifo_sel_i==3'h3)), |
.clk(a_clk), |
.rst(rst) |
); |
|
fifo_adr_counter rptr3_cnt |
( |
.q(rptr3), |
.q_bin(radr3), |
.cke(b_re_i & (b_fifo_sel_i==3'h3)), |
.clk(b_clk), |
.rst(rst) |
); |
|
versatile_fifo_async_cmp |
# |
( |
.ADDR_WIDTH(5) |
) |
cmp3 |
( |
.wptr(wptr3), |
.rptr(rptr3), |
.fifo_empty(b_fifo_empty_o[3]), |
.fifo_full(a_fifo_full_o[3]), |
.wclk(a_clk), |
.rclk(b_clk), |
.rst(rst) |
); |
`else // !`ifdef PORT3 |
assign wptr3 = 5'h0; |
assign wadr3 = 5'h0; |
assign rptr3 = 5'h0; |
assign radr3 = 5'h0; |
assign a_fifo_full_o[3] = 1'b0; |
assign b_fifo_empty_o[3] = 1'b1; |
`endif // !`ifdef PORT3 |
|
// WB#4 |
`ifdef PORT4 |
fifo_adr_counter wptr4_cnt |
( |
.q(wptr4), |
.q_bin(wadr4), |
.cke(a_we_i & (a_fifo_sel_i==3'h4)), |
.clk(a_clk), |
.rst(rst) |
); |
|
fifo_adr_counter rptr4_cnt |
( |
.q(rptr4), |
.q_bin(radr4), |
.cke(b_re_i & (b_fifo_sel_i==3'h4)), |
.clk(b_clk), |
.rst(rst) |
); |
|
versatile_fifo_async_cmp |
# |
( |
.ADDR_WIDTH(5) |
) |
cmp4 |
( |
.wptr(wptr4), |
.rptr(rptr4), |
.fifo_empty(b_fifo_empty_o[4]), |
.fifo_full(a_fifo_full_o[4]), |
.wclk(a_clk), |
.rclk(b_clk), |
.rst(rst) |
); |
`else // !`ifdef PORT4 |
assign wptr4 = 5'h0; |
assign wadr4 = 5'h0; |
assign rptr4 = 5'h0; |
assign radr4 = 5'h0; |
assign a_fifo_full_o[4] = 1'b0; |
assign b_fifo_empty_o[4] = 1'b1; |
`endif // !`ifdef PORT4 |
|
// WB#5 |
`ifdef PORT5 |
fifo_adr_counter wptr5_cnt |
( |
.q(wptr5), |
.q_bin(wadr5), |
.cke(a_we_i & (a_fifo_sel_i==3'h5)), |
.clk(a_clk), |
.rst(rst) |
); |
|
fifo_adr_counter rptr5_cnt |
( |
.q(rptr5), |
.q_bin(radr5), |
.cke(b_re_i & (b_fifo_sel_i==3'h5)), |
.clk(b_clk), |
.rst(rst) |
); |
|
versatile_fifo_async_cmp |
# |
( |
.ADDR_WIDTH(5) |
) |
cmp5 |
( |
.wptr(wptr5), |
.rptr(rptr5), |
.fifo_empty(b_fifo_empty_o[5]), |
.fifo_full(a_fifo_full_o[5]), |
.wclk(a_clk), |
.rclk(b_clk), |
.rst(rst) |
); |
`else // !`ifdef PORT5 |
assign wptr5 = 5'h0; |
assign wadr5 = 5'h0; |
assign rptr5 = 5'h0; |
assign radr5 = 5'h0; |
assign a_fifo_full_o[5] = 1'b0; |
assign b_fifo_empty_o[5] = 1'b1; |
`endif // !`ifdef PORT5 |
|
// WB#6 |
`ifdef PORT6 |
fifo_adr_counter wptr6_cnt |
( |
.q(wptr6), |
.q_bin(wadr6), |
.cke(a_we_i & (a_fifo_sel_i==3'h6)), |
.clk(a_clk), |
.rst(rst) |
); |
|
fifo_adr_counter rptr6_cnt |
( |
.q(rptr6), |
.q_bin(radr6), |
.cke(b_re_i & (b_fifo_sel_i==3'h6)), |
.clk(b_clk), |
.rst(rst) |
); |
|
versatile_fifo_async_cmp |
# |
( |
.ADDR_WIDTH(5) |
) |
cmp6 |
( |
.wptr(wptr6), |
.rptr(rptr6), |
.fifo_empty(b_fifo_empty_o[6]), |
.fifo_full(a_fifo_full_o[6]), |
.wclk(a_clk), |
.rclk(b_clk), |
.rst(rst) |
); |
`else // !`ifdef PORT6 |
assign wptr6 = 5'h0; |
assign wadr6 = 5'h0; |
assign rptr6 = 5'h0; |
assign radr6 = 5'h0; |
assign a_fifo_full_o[6] = 1'b0; |
assign b_fifo_empty_o[6] = 1'b1; |
`endif // !`ifdef PORT6 |
|
// WB#7 |
`ifdef PORT7 |
fifo_adr_counter wptr7_cnt |
( |
.q(wptr7), |
.q_bin(wadr7), |
.cke(a_we_i & (a_fifo_sel_i==3'h7)), |
.clk(a_clk), |
.rst(rst) |
); |
|
fifo_adr_counter rptr7_cnt |
( |
.q(rptr7), |
.q_bin(radr7), |
.cke(b_re_i & (b_fifo_sel_i==3'h7)), |
.clk(b_clk), |
.rst(rst) |
); |
|
versatile_fifo_async_cmp |
# |
( |
.ADDR_WIDTH(5) |
) |
cmp7 |
( |
.wptr(wptr7), |
.rptr(rptr7), |
.fifo_empty(b_fifo_empty_o[7]), |
.fifo_full(a_fifo_full_o[7]), |
.wclk(a_clk), |
.rclk(b_clk), |
.rst(rst) |
); |
`else // !`ifdef PORT7 |
assign wptr7 = 5'h0; |
assign wadr7 = 5'h0; |
assign rptr7 = 5'h0; |
assign radr7 = 5'h0; |
assign a_fifo_full_o[7] = 1'b0; |
assign b_fifo_empty_o[7] = 1'b1; |
`endif // !`ifdef PORT7 |
|
assign dpram_a_a = (a_fifo_sel_i==3'd0) ? {a_fifo_sel_i,wadr0} : |
(a_fifo_sel_i==3'd1) ? {a_fifo_sel_i,wadr1} : |
(a_fifo_sel_i==3'd2) ? {a_fifo_sel_i,wadr2} : |
(a_fifo_sel_i==3'd3) ? {a_fifo_sel_i,wadr3} : |
(a_fifo_sel_i==3'd4) ? {a_fifo_sel_i,wadr4} : |
(a_fifo_sel_i==3'd5) ? {a_fifo_sel_i,wadr5} : |
(a_fifo_sel_i==3'd6) ? {a_fifo_sel_i,wadr6} : |
{a_fifo_sel_i,wadr7} ; |
|
assign dpram_a_b = (b_fifo_sel_i==3'd0) ? {b_fifo_sel_i,radr0} : |
(b_fifo_sel_i==3'd1) ? {b_fifo_sel_i,radr1} : |
(b_fifo_sel_i==3'd2) ? {b_fifo_sel_i,radr2} : |
(b_fifo_sel_i==3'd3) ? {b_fifo_sel_i,radr3} : |
(b_fifo_sel_i==3'd4) ? {b_fifo_sel_i,radr4} : |
(b_fifo_sel_i==3'd5) ? {b_fifo_sel_i,radr5} : |
(b_fifo_sel_i==3'd6) ? {b_fifo_sel_i,radr6} : |
{b_fifo_sel_i,radr7} ; |
|
|
`ifdef ACTEL |
TwoPortRAM_256x36 dpram |
( |
.WD(a_dat_i), |
.RD(b_dat_o), |
.WEN(a_we_i), |
//.REN(b_re_i), |
.REN(1'b1), |
.WADDR(dpram_a_a), |
.RADDR(dpram_a_b), |
.WCLK(a_clk), |
.RCLK(b_clk) |
); |
`else |
vfifo_dual_port_ram_dc_dw |
/* # |
( |
.ADDR_WIDTH(8), |
.DATA_WIDTH(36) |
)*/ |
dpram |
( |
.d_a(a_dat_i), |
.q_a(), |
.adr_a(dpram_a_a), |
.we_a(a_we_i), |
.clk_a(a_clk), |
.q_b(b_dat_o), |
.adr_b(dpram_a_b), |
.d_b(36'h0), |
.we_b(1'b0), |
.clk_b(b_clk) |
); |
`endif |
endmodule // sd_fifo |
`define EOB (!(|cti) | &cti) |
module fifo_fill ( |
output reg wbs_flag, |
output reg we_req, |
input wire ack, |
input wire [1:0] bte, |
input wire clk, |
input wire [2:0] cti, |
input wire cyc, |
input wire rst, |
input wire stb, |
input wire we, |
input wire we_ack |
); |
|
|
// state bits |
parameter |
idle = 0, |
state1 = 1, |
state10 = 2, |
state11 = 3, |
state12 = 4, |
state13 = 5, |
state14 = 6, |
state15 = 7, |
state16 = 8, |
state2 = 9, |
state3 = 10, |
state4 = 11, |
state5 = 12, |
state6 = 13, |
state7 = 14, |
state8 = 15, |
state9 = 16; |
|
reg [16:0] state; |
reg [16:0] nextstate; |
|
// comb always block |
always @* begin |
nextstate = 17'b00000000000000000; |
wbs_flag = 1'b0; // default |
we_req = we & stb; // default |
case (1'b1) // synopsys parallel_case full_case |
state[idle] : begin |
wbs_flag = 1'b1; |
we_req = cyc & stb; |
if (cyc & stb & we_ack) begin |
nextstate[state1] = 1'b1; |
end |
else begin |
nextstate[idle] = 1'b1; // Added because implied_loopback is true |
end |
end |
state[state1] : begin |
if (`EOB & ack) begin |
nextstate[idle] = 1'b1; |
end |
else if (ack) begin |
nextstate[state2] = 1'b1; |
end |
else begin |
nextstate[state1] = 1'b1; // Added because implied_loopback is true |
end |
end |
state[state10]: begin |
if (`EOB & ack) begin |
nextstate[idle] = 1'b1; |
end |
else if (ack) begin |
nextstate[state11] = 1'b1; |
end |
else begin |
nextstate[state10] = 1'b1; // Added because implied_loopback is true |
end |
end |
state[state11]: begin |
if (`EOB & ack) begin |
nextstate[idle] = 1'b1; |
end |
else if (ack) begin |
nextstate[state12] = 1'b1; |
end |
else begin |
nextstate[state11] = 1'b1; // Added because implied_loopback is true |
end |
end |
state[state12]: begin |
if (`EOB & ack) begin |
nextstate[idle] = 1'b1; |
end |
else if (ack) begin |
nextstate[state13] = 1'b1; |
end |
else begin |
nextstate[state12] = 1'b1; // Added because implied_loopback is true |
end |
end |
state[state13]: begin |
if (`EOB & ack) begin |
nextstate[idle] = 1'b1; |
end |
else if (ack) begin |
nextstate[state14] = 1'b1; |
end |
else begin |
nextstate[state13] = 1'b1; // Added because implied_loopback is true |
end |
end |
state[state14]: begin |
if (`EOB & ack) begin |
nextstate[idle] = 1'b1; |
end |
else if (ack) begin |
nextstate[state15] = 1'b1; |
end |
else begin |
nextstate[state14] = 1'b1; // Added because implied_loopback is true |
end |
end |
state[state15]: begin |
if (`EOB & ack) begin |
nextstate[idle] = 1'b1; |
end |
else if (ack) begin |
nextstate[state16] = 1'b1; |
end |
else begin |
nextstate[state15] = 1'b1; // Added because implied_loopback is true |
end |
end |
state[state16]: begin |
if (ack) begin |
nextstate[idle] = 1'b1; |
end |
else begin |
nextstate[state16] = 1'b1; // Added because implied_loopback is true |
end |
end |
state[state2] : begin |
if (`EOB & ack) begin |
nextstate[idle] = 1'b1; |
end |
else if (ack) begin |
nextstate[state3] = 1'b1; |
end |
else begin |
nextstate[state2] = 1'b1; // Added because implied_loopback is true |
end |
end |
state[state3] : begin |
if (`EOB & ack) begin |
nextstate[idle] = 1'b1; |
end |
else if (ack) begin |
nextstate[state4] = 1'b1; |
end |
else begin |
nextstate[state3] = 1'b1; // Added because implied_loopback is true |
end |
end |
state[state4] : begin |
if (`EOB & ack) begin |
nextstate[idle] = 1'b1; |
end |
else if ((bte==2'b01) & ack) begin |
nextstate[idle] = 1'b1; |
end |
else if (ack) begin |
nextstate[state5] = 1'b1; |
end |
else begin |
nextstate[state4] = 1'b1; // Added because implied_loopback is true |
end |
end |
state[state5] : begin |
if (`EOB & ack) begin |
nextstate[idle] = 1'b1; |
end |
else if (ack) begin |
nextstate[state6] = 1'b1; |
end |
else begin |
nextstate[state5] = 1'b1; // Added because implied_loopback is true |
end |
end |
state[state6] : begin |
if (`EOB & ack) begin |
nextstate[idle] = 1'b1; |
end |
else if (ack) begin |
nextstate[state7] = 1'b1; |
end |
else begin |
nextstate[state6] = 1'b1; // Added because implied_loopback is true |
end |
end |
state[state7] : begin |
if (`EOB & ack) begin |
nextstate[idle] = 1'b1; |
end |
else if (ack) begin |
nextstate[state8] = 1'b1; |
end |
else begin |
nextstate[state7] = 1'b1; // Added because implied_loopback is true |
end |
end |
state[state8] : begin |
if (`EOB & ack) begin |
nextstate[idle] = 1'b1; |
end |
else if ((bte==2'b10) & ack) begin |
nextstate[idle] = 1'b1; |
end |
else if (ack) begin |
nextstate[state9] = 1'b1; |
end |
else begin |
nextstate[state8] = 1'b1; // Added because implied_loopback is true |
end |
end |
state[state9] : begin |
if (`EOB & ack) begin |
nextstate[idle] = 1'b1; |
end |
else if (ack) begin |
nextstate[state10] = 1'b1; |
end |
else begin |
nextstate[state9] = 1'b1; // Added because implied_loopback is true |
end |
end |
endcase |
end |
|
// sequential always block |
always @(posedge clk or posedge rst) begin |
if (rst) |
state <= 17'b00000000000000001 << idle; |
else |
state <= nextstate; |
end |
|
// This code allows you to see state names in simulation |
`ifndef SYNTHESIS |
reg [55:0] statename; |
always @* begin |
case (1'b1) |
state[idle] : |
statename = "idle"; |
state[state1] : |
statename = "state1"; |
state[state10]: |
statename = "state10"; |
state[state11]: |
statename = "state11"; |
state[state12]: |
statename = "state12"; |
state[state13]: |
statename = "state13"; |
state[state14]: |
statename = "state14"; |
state[state15]: |
statename = "state15"; |
state[state16]: |
statename = "state16"; |
state[state2] : |
statename = "state2"; |
state[state3] : |
statename = "state3"; |
state[state4] : |
statename = "state4"; |
state[state5] : |
statename = "state5"; |
state[state6] : |
statename = "state6"; |
state[state7] : |
statename = "state7"; |
state[state8] : |
statename = "state8"; |
state[state9] : |
statename = "state9"; |
default: |
statename = "XXXXXXX"; |
endcase |
end |
`endif |
|
|
endmodule |
|
module inc_adr |
( |
input [3:0] adr_i, |
input [2:0] cti_i, |
input [1:0] bte_i, |
input init, |
input inc, |
output reg [3:0] adr_o, |
output reg done, |
input clk, |
input rst |
); |
|
reg init_i; |
|
reg [1:0] bte; |
reg [3:0] cnt; |
|
// delay init one clock cycle to be able to read from mem |
always @ (posedge clk or posedge rst) |
if (rst) |
init_i <= 1'b0; |
else |
init_i <= init; |
|
// bte |
always @ (posedge clk or posedge rst) |
if (rst) |
bte <= 2'b00; |
else |
if (init_i) |
bte <= bte_i; |
|
// adr_o |
always @ (posedge clk or posedge rst) |
if (rst) |
adr_o <= 4'd0; |
else |
if (init_i) |
adr_o <= adr_i; |
else |
if (inc) |
case (bte) |
2'b01: adr_o <= {adr_o[3:2], adr_o[1:0] + 2'd1}; |
2'b10: adr_o <= {adr_o[3], adr_o[2:0] + 3'd1}; |
default: adr_o <= adr_o + 4'd1; |
endcase // case (bte) |
|
// done |
always @ (posedge clk or posedge rst) |
if (rst) |
{done,cnt} <= {1'b0,4'd0}; |
else |
if (init_i) |
begin |
done <= ({bte_i,cti_i} == {2'b00,3'b000}); |
case (bte_i) |
2'b01: cnt <= 4'd12; |
2'b10: cnt <= 4'd8; |
2'b11: cnt <= 4'd0; |
default: cnt <= adr_i; |
endcase |
end |
else |
if (inc) |
{done,cnt} <= cnt + 4'd1; |
|
endmodule // inc_adr |
|
|
////////////////////////////////////////////////////////////////////// |
//// //// |
//// Versatile counter //// |
//// //// |
//// Description //// |
//// Versatile counter, a reconfigurable binary, gray or LFSR //// |
//// counter //// |
//// //// |
//// To Do: //// |
//// - add LFSR with more taps //// |
//// //// |
//// Author(s): //// |
//// - Michael Unneback, unneback@opencores.org //// |
//// ORSoC AB //// |
//// //// |
////////////////////////////////////////////////////////////////////// |
//// //// |
//// Copyright (C) 2009 Authors and OPENCORES.ORG //// |
//// //// |
//// This source file may be used and distributed without //// |
//// restriction provided that this copyright statement is not //// |
//// removed from the file and that any derivative work contains //// |
//// the original copyright notice and the associated disclaimer. //// |
//// //// |
//// This source file is free software; you can redistribute it //// |
//// and/or modify it under the terms of the GNU Lesser General //// |
//// Public License as published by the Free Software Foundation; //// |
//// either version 2.1 of the License, or (at your option) any //// |
//// later version. //// |
//// //// |
//// This source is distributed in the hope that it will be //// |
//// useful, but WITHOUT ANY WARRANTY; without even the implied //// |
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// |
//// PURPOSE. See the GNU Lesser General Public License for more //// |
//// details. //// |
//// //// |
//// You should have received a copy of the GNU Lesser General //// |
//// Public License along with this source; if not, download it //// |
//// from http://www.opencores.org/lgpl.shtml //// |
//// //// |
////////////////////////////////////////////////////////////////////// |
|
// LFSR counter |
module ref_counter ( zq, rst, clk); |
|
parameter length = 10; |
output reg zq; |
input rst; |
input clk; |
|
parameter clear_value = 0; |
parameter set_value = 0; |
parameter wrap_value = 417; |
|
reg [length:1] qi; |
reg lfsr_fb; |
wire [length:1] q_next; |
reg [32:1] polynom; |
integer i; |
|
always @ (qi) |
begin |
case (length) |
2: polynom = 32'b11; // 0x3 |
3: polynom = 32'b110; // 0x6 |
4: polynom = 32'b1100; // 0xC |
5: polynom = 32'b10100; // 0x14 |
6: polynom = 32'b110000; // 0x30 |
7: polynom = 32'b1100000; // 0x60 |
8: polynom = 32'b10111000; // 0xb8 |
9: polynom = 32'b100010000; // 0x110 |
10: polynom = 32'b1001000000; // 0x240 |
11: polynom = 32'b10100000000; // 0x500 |
12: polynom = 32'b100000101001; // 0x829 |
13: polynom = 32'b1000000001100; // 0x100C |
14: polynom = 32'b10000000010101; // 0x2015 |
15: polynom = 32'b110000000000000; // 0x6000 |
16: polynom = 32'b1101000000001000; // 0xD008 |
17: polynom = 32'b10010000000000000; // 0x12000 |
18: polynom = 32'b100000010000000000; // 0x20400 |
19: polynom = 32'b1000000000000100011; // 0x40023 |
20: polynom = 32'b10000010000000000000; // 0x82000 |
21: polynom = 32'b101000000000000000000; // 0x140000 |
22: polynom = 32'b1100000000000000000000; // 0x300000 |
23: polynom = 32'b10000100000000000000000; // 0x420000 |
24: polynom = 32'b111000010000000000000000; // 0xE10000 |
25: polynom = 32'b1001000000000000000000000; // 0x1200000 |
26: polynom = 32'b10000000000000000000100011; // 0x2000023 |
27: polynom = 32'b100000000000000000000010011; // 0x4000013 |
28: polynom = 32'b1100100000000000000000000000; // 0xC800000 |
29: polynom = 32'b10100000000000000000000000000; // 0x14000000 |
30: polynom = 32'b100000000000000000000000101001; // 0x20000029 |
31: polynom = 32'b1001000000000000000000000000000; // 0x48000000 |
32: polynom = 32'b10000000001000000000000000000011; // 0x80200003 |
default: polynom = 32'b0; |
endcase |
lfsr_fb = qi[length]; |
for (i=length-1; i>=1; i=i-1) begin |
if (polynom[i]) |
lfsr_fb = lfsr_fb ~^ qi[i]; |
end |
end |
assign q_next = (qi == wrap_value) ? {length{1'b0}} :{qi[length-1:1],lfsr_fb}; |
|
always @ (posedge clk or posedge rst) |
if (rst) |
qi <= {length{1'b0}}; |
else |
qi <= q_next; |
|
|
|
always @ (posedge clk or posedge rst) |
if (rst) |
zq <= 1'b1; |
else |
zq <= q_next == {length{1'b0}}; |
endmodule |
////////////////////////////////////////////////////////////////////// |
//// //// |
//// Versatile counter //// |
//// //// |
//// Description //// |
//// Versatile counter, a reconfigurable binary, gray or LFSR //// |
//// counter //// |
//// //// |
//// To Do: //// |
//// - add LFSR with more taps //// |
//// //// |
//// Author(s): //// |
//// - Michael Unneback, unneback@opencores.org //// |
//// ORSoC AB //// |
//// //// |
////////////////////////////////////////////////////////////////////// |
//// //// |
//// Copyright (C) 2009 Authors and OPENCORES.ORG //// |
//// //// |
//// This source file may be used and distributed without //// |
//// restriction provided that this copyright statement is not //// |
//// removed from the file and that any derivative work contains //// |
//// the original copyright notice and the associated disclaimer. //// |
//// //// |
//// This source file is free software; you can redistribute it //// |
//// and/or modify it under the terms of the GNU Lesser General //// |
//// Public License as published by the Free Software Foundation; //// |
//// either version 2.1 of the License, or (at your option) any //// |
//// later version. //// |
//// //// |
//// This source is distributed in the hope that it will be //// |
//// useful, but WITHOUT ANY WARRANTY; without even the implied //// |
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// |
//// PURPOSE. See the GNU Lesser General Public License for more //// |
//// details. //// |
//// //// |
//// You should have received a copy of the GNU Lesser General //// |
//// Public License along with this source; if not, download it //// |
//// from http://www.opencores.org/lgpl.shtml //// |
//// //// |
////////////////////////////////////////////////////////////////////// |
|
// BINARY counter |
module ref_delay_counter ( cke, zq, rst, clk); |
|
parameter length = 6; |
input cke; |
output reg zq; |
input rst; |
input clk; |
|
parameter clear_value = 0; |
parameter set_value = 0; |
parameter wrap_value = 12; |
|
reg [length:1] qi; |
wire [length:1] q_next; |
assign q_next = qi + {{length-1{1'b0}},1'b1}; |
|
always @ (posedge clk or posedge rst) |
if (rst) |
qi <= {length{1'b0}}; |
else |
if (cke) |
qi <= q_next; |
|
|
|
always @ (posedge clk or posedge rst) |
if (rst) |
zq <= 1'b1; |
else |
if (cke) |
zq <= q_next == {length{1'b0}}; |
endmodule |
////////////////////////////////////////////////////////////////////// |
//// //// |
//// Versatile counter //// |
//// //// |
//// Description //// |
//// Versatile counter, a reconfigurable binary, gray or LFSR //// |
//// counter //// |
//// //// |
//// To Do: //// |
//// - add LFSR with more taps //// |
//// //// |
//// Author(s): //// |
//// - Michael Unneback, unneback@opencores.org //// |
//// ORSoC AB //// |
//// //// |
////////////////////////////////////////////////////////////////////// |
//// //// |
//// Copyright (C) 2009 Authors and OPENCORES.ORG //// |
//// //// |
//// This source file may be used and distributed without //// |
//// restriction provided that this copyright statement is not //// |
//// removed from the file and that any derivative work contains //// |
//// the original copyright notice and the associated disclaimer. //// |
//// //// |
//// This source file is free software; you can redistribute it //// |
//// and/or modify it under the terms of the GNU Lesser General //// |
//// Public License as published by the Free Software Foundation; //// |
//// either version 2.1 of the License, or (at your option) any //// |
//// later version. //// |
//// //// |
//// This source is distributed in the hope that it will be //// |
//// useful, but WITHOUT ANY WARRANTY; without even the implied //// |
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// |
//// PURPOSE. See the GNU Lesser General Public License for more //// |
//// details. //// |
//// //// |
//// You should have received a copy of the GNU Lesser General //// |
//// Public License along with this source; if not, download it //// |
//// from http://www.opencores.org/lgpl.shtml //// |
//// //// |
////////////////////////////////////////////////////////////////////// |
|
// BINARY counter |
module pre_delay_counter ( cke, zq, rst, clk); |
|
parameter length = 2; |
input cke; |
output reg zq; |
input rst; |
input clk; |
|
parameter clear_value = 0; |
parameter set_value = 0; |
parameter wrap_value = 2; |
|
reg [length:1] qi; |
wire [length:1] q_next; |
assign q_next = qi + {{length-1{1'b0}},1'b1}; |
|
always @ (posedge clk or posedge rst) |
if (rst) |
qi <= {length{1'b0}}; |
else |
if (cke) |
qi <= q_next; |
|
|
|
always @ (posedge clk or posedge rst) |
if (rst) |
zq <= 1'b1; |
else |
if (cke) |
zq <= q_next == {length{1'b0}}; |
endmodule |
////////////////////////////////////////////////////////////////////// |
//// //// |
//// Versatile counter //// |
//// //// |
//// Description //// |
//// Versatile counter, a reconfigurable binary, gray or LFSR //// |
//// counter //// |
//// //// |
//// To Do: //// |
//// - add LFSR with more taps //// |
//// //// |
//// Author(s): //// |
//// - Michael Unneback, unneback@opencores.org //// |
//// ORSoC AB //// |
//// //// |
////////////////////////////////////////////////////////////////////// |
//// //// |
//// Copyright (C) 2009 Authors and OPENCORES.ORG //// |
//// //// |
//// This source file may be used and distributed without //// |
//// restriction provided that this copyright statement is not //// |
//// removed from the file and that any derivative work contains //// |
//// the original copyright notice and the associated disclaimer. //// |
//// //// |
//// This source file is free software; you can redistribute it //// |
//// and/or modify it under the terms of the GNU Lesser General //// |
//// Public License as published by the Free Software Foundation; //// |
//// either version 2.1 of the License, or (at your option) any //// |
//// later version. //// |
//// //// |
//// This source is distributed in the hope that it will be //// |
//// useful, but WITHOUT ANY WARRANTY; without even the implied //// |
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// |
//// PURPOSE. See the GNU Lesser General Public License for more //// |
//// details. //// |
//// //// |
//// You should have received a copy of the GNU Lesser General //// |
//// Public License along with this source; if not, download it //// |
//// from http://www.opencores.org/lgpl.shtml //// |
//// //// |
////////////////////////////////////////////////////////////////////// |
|
// BINARY counter |
module burst_length_counter ( cke, zq, rst, clk); |
|
parameter length = 3; |
input cke; |
output reg zq; |
input rst; |
input clk; |
|
parameter clear_value = 0; |
parameter set_value = 0; |
parameter wrap_value = 3; |
|
reg [length:1] qi; |
wire [length:1] q_next; |
assign q_next = qi + {{length-1{1'b0}},1'b1}; |
|
always @ (posedge clk or posedge rst) |
if (rst) |
qi <= {length{1'b0}}; |
else |
if (cke) |
qi <= q_next; |
|
|
|
always @ (posedge clk or posedge rst) |
if (rst) |
zq <= 1'b1; |
else |
if (cke) |
zq <= q_next == {length{1'b0}}; |
endmodule |
module versatile_fifo_async_cmp ( wptr, rptr, fifo_empty, fifo_full, wclk, rclk, rst ); |
parameter ADDR_WIDTH = 4; |
parameter N = ADDR_WIDTH-1; |
parameter Q1 = 2'b00; |
parameter Q2 = 2'b01; |
parameter Q3 = 2'b11; |
parameter Q4 = 2'b10; |
parameter going_empty = 1'b0; |
parameter going_full = 1'b1; |
input [N:0] wptr, rptr; |
output reg fifo_empty; |
output fifo_full; |
input wclk, rclk, rst; |
wire direction; |
reg direction_set, direction_clr; |
wire async_empty, async_full; |
wire fifo_full2; |
reg fifo_empty2; |
always @ (wptr[N:N-1] or rptr[N:N-1]) |
case ({wptr[N:N-1],rptr[N:N-1]}) |
{Q1,Q2} : direction_set <= 1'b1; |
{Q2,Q3} : direction_set <= 1'b1; |
{Q3,Q4} : direction_set <= 1'b1; |
{Q4,Q1} : direction_set <= 1'b1; |
default : direction_set <= 1'b0; |
endcase |
always @ (wptr[N:N-1] or rptr[N:N-1] or rst) |
if (rst) |
direction_clr <= 1'b1; |
else |
case ({wptr[N:N-1],rptr[N:N-1]}) |
{Q2,Q1} : direction_clr <= 1'b1; |
{Q3,Q2} : direction_clr <= 1'b1; |
{Q4,Q3} : direction_clr <= 1'b1; |
{Q1,Q4} : direction_clr <= 1'b1; |
default : direction_clr <= 1'b0; |
endcase |
dff_sr dff_sr_dir( .aclr(direction_clr), .aset(direction_set), .clock(1'b1), .data(1'b1), .q(direction)); |
assign async_empty = (wptr == rptr) && (direction==going_empty); |
assign async_full = (wptr == rptr) && (direction==going_full); |
dff_sr dff_sr_empty0( .aclr(rst), .aset(async_full), .clock(wclk), .data(async_full), .q(fifo_full2)); |
dff_sr dff_sr_empty1( .aclr(rst), .aset(async_full), .clock(wclk), .data(fifo_full2), .q(fifo_full)); |
always @ (posedge rclk or posedge async_empty) |
if (async_empty) |
{fifo_empty, fifo_empty2} <= 2'b11; |
else |
{fifo_empty,fifo_empty2} <= {fifo_empty2,async_empty}; |
endmodule |
module async_fifo_mq ( |
d, fifo_full, write, write_enable, clk1, rst1, |
q, fifo_empty, read, read_enable, clk2, rst2 |
); |
parameter a_hi_size = 4; |
parameter a_lo_size = 4; |
parameter nr_of_queues = 16; |
parameter data_width = 36; |
input [data_width-1:0] d; |
output [0:nr_of_queues-1] fifo_full; |
input write; |
input [0:nr_of_queues-1] write_enable; |
input clk1; |
input rst1; |
output [data_width-1:0] q; |
output [0:nr_of_queues-1] fifo_empty; |
input read; |
input [0:nr_of_queues-1] read_enable; |
input clk2; |
input rst2; |
wire [a_lo_size-1:0] fifo_wadr_bin[0:nr_of_queues-1]; |
wire [a_lo_size-1:0] fifo_wadr_gray[0:nr_of_queues-1]; |
wire [a_lo_size-1:0] fifo_radr_bin[0:nr_of_queues-1]; |
wire [a_lo_size-1:0] fifo_radr_gray[0:nr_of_queues-1]; |
reg [a_lo_size-1:0] wadr; |
reg [a_lo_size-1:0] radr; |
reg [data_width-1:0] wdata; |
wire [data_width-1:0] wdataa[0:nr_of_queues-1]; |
genvar i; |
integer j,k,l; |
function [a_lo_size-1:0] onehot2bin; |
input [0:nr_of_queues-1] a; |
integer i; |
begin |
onehot2bin = {a_lo_size{1'b0}}; |
for (i=1;i<nr_of_queues;i=i+1) begin |
if (a[i]) |
onehot2bin = i; |
end |
end |
endfunction |
generate |
for (i=0;i<nr_of_queues;i=i+1) begin : fifo_adr |
gray_counter wadrcnt ( |
.cke(write & write_enable[i]), |
.q(fifo_wadr_gray[i]), |
.q_bin(fifo_wadr_bin[i]), |
.rst(rst1), |
.clk(clk1)); |
gray_counter radrcnt ( |
.cke(read & read_enable[i]), |
.q(fifo_radr_gray[i]), |
.q_bin(fifo_radr_bin[i]), |
.rst(rst2), |
.clk(clk2)); |
versatile_fifo_async_cmp |
#(.ADDR_WIDTH(a_lo_size)) |
egresscmp ( |
.wptr(fifo_wadr_gray[i]), |
.rptr(fifo_radr_gray[i]), |
.fifo_empty(fifo_empty[i]), |
.fifo_full(fifo_full[i]), |
.wclk(clk1), |
.rclk(clk2), |
.rst(rst1)); |
end |
endgenerate |
always @* |
begin |
wadr = {a_lo_size{1'b0}}; |
for (j=0;j<nr_of_queues;j=j+1) begin |
wadr = (fifo_wadr_bin[j] & {a_lo_size{write_enable[j]}}) | wadr; |
end |
end |
always @* |
begin |
radr = {a_lo_size{1'b0}}; |
for (k=0;k<nr_of_queues;k=k+1) begin |
radr = (fifo_radr_bin[k] & {a_lo_size{read_enable[k]}}) | radr; |
end |
end |
vfifo_dual_port_ram_dc_sw # ( .DATA_WIDTH(data_width), .ADDR_WIDTH(a_hi_size+a_lo_size)) |
dpram ( |
.d_a(d), |
.adr_a({onehot2bin(write_enable),wadr}), |
.we_a(write), |
.clk_a(clk1), |
.q_b(q), |
.adr_b({onehot2bin(read_enable),radr}), |
.clk_b(clk2) ); |
endmodule |
`timescale 1ns/1ns |
module delay (d, q, clk, rst); |
parameter width = 4; |
136,7 → 1769,7
assign fifo_we_2 = (fifo_sel_domain == 2'b10) ? fifo_sel : {16{1'b0}}; |
assign fifo_we_3 = (fifo_sel_domain == 2'b11) ? fifo_sel : {16{1'b0}}; |
endmodule |
module fifo_adr_counter ( cke, q, q_bin, rst, clk); |
module gray_counter ( cke, q, q_bin, rst, clk); |
parameter length = 4; |
input cke; |
output reg [length:1] q; |
144,8 → 1777,6
input rst; |
input clk; |
parameter clear_value = 0; |
parameter set_value = 0; |
parameter wrap_value = 9; |
reg [length:1] qi; |
wire [length:1] q_next; |
assign q_next = qi + {{length-1{1'b0}},1'b1}; |
163,60 → 1794,163
q <= (q_next>>1) ^ q_next; |
assign q_bin = qi; |
endmodule |
module versatile_fifo_async_cmp ( wptr, rptr, fifo_empty, fifo_full, wclk, rclk, rst ); |
parameter ADDR_WIDTH = 4; |
parameter N = ADDR_WIDTH-1; |
parameter Q1 = 2'b00; |
parameter Q2 = 2'b01; |
parameter Q3 = 2'b11; |
parameter Q4 = 2'b10; |
parameter going_empty = 1'b0; |
parameter going_full = 1'b1; |
input [N:0] wptr, rptr; |
output reg fifo_empty, fifo_full; |
input wclk, rclk, rst; |
reg direction, direction_set, direction_clr; |
wire async_empty, async_full; |
reg fifo_full2, fifo_empty2; |
always @ (wptr[N:N-1] or rptr[N:N-1]) |
case ({wptr[N:N-1],rptr[N:N-1]}) |
{Q1,Q2} : direction_set <= 1'b1; |
{Q2,Q3} : direction_set <= 1'b1; |
{Q3,Q4} : direction_set <= 1'b1; |
{Q4,Q1} : direction_set <= 1'b1; |
default : direction_set <= 1'b0; |
endcase |
always @ (wptr[N:N-1] or rptr[N:N-1] or rst) |
if (rst) |
direction_clr <= 1'b1; |
module egress_fifo ( |
d, fifo_full, write, write_enable, clk1, rst1, |
q, fifo_empty, read_adr, read_data, read_enable, clk2, rst2 |
); |
parameter a_hi_size = 4; |
parameter a_lo_size = 4; |
parameter nr_of_queues = 16; |
parameter data_width = 36; |
input [data_width*nr_of_queues-1:0] d; |
output [0:nr_of_queues-1] fifo_full; |
input write; |
input [0:nr_of_queues-1] write_enable; |
input clk1; |
input rst1; |
output [data_width-1:0] q; |
output [0:nr_of_queues-1] fifo_empty; |
input read_adr, read_data; |
input [0:nr_of_queues-1] read_enable; |
input clk2; |
input rst2; |
wire [a_lo_size-1:0] fifo_wadr_bin[0:nr_of_queues-1]; |
wire [a_lo_size-1:0] fifo_wadr_gray[0:nr_of_queues-1]; |
wire [a_lo_size-1:0] fifo_radr_bin[0:nr_of_queues-1]; |
wire [a_lo_size-1:0] fifo_radr_gray[0:nr_of_queues-1]; |
reg [a_lo_size-1:0] wadr; |
reg [a_lo_size-1:0] radr; |
reg [data_width-1:0] wdata; |
wire [data_width-1:0] wdataa[0:nr_of_queues-1]; |
reg read_adr_reg; |
reg [0:nr_of_queues-1] read_enable_reg; |
genvar i; |
integer j,k,l; |
function [a_lo_size-1:0] onehot2bin; |
input [0:nr_of_queues-1] a; |
integer i; |
begin |
onehot2bin = {a_lo_size{1'b0}}; |
for (i=1;i<nr_of_queues;i=i+1) begin |
if (a[i]) |
onehot2bin = i; |
end |
end |
endfunction |
always @ (posedge clk2 or posedge rst2) |
if (rst2) |
read_adr_reg <= 1'b0; |
else |
read_adr_reg <= read_adr; |
always @ (posedge clk2 or posedge rst2) |
if (rst2) |
read_enable_reg <= {nr_of_queues{1'b0}}; |
else |
if (read_adr) |
read_enable_reg <= read_enable; |
generate |
for (i=0;i<nr_of_queues;i=i+1) begin : fifo_adr |
gray_counter wadrcnt ( |
.cke(write & write_enable[i]), |
.q(fifo_wadr_gray[i]), |
.q_bin(fifo_wadr_bin[i]), |
.rst(rst1), |
.clk(clk1)); |
gray_counter radrcnt ( |
.cke((read_adr_reg | read_data) & read_enable_reg[i]), |
.q(fifo_radr_gray[i]), |
.q_bin(fifo_radr_bin[i]), |
.rst(rst2), |
.clk(clk2)); |
versatile_fifo_async_cmp |
#(.ADDR_WIDTH(a_lo_size)) |
egresscmp ( |
.wptr(fifo_wadr_gray[i]), |
.rptr(fifo_radr_gray[i]), |
.fifo_empty(fifo_empty[i]), |
.fifo_full(fifo_full[i]), |
.wclk(clk1), |
.rclk(clk2), |
.rst(rst1)); |
end |
endgenerate |
always @* |
begin |
wadr = {a_lo_size{1'b0}}; |
for (j=0;j<nr_of_queues;j=j+1) begin |
wadr = (fifo_wadr_bin[j] & {a_lo_size{write_enable[j]}}) | wadr; |
end |
end |
always @* |
begin |
radr = {a_lo_size{1'b0}}; |
for (k=0;k<nr_of_queues;k=k+1) begin |
radr = (fifo_radr_bin[k] & {a_lo_size{read_enable_reg[k]}}) | radr; |
end |
end |
generate |
for (i=0;i<nr_of_queues;i=i+1) begin : vector2array |
assign wdataa[i] = d[(nr_of_queues-i)*data_width-1:(nr_of_queues-1-i)*data_width]; |
end |
endgenerate |
always @* |
begin |
wdata = {data_width{1'b0}}; |
for (l=0;l<nr_of_queues;l=l+1) begin |
wdata = (wdataa[l] & {data_width{write_enable[l]}}) | wdata; |
end |
end |
vfifo_dual_port_ram_dc_sw # ( .DATA_WIDTH(data_width), .ADDR_WIDTH(a_hi_size+a_lo_size)) |
dpram ( |
.d_a(wdata), |
.adr_a({onehot2bin(write_enable),wadr}), |
.we_a(write), |
.clk_a(clk1), |
.q_b(q), |
.adr_b({onehot2bin(read_enable_reg),radr}), |
.clk_b(clk2) ); |
endmodule |
module vfifo_dual_port_ram_dc_sw |
( |
d_a, |
adr_a, |
we_a, |
clk_a, |
q_b, |
adr_b, |
clk_b |
); |
parameter DATA_WIDTH = 32; |
parameter ADDR_WIDTH = 8; |
input [(DATA_WIDTH-1):0] d_a; |
input [(ADDR_WIDTH-1):0] adr_a; |
input [(ADDR_WIDTH-1):0] adr_b; |
input we_a; |
output [(DATA_WIDTH-1):0] q_b; |
input clk_a, clk_b; |
reg [(ADDR_WIDTH-1):0] adr_b_reg; |
reg [DATA_WIDTH-1:0] ram [(1<<ADDR_WIDTH)-1:0] ; |
always @ (posedge clk_a) |
if (we_a) |
ram[adr_a] <= d_a; |
always @ (posedge clk_b) |
adr_b_reg <= adr_b; |
assign q_b = ram[adr_b_reg]; |
endmodule |
module dff_sr ( aclr, aset, clock, data, q); |
input aclr; |
input aset; |
input clock; |
input data; |
output reg q; |
always @ (posedge clock or posedge aclr or posedge aset) |
if (aclr) |
q <= 1'b0; |
else if (aset) |
q <= 1'b1; |
else |
case ({wptr[N:N-1],rptr[N:N-1]}) |
{Q2,Q1} : direction_clr <= 1'b1; |
{Q3,Q2} : direction_clr <= 1'b1; |
{Q4,Q3} : direction_clr <= 1'b1; |
{Q1,Q4} : direction_clr <= 1'b1; |
default : direction_clr <= 1'b0; |
endcase |
always @ (posedge direction_set or posedge direction_clr) |
if (direction_clr) |
direction <= going_empty; |
else |
direction <= going_full; |
assign async_empty = (wptr == rptr) && (direction==going_empty); |
assign async_full = (wptr == rptr) && (direction==going_full); |
always @ (posedge wclk or posedge rst or posedge async_full) |
if (rst) |
{fifo_full, fifo_full2} <= 2'b00; |
else if (async_full) |
{fifo_full, fifo_full2} <= 2'b11; |
else |
{fifo_full, fifo_full2} <= {fifo_full2, async_full}; |
always @ (posedge rclk or posedge async_empty) |
if (async_empty) |
{fifo_empty, fifo_empty2} <= 2'b11; |
else |
{fifo_empty,fifo_empty2} <= {fifo_empty2,async_empty}; |
endmodule |
q <= data; |
endmodule |
module ref_counter ( zq, rst, clk); |
parameter length = 10; |
output reg zq; |
224,7 → 1958,7
input clk; |
parameter clear_value = 0; |
parameter set_value = 0; |
parameter wrap_value = 592; |
parameter wrap_value = 417; |
reg [length:1] qi; |
reg lfsr_fb; |
wire [length:1] q_next; |
272,7 → 2006,7
lfsr_fb = lfsr_fb ~^ qi[i]; |
end |
end |
assign q_next = {qi[length-1:1],lfsr_fb}; |
assign q_next = (qi == wrap_value) ? {length{1'b0}} :{qi[length-1:1],lfsr_fb}; |
always @ (posedge clk or posedge rst) |
if (rst) |
qi <= {length{1'b0}}; |
287,10 → 2021,8
`timescale 1ns/1ns |
module fsm_sdr_16 ( |
adr_i, we_i, bte_i, |
fifo_sel_i, fifo_sel_domain_i, |
fifo_sel_reg, fifo_sel_domain_reg, |
fifo_empty, fifo_rd, count0, |
refresh_req, cmd_aref, cmd_read, |
fifo_empty, fifo_rd_adr, fifo_rd_data, count0, |
refresh_req, cmd_aref, cmd_read, state_idle, |
ba, a, cmd, dq_oe, |
sdram_clk, sdram_rst |
); |
300,16 → 2032,13
input [ba_size+row_size+col_size-1:0] adr_i; |
input we_i; |
input [1:0] bte_i; |
input [0:15] fifo_sel_i; |
input [1:0] fifo_sel_domain_i; |
output [0:15] fifo_sel_reg; |
output [1:0] fifo_sel_domain_reg; |
input fifo_empty; |
output fifo_rd; |
output fifo_rd_adr, fifo_rd_data; |
output count0; |
input refresh_req; |
output reg cmd_aref; |
output reg cmd_read; |
output state_idle; |
output reg [1:0] ba; |
output reg [12:0] a; |
output reg [2:0] cmd; |
327,8 → 2056,10
reg [col_size-1:0] col_reg; |
reg we_reg; |
reg [1:0] bte_reg; |
reg [row_size-1:0] open_row[3:0]; |
reg [3:0] open_ba; |
reg [row_size-1:0] open_row[0:3]; |
reg [0:3] open_ba; |
wire current_bank_closed, current_row_open; |
reg current_bank_closed_reg, current_row_open_reg; |
parameter [1:0] linear = 2'b00, |
beat4 = 2'b01, |
beat8 = 2'b10, |
346,10 → 2077,10
adr = 3'b011, |
pch = 3'b100, |
act = 3'b101, |
nop = 3'b110, |
w4d = 3'b110, |
rw = 3'b111; |
reg [2:0] state, next; |
function [3:0] a10_fix; |
function [12:0] a10_fix; |
input [col_size-1:0] a; |
integer i; |
begin |
370,13 → 2101,13
end |
endfunction |
assign {bank,row,col} = adr_i; |
always @ (posedge sdram_clk or sdram_rst) |
always @ (posedge sdram_clk or posedge sdram_rst) |
if (sdram_rst) |
{ba_reg,row_reg,col_reg,we_reg,bte_reg} <= {2'b00,{row_size{1'b0}},{col_size{1'b0}}}; |
{ba_reg,row_reg,col_reg,we_reg,bte_reg} <= {2'b00, {row_size{1'b0}}, {col_size{1'b0}}, 1'b0, 2'b00 }; |
else |
if (state==adr & !counter[0]) |
if (state==adr & counter[1:0]==2'b10) |
{ba_reg,row_reg,col_reg,we_reg,bte_reg} <= {bank,row,col,we_i,bte_i}; |
always @ (posedge sdram_clk or sdram_rst) |
always @ (posedge sdram_clk or posedge sdram_rst) |
if (sdram_rst) |
state <= init; |
else |
388,20 → 2119,24
init: if (counter==5'd31) next = idle; |
else next = init; |
idle: if (refresh_req) next = rfr; |
else if (|fifo_sel_i) next = adr; |
else if (!fifo_empty) next = adr; |
else next = idle; |
rfr: if (counter==5'd5) next = idle; |
else next = rfr; |
adr: if (open_ba[ba_reg] & (open_row[ba_reg]==row_reg) & counter[0]) next = rw; |
else if (!open_ba[ba_reg]& counter[0]) next = act; |
else if (counter[0]) next = pch; |
adr: if (current_row_open_reg & (counter[1:0]==2'b11) & we_reg) next = w4d; |
else if (current_row_open_reg & (counter[1:0]==2'b11)) next = rw; |
else if (current_bank_closed_reg & (counter[1:0]==2'b11)) next = act; |
else if ((counter[1:0]==2'b11)) next = pch; |
else next = adr; |
pch: if (counter[0]) next = act; |
else next = pch; |
act: if (counter==5'd2) next = rw; |
else next = act; |
rw: case ({bte_reg,counter}) |
{linear,5'd1},{beat4,5'd7},{beat8,5'd15},{beat16,5'd31}: next = idle; |
act: if (counter[1:0]==2'd2 & !fifo_empty) next = rw; |
else if (counter[1:0]==2'd2 & fifo_empty) next = w4d; |
else next = act; |
w4d: if (!fifo_empty) next = rw; |
else next = w4d; |
rw: casex ({bte_reg,counter}) |
{linear,5'bxxxx1},{beat4,5'bxx111},{beat8,5'bx1111},{beat16,5'b11111}: next = idle; |
default: next = rw; |
endcase |
endcase |
414,18 → 2149,10
if (state!=next) |
counter <= 5'd0; |
else |
if (~(state==rw & fifo_empty & ~counter[0] & we_reg)) |
if (~(state==rw & next==rw & fifo_empty & counter[0] & we_reg)) |
counter <= counter + 5'd1; |
end |
always @ (posedge sdram_clk or posedge sdram_rst) |
begin |
if (sdram_rst) |
{fifo_sel_reg_int,fifo_sel_domain_reg_int} <= {16'h0,2'b00}; |
else |
if (state==idle) |
{fifo_sel_reg_int,fifo_sel_domain_reg_int} <= {fifo_sel_i,fifo_sel_domain_i}; |
end |
assign {fifo_sel_reg,fifo_sel_domain_reg} = (state==idle) ? {fifo_sel_i,fifo_sel_domain_i} : {fifo_sel_reg_int,fifo_sel_domain_reg_int}; |
assign count0 = counter[0]; |
parameter [0:0] init_wb = 1'b0; |
parameter [2:0] init_cl = 3'b010; |
parameter [0:0] init_bt = 1'b0; |
433,61 → 2160,66
assign col_reg_a10_fix = a10_fix(col_reg); |
always @ (posedge sdram_clk or posedge sdram_rst) |
begin |
if (sdram_rst) |
{ba,a,cmd,cmd_aref,cmd_read} = {2'b00,13'd0,cmd_nop,1'b0,1'b0}; |
else begin |
{ba,a,cmd,cmd_aref,cmd_read} = {2'b00,13'd0,cmd_nop,1'b0,1'b0}; |
if (sdram_rst) begin |
{ba,a,cmd} = {2'b00,13'd0,cmd_nop}; |
cmd_aref = 1'b0; |
cmd_read = 1'b0; |
dq_oe = 1'b0; |
{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}; |
cmd_aref = 1'b0; |
cmd_read = 1'b0; |
dq_oe = 1'b0; |
casex ({state,counter}) |
{init,5'd3}, {rfr,5'd0}: |
{init,5'd3}, {rfr,5'd0}: begin |
{ba,a,cmd} = {2'b00, 13'b0010000000000, cmd_pch}; |
open_ba[ba_reg] <= 1'b0; |
end |
{init,5'd7}, {init,5'd19}, {rfr,5'd2}: |
{ba,a,cmd,cmd_aref} = {2'b00, 13'd0, cmd_rfr,1'b1}; |
{init,5'd31}: |
{ba,a,cmd} = {2'b00,3'b000,init_wb,2'b00,init_cl,init_bt,init_bl, cmd_lmr}; |
{pch,5'bxxxx0}: |
{pch,5'bxxxx0}: begin |
{ba,a,cmd} = {ba_reg,13'd0,cmd_pch}; |
{act,5'd0}: |
open_ba <= 4'b0000; |
end |
{act,5'd0}: begin |
{ba,a,cmd} = {ba_reg,(13'd0 | row_reg),cmd_act}; |
{open_ba[ba_reg],open_row[ba_reg]} <= {1'b1,row_reg}; |
end |
{rw,5'bxxxxx}: |
begin |
casex ({we_reg,counter[0],fifo_empty}) |
{1'b0,1'b0,1'bx}: {cmd,cmd_read} = {cmd_rd,1'b1}; |
{1'b1,1'b0,1'b0}: cmd = cmd_wr; |
endcase |
if (we_reg & !counter[0]) |
cmd = cmd_wr; |
else if (!counter[0]) |
{cmd,cmd_read} = {cmd_rd,1'b1}; |
else |
cmd = cmd_nop; |
if (we_reg) |
dq_oe = 1'b1; |
case (bte_reg) |
linear: {ba,a} = {ba_reg,col_reg_a10_fix}; |
beat4: {ba,a} = {ba_reg,col_reg_a10_fix[12:2],col_reg_a10_fix[2:0] + counter[2:0]}; |
beat8: {ba,a} = {ba_reg,col_reg_a10_fix[12:3],col_reg_a10_fix[3:0] + counter[3:0]}; |
beat16: {ba,a} = {ba_reg,col_reg_a10_fix[12:4],col_reg_a10_fix[4:0] + counter[4:0]}; |
beat4: {ba,a} = {ba_reg,col_reg_a10_fix[12:3],col_reg_a10_fix[2:0] + counter[2:0]}; |
beat8: {ba,a} = {ba_reg,col_reg_a10_fix[12:4],col_reg_a10_fix[3:0] + counter[3:0]}; |
beat16: {ba,a} = {ba_reg,col_reg_a10_fix[12:5],col_reg_a10_fix[4:0] + counter[4:0]}; |
endcase |
end |
endcase |
end |
end |
assign fifo_rd = ((state==idle) & (next==adr)) ? 1'b1 : |
((state==rw) & we_reg & !counter[0] & !fifo_empty) ? 1'b1 : |
1'b0; |
assign count0 = counter[0]; |
assign fifo_rd_adr = ((state==adr) & (counter[1:0]==2'b00)) ? 1'b1 : 1'b0; |
assign fifo_rd_data = (state==w4d & !fifo_empty) ? 1'b1 : |
((state==rw & next==rw) & we_reg & !counter[0] & !fifo_empty) ? 1'b1 : |
1'b0; |
assign state_idle = (state==idle); |
assign current_bank_closed = !(open_ba[bank]); |
assign current_row_open = open_ba[bank] & (open_row[bank]==row); |
always @ (posedge sdram_clk or posedge sdram_rst) |
if (sdram_rst) |
dq_oe <= 1'b0; |
{current_bank_closed_reg, current_row_open_reg} <= {1'b1, 1'b0}; |
else |
dq_oe <= ((state==rw & we_reg & ~counter[0] & !fifo_empty) | (state==rw & we_reg & counter[0])); |
always @ (posedge sdram_clk or posedge sdram_rst) |
if (sdram_rst) |
{open_ba,open_row[0],open_row[1],open_row[2],open_row[3]} <= {4'b0000,{row_size*4{1'b0}}}; |
else |
casex ({ba,a[10],cmd}) |
{2'bxx,1'b1,cmd_pch}: open_ba <= 4'b0000; |
{2'b00,1'b0,cmd_pch}: open_ba[0] <= 1'b0; |
{2'b01,1'b0,cmd_pch}: open_ba[1] <= 1'b0; |
{2'b10,1'b0,cmd_pch}: open_ba[2] <= 1'b0; |
{2'b11,1'b0,cmd_pch}: open_ba[3] <= 1'b0; |
{2'b00,1'bx,cmd_act}: {open_ba[0],open_row[0]} <= {1'b1,row_reg}; |
{2'b01,1'bx,cmd_act}: {open_ba[1],open_row[1]} <= {1'b1,row_reg}; |
{2'b10,1'bx,cmd_act}: {open_ba[2],open_row[2]} <= {1'b1,row_reg}; |
{2'b11,1'bx,cmd_act}: {open_ba[3],open_row[3]} <= {1'b1,row_reg}; |
endcase |
{current_bank_closed_reg, current_row_open_reg} <= {current_bank_closed, current_row_open}; |
endmodule |
`timescale 1ns/1ns |
module versatile_mem_ctrl_wb ( |
494,8 → 2226,8
wb_adr_i_v, wb_dat_i_v, wb_dat_o_v, |
wb_stb_i, wb_cyc_i, wb_ack_o, |
wb_clk, wb_rst, |
sdram_dat_o, sdram_fifo_empty, sdram_fifo_rd, |
sdram_dat_i, sdram_fifo_wr, |
sdram_dat_o, sdram_fifo_empty, sdram_fifo_rd_adr, sdram_fifo_rd_data, sdram_fifo_re, |
sdram_dat_i, sdram_fifo_wr, sdram_fifo_we, |
sdram_clk, sdram_rst |
); |
parameter nr_of_wb_ports = 3; |
509,12 → 2241,14
input wb_rst; |
output [35:0] sdram_dat_o; |
output [0:nr_of_wb_ports-1] sdram_fifo_empty; |
input [0:nr_of_wb_ports-1] sdram_fifo_rd; |
input sdram_fifo_rd_adr, sdram_fifo_rd_data; |
input [0:nr_of_wb_ports-1] sdram_fifo_re; |
input [31:0] sdram_dat_i; |
input [0:nr_of_wb_ports-1] sdram_fifo_wr; |
input sdram_fifo_wr; |
input [0:nr_of_wb_ports-1] sdram_fifo_we; |
input sdram_clk; |
input sdram_rst; |
parameter linear_burst = 2'b00; |
parameter linear = 2'b00; |
parameter wrap4 = 2'b01; |
parameter wrap8 = 2'b10; |
parameter wrap16 = 2'b11; |
526,37 → 2260,18
reg [1:0] wb_state[0:nr_of_wb_ports-1]; |
wire [35:0] wb_adr_i[0:nr_of_wb_ports-1]; |
wire [35:0] wb_dat_i[0:nr_of_wb_ports-1]; |
wire [35:0] egress_fifo_di[0:nr_of_wb_ports-1]; |
wire [36*nr_of_wb_ports-1:0] egress_fifo_di; |
wire [31:0] wb_dat_o; |
wire [0:nr_of_wb_ports-1] wb_wr_ack, wb_rd_ack, wr_adr; |
reg [0:nr_of_wb_ports-1] wb_rd_ack_dly; |
wire [3:0] egress_fifo_wadr_bin[0:nr_of_wb_ports-1]; |
wire [3:0] egress_fifo_wadr_gray[0:nr_of_wb_ports-1]; |
wire [3:0] egress_fifo_radr_bin[0:nr_of_wb_ports-1]; |
wire [3:0] egress_fifo_radr_gray[0:nr_of_wb_ports-1]; |
wire [3:0] egress_fifo_full; |
wire [3:0] ingress_fifo_wadr_bin[0:nr_of_wb_ports-1]; |
wire [3:0] ingress_fifo_wadr_gray[0:nr_of_wb_ports-1]; |
wire [3:0] ingress_fifo_radr_bin[0:nr_of_wb_ports-1]; |
wire [3:0] ingress_fifo_radr_gray[0:nr_of_wb_ports-1]; |
wire [3:0] ingress_fifo_empty; |
function [3:0] onehot2bin; |
input [0:nr_of_wb_ports-1] a; |
integer i; |
begin |
onehot2bin = 0; |
for (i=1;i<nr_of_wb_ports;i=i+1) begin |
if (a[i]) |
onehot2bin = i; |
end |
end |
endfunction |
wire [0:nr_of_wb_ports-1] egress_fifo_full; |
wire [0:nr_of_wb_ports-1] ingress_fifo_empty; |
genvar i; |
generate |
for (i=0;i<nr_of_wb_ports;i=i+1) begin : vector2array |
assign wb_adr_i[i] = wb_adr_i_v[(nr_of_wb_ports-i)*36-1:(nr_of_wb_ports-1-i)*36]; |
assign wb_dat_i[i] = wb_dat_i_v[(nr_of_wb_ports-i)*36-1:(nr_of_wb_ports-1-i)*36]; |
assign egress_fifo_di[i] = (wb_state[i]==idle) ? wb_adr_i[i] : wb_dat_i[i]; |
assign egress_fifo_di[(nr_of_wb_ports-i)*36-1:(nr_of_wb_ports-1-i)*36] = (wb_state[i]==idle) ? wb_adr_i[i] : wb_dat_i[i]; |
end |
endgenerate |
generate |
594,81 → 2309,27
else if (wb_wr_ack[i]) |
wb_state[i] <= rd; |
rd: |
if ((wb_adr_i[i][2:0]==classic | wb_adr_i[i][2:0]==endofburst) & wb_ack_o[i]) |
if ((wb_adr_i[i][2:0]==classic | wb_adr_i[i][2:0]==endofburst | wb_adr_i[i][4:3]==linear) & wb_ack_o[i]) |
wb_state[i] <= idle; |
wr: |
if ((wb_adr_i[i][2:0]==classic | wb_adr_i[i][2:0]==endofburst) & wb_ack_o[i]) |
if ((wb_adr_i[i][2:0]==classic | wb_adr_i[i][2:0]==endofburst | wb_adr_i[i][4:3]==linear) & wb_ack_o[i]) |
wb_state[i] <= idle; |
default: ; |
endcase |
end |
endgenerate |
generate |
for (i=0;i<nr_of_wb_ports;i=i+1) begin : fifo_adr |
fifo_adr_counter egress_wadrcnt ( |
.cke(wb_wr_ack[i]), |
.q(egress_fifo_wadr_gray[i]), |
.q_bin(egress_fifo_wadr_bin[i]), |
.rst(wb_rst), |
.clk(wb_clk)); |
fifo_adr_counter egress_radrcnt ( |
.cke(sdram_fifo_rd[i]), |
.q(egress_fifo_radr_gray[i]), |
.q_bin(egress_fifo_radr_bin[i]), |
.rst(sdram_rst), |
.clk(sdram_clk)); |
versatile_fifo_async_cmp |
#(.ADDR_WIDTH(4)) |
egresscmp ( |
.wptr(egress_fifo_wadr_gray[i]), |
.rptr(egress_fifo_radr_gray[i]), |
.fifo_empty(sdram_fifo_empty[i]), |
.fifo_full(egress_fifo_full[i]), |
.wclk(wb_clk), |
.rclk(sdram_clk), |
.rst(wb_rst)); |
fifo_adr_counter ingress_wadrcnt ( |
.cke(sdram_fifo_wr[i]), |
.q(ingress_fifo_wadr_gray[i]), |
.q_bin(ingress_fifo_wadr_bin[i]), |
.rst(sdram_rst), |
.clk(sdram_clk)); |
fifo_adr_counter ingress_radrcnt ( |
.cke(wb_rd_ack[i]), |
.q(ingress_fifo_radr_gray[i]), |
.q_bin(ingress_fifo_radr_bin[i]), |
.rst(wb_rst), |
.clk(wb_clk)); |
versatile_fifo_async_cmp |
#(.ADDR_WIDTH(4)) |
ingresscmp ( |
.wptr(ingress_fifo_wadr_gray[i]), |
.rptr(ingress_fifo_radr_gray[i]), |
.fifo_empty(ingress_fifo_empty[i]), |
.fifo_full(), |
.wclk(sdram_clk), |
.rclk(wb_clk), |
.rst(wb_rst)); |
end |
endgenerate |
vfifo_dual_port_ram_dc_sw # ( .DATA_WIDTH(36), .ADDR_WIDTH(8)) |
egress_dpram ( |
.d_a(egress_fifo_di[onehot2bin(wb_wr_ack)]), |
.adr_a({onehot2bin(wb_wr_ack),egress_fifo_wadr_bin[onehot2bin(wb_wr_ack)]}), |
.we_a(|(wb_wr_ack)), |
.clk_a(wb_clk), |
.q_b(sdram_dat_o), |
.adr_b({onehot2bin(sdram_fifo_rd),egress_fifo_radr_bin[onehot2bin(sdram_fifo_rd)]}), |
.clk_b(sdram_clk) ); |
vfifo_dual_port_ram_dc_sw # ( .DATA_WIDTH(32), .ADDR_WIDTH(8)) |
ingress_dpram ( |
.d_a(sdram_dat_i), |
.adr_a({onehot2bin(sdram_fifo_wr),ingress_fifo_wadr_bin[onehot2bin(sdram_fifo_wr)]}), |
.we_a(|(sdram_fifo_wr)), |
.clk_a(sdram_clk), |
.q_b(wb_dat_o), |
.adr_b({onehot2bin(wb_rd_ack),ingress_fifo_radr_bin[onehot2bin(wb_rd_ack)]}), |
.clk_b(wb_clk) ); |
egress_fifo # (.a_hi_size(4),.a_lo_size(4),.nr_of_queues(nr_of_wb_ports),.data_width(36)) |
egress_FIFO( |
.d(egress_fifo_di), .fifo_full(egress_fifo_full), .write(|(wb_wr_ack)), .write_enable(wb_wr_ack), |
.q(sdram_dat_o), .fifo_empty(sdram_fifo_empty), .read_adr(sdram_fifo_rd_adr), .read_data(sdram_fifo_rd_data), .read_enable(sdram_fifo_re), |
.clk1(wb_clk), .rst1(wb_rst), .clk2(sdram_clk), .rst2(sdram_rst) |
); |
async_fifo_mq # (.a_hi_size(4),.a_lo_size(4),.nr_of_queues(nr_of_wb_ports),.data_width(32)) |
ingress_FIFO( |
.d(sdram_dat_i), .fifo_full(), .write(sdram_fifo_wr), .write_enable(sdram_fifo_we), |
.q(wb_dat_o), .fifo_empty(ingress_fifo_empty), .read(|(wb_rd_ack)), .read_enable(wb_rd_ack), |
.clk1(sdram_clk), .rst1(sdram_rst), .clk2(wb_clk), .rst2(wb_rst) |
); |
assign wb_dat_o_v = {nr_of_wb_ports{wb_dat_o}}; |
endmodule |
`timescale 1ns/1ns |
691,7 → 2352,10
parameter nr_of_wb_ports_clk1 = 0; |
parameter nr_of_wb_ports_clk2 = 0; |
parameter nr_of_wb_ports_clk3 = 0; |
parameter tot_nr_of_wb_ports = nr_of_wb_ports_clk0 + nr_of_wb_ports_clk1 + nr_of_wb_ports_clk2 + nr_of_wb_ports_clk3; |
parameter ba_size = 2; |
parameter row_size = 13; |
parameter col_size = 9; |
parameter [2:0] cl = 3'b010; |
input [36*nr_of_wb_ports_clk0-1:0] wb_adr_i_0; |
input [36*nr_of_wb_ports_clk0-1:0] wb_dat_i_0; |
output [32*nr_of_wb_ports_clk0-1:0] wb_dat_o_0; |
710,12 → 2374,12
input [0:nr_of_wb_ports_clk3-1] wb_stb_i_3, wb_cyc_i_3, wb_ack_o_3; |
input [0:nr_of_wb_clk_domains-1] wb_clk; |
input [0:nr_of_wb_clk_domains-1] wb_rst; |
output [1:0] ba_pad_o; |
output [1:0] ba_pad_o; |
output [12:0] a_pad_o; |
output cs_n_pad_o; |
output ras_pad_o; |
output cas_pad_o; |
output we_pad_o; |
output cs_n_pad_o; |
output ras_pad_o; |
output cas_pad_o; |
output we_pad_o; |
output reg [15:0] dq_o; |
output reg [1:0] dqm_pad_o; |
input [15:0] dq_i; |
728,9 → 2392,11
wire [35:0] fifo_dat_o[0:3]; |
wire [31:0] fifo_dat_i; |
wire [0:15] fifo_we[0:3]; |
wire fifo_rd, fifo_wr, count0; |
wire [0:15] fifo_sel_i, fifo_sel_reg, fifo_sel_dly; |
wire [1:0] fifo_sel_domain_i, fifo_sel_domain_reg, fifo_sel_domain_dly; |
wire fifo_rd_adr, fifo_rd_data, fifo_wr, idle, count0; |
wire [0:15] fifo_sel_i, fifo_sel_dly; |
reg [0:15] fifo_sel_reg; |
wire [1:0] fifo_sel_domain_i, fifo_sel_domain_dly; |
reg [1:0] fifo_sel_domain_reg; |
reg refresh_req; |
wire [35:0] tx_fifo_dat_o; |
generate |
748,9 → 2414,12
.wb_rst(wb_rst[0]), |
.sdram_dat_o(fifo_dat_o[0]), |
.sdram_fifo_empty(fifo_empty[0][0:nr_of_wb_ports_clk0-1]), |
.sdram_fifo_rd(fifo_re[0][0:nr_of_wb_ports_clk0-1] & {nr_of_wb_ports_clk0{fifo_rd}}), |
.sdram_fifo_rd_adr(fifo_rd_adr), |
.sdram_fifo_rd_data(fifo_rd_data), |
.sdram_fifo_re(fifo_re[0][0:nr_of_wb_ports_clk0-1]), |
.sdram_dat_i(fifo_dat_i), |
.sdram_fifo_wr(fifo_we[0][0:nr_of_wb_ports_clk0-1] & {nr_of_wb_ports_clk0{fifo_wr}}), |
.sdram_fifo_wr(fifo_wr), |
.sdram_fifo_we(fifo_we[0][0:nr_of_wb_ports_clk0-1]), |
.sdram_clk(sdram_clk), |
.sdram_rst(sdram_rst) ); |
end |
773,9 → 2442,12
.wb_rst(wb_rst[1]), |
.sdram_dat_o(fifo_dat_o[1]), |
.sdram_fifo_empty(fifo_empty[1][0:nr_of_wb_ports_clk1-1]), |
.sdram_fifo_rd(fifo_re[1][0:nr_of_wb_ports_clk1-1] & {nr_of_wb_ports_clk1{fifo_rd}}), |
.sdram_fifo_rd_adr(fifo_rd_adr), |
.sdram_fifo_rd_data(fifo_rd_data), |
.sdram_fifo_re(fifo_re[1][0:nr_of_wb_ports_clk1-1]), |
.sdram_dat_i(fifo_dat_i), |
.sdram_fifo_wr(fifo_we[1][0:nr_of_wb_ports_clk1-1] & {nr_of_wb_ports_clk1{fifo_wr}}), |
.sdram_fifo_wr(fifo_wr), |
.sdram_fifo_we(fifo_we[1][0:nr_of_wb_ports_clk1-1]), |
.sdram_clk(sdram_clk), |
.sdram_rst(sdram_rst) ); |
if (nr_of_wb_ports_clk1 < 16) begin |
799,11 → 2471,14
.wb_ack_o(wb_ack_o_2), |
.wb_clk(wb_clk[2]), |
.wb_rst(wb_rst[2]), |
.sdram_dat_o(), |
.sdram_fifo_empty(), |
.sdram_fifo_rd(), |
.sdram_dat_i(), |
.sdram_fifo_wr(), |
.sdram_dat_o(fifo_dat_o[2]), |
.sdram_fifo_empty(fifo_empty[2][0:nr_of_wb_ports_clk2-1]), |
.sdram_fifo_rd_adr(fifo_rd_adr), |
.sdram_fifo_rd_data(fifo_rd_data), |
.sdram_fifo_re(fifo_re[2][0:nr_of_wb_ports_clk2-1]), |
.sdram_dat_i(fifo_dat_i), |
.sdram_fifo_wr(fifo_wr), |
.sdram_fifo_we(fifo_we[2][0:nr_of_wb_ports_clk2-1]), |
.sdram_clk(sdram_clk), |
.sdram_rst(sdram_rst) ); |
if (nr_of_wb_ports_clk2 < 16) begin |
827,11 → 2502,14
.wb_ack_o(wb_ack_o_3), |
.wb_clk(wb_clk[3]), |
.wb_rst(wb_rst[3]), |
.sdram_dat_o(), |
.sdram_fifo_empty(), |
.sdram_fifo_rd(), |
.sdram_dat_i(), |
.sdram_fifo_wr(), |
.sdram_dat_o(fifo_dat_o[3]), |
.sdram_fifo_empty(fifo_empty[3][0:nr_of_wb_ports_clk3-1]), |
.sdram_fifo_rd_adr(fifo_rd_adr), |
.sdram_fifo_rd_data(fifo_rd_data), |
.sdram_fifo_re(fifo_re[3][0:nr_of_wb_ports_clk3-1]), |
.sdram_dat_i(fifo_dat_i), |
.sdram_fifo_wr(fifo_wr), |
.sdram_fifo_we(fifo_we[3][0:nr_of_wb_ports_clk3-1]), |
.sdram_clk(sdram_clk), |
.sdram_rst(sdram_rst) ); |
if (nr_of_wb_ports_clk3 < 16) begin |
846,17 → 2524,26
.fifo_empty_0(fifo_empty[0]), .fifo_empty_1(fifo_empty[1]), .fifo_empty_2(fifo_empty[2]), .fifo_empty_3(fifo_empty[3]), |
.fifo_sel(fifo_sel_i), .fifo_sel_domain(fifo_sel_domain_i) |
); |
always @ (posedge sdram_clk or posedge sdram_rst) |
begin |
if (sdram_rst) |
{fifo_sel_reg,fifo_sel_domain_reg} <= {16'h0,2'b00}; |
else |
if (idle) |
{fifo_sel_reg,fifo_sel_domain_reg} <= {fifo_sel_i,fifo_sel_domain_i}; |
end |
decode decode0 ( |
.fifo_sel(fifo_sel_reg), .fifo_sel_domain(fifo_sel_domain_reg), |
.fifo_we_0(fifo_re[0]), .fifo_we_1(fifo_re[1]), .fifo_we_2(fifo_re[2]), .fifo_we_3(fifo_re[3]) |
); |
assign current_fifo_empty = (|(fifo_empty[0] & fifo_re[0])) | (|(fifo_empty[1] & fifo_re[1])) | (|(fifo_empty[2] & fifo_re[2])) | (|(fifo_empty[3] & fifo_re[3])); |
assign current_fifo_empty = (idle) ? (!(|fifo_sel_i)) : (|(fifo_empty[0] & fifo_re[0])) | (|(fifo_empty[1] & fifo_re[1])) | (|(fifo_empty[2] & fifo_re[2])) | (|(fifo_empty[3] & fifo_re[3])); |
decode decode1 ( |
.fifo_sel(fifo_sel_dly), .fifo_sel_domain(fifo_sel_domain_dly), |
.fifo_we_0(fifo_we[0]), .fifo_we_1(fifo_we[1]), .fifo_we_2(fifo_we[2]), .fifo_we_3(fifo_we[3]) |
); |
wire ref_cnt_zero; |
reg [15:0] dq_i_reg, dq_i_tmp_reg; |
reg [15:0] dq_i_reg, dq_i_tmp_reg; |
reg [17:0] dq_o_tmp_reg; |
wire cmd_aref, cmd_read; |
ref_counter ref_counter0( .zq(ref_cnt_zero), .rst(sdram_rst), .clk(sdram_clk)); |
always @ (posedge sdram_clk or posedge sdram_rst) |
867,15 → 2554,13
refresh_req <= 1'b1; |
else if (cmd_aref) |
refresh_req <= 1'b0; |
fsm_sdr_16 # ( .ba_size(2), .row_size(13), .col_size(9)) |
fsm_sdr_16 # ( .ba_size(ba_size), .row_size(row_size), .col_size(col_size), .init_cl(cl)) |
fsm_sdr_16( |
.adr_i({fifo_dat_o[fifo_sel_domain_reg][2+13+9+6-2:6],1'b0}), |
.adr_i({fifo_dat_o[fifo_sel_domain_reg][ba_size+row_size+col_size+6-2:6],1'b0}), |
.we_i(fifo_dat_o[fifo_sel_domain_reg][5]), |
.bte_i(fifo_dat_o[fifo_sel_domain_reg][4:3]), |
.fifo_sel_i(fifo_sel_i), .fifo_sel_domain_i(fifo_sel_domain_i), |
.fifo_sel_reg(fifo_sel_reg), .fifo_sel_domain_reg(fifo_sel_domain_reg), |
.fifo_empty(current_fifo_empty), .fifo_rd(fifo_rd), |
.count0(count0), |
.fifo_empty(current_fifo_empty), .fifo_rd_adr(fifo_rd_adr), .fifo_rd_data(fifo_rd_data), |
.state_idle(idle), .count0(count0), |
.refresh_req(refresh_req), |
.cmd_aref(cmd_aref), .cmd_read(cmd_read), |
.ba(ba_pad_o), .a(a_pad_o), .cmd({ras_pad_o, cas_pad_o, we_pad_o}), .dq_oe(dq_oe), |
886,7 → 2571,7
genvar i; |
generate |
for (i=0; i < 16; i=i+1) begin : dly |
defparam delay0.depth=2+2; |
defparam delay0.depth=cl+2; |
defparam delay0.width=1; |
delay delay0 ( |
.d(fifo_sel_reg[i]), |
895,7 → 2580,7
.rst(sdram_rst) |
); |
end |
defparam delay1.depth=2+2; |
defparam delay1.depth=cl+2; |
defparam delay1.width=2; |
delay delay1 ( |
.d(fifo_sel_domain_reg), |
903,7 → 2588,7
.clk(sdram_clk), |
.rst(sdram_rst) |
); |
defparam delay2.depth=2+2; |
defparam delay2.depth=cl+2; |
defparam delay2.width=1; |
delay delay2 ( |
.d(cmd_read), |
914,18 → 2599,2264
endgenerate |
assign cs_n_pad_o = 1'b0; |
assign cke_pad_o = 1'b1; |
always @ (posedge sdram_clk or posedge sdram_rst) |
if (wb_rst) |
always @ (posedge sdram_clk or posedge sdram_rst) |
if (sdram_rst) |
{dq_i_reg, dq_i_tmp_reg} <= {16'h0000,16'h0000}; |
else |
{dq_i_reg, dq_i_tmp_reg} <= {dq_i, dq_i_reg}; |
assign fifo_dat_i = {dq_i_tmp_reg, dq_i_reg}; |
always @ (posedge sdram_clk or posedge sdram_rst) |
always @ (posedge sdram_clk or posedge sdram_rst) |
if (sdram_rst) begin |
{dq_o, dqm_pad_o} <= {16'h0000,2'b00}; |
dq_o_tmp_reg <= 18'h0; |
end else |
if (~count0) begin |
dq_o <= fifo_dat_o[fifo_sel_domain_reg][35:20]; |
dq_o_tmp_reg[17:2] <= fifo_dat_o[fifo_sel_domain_reg][19:4]; |
if (cmd_read) |
dqm_pad_o <= 2'b00; |
else |
dqm_pad_o <= ~fifo_dat_o[fifo_sel_domain_reg][3:2]; |
if (cmd_read) |
dq_o_tmp_reg[1:0] <= 2'b00; |
else |
dq_o_tmp_reg[1:0] <= ~fifo_dat_o[fifo_sel_domain_reg][1:0]; |
end else |
{dq_o,dqm_pad_o} <= dq_o_tmp_reg; |
endmodule |
`timescale 1ns/1ns |
module ddr_16 ( |
output reg [14:0] a, |
output reg adr_init, |
output reg bl_en, |
output reg [2:0] cmd, |
output reg cs_n, |
output reg [12:0] cur_row, |
output reg fifo_re, |
output reg read, |
output reg ref_ack, |
output reg ref_delay, |
output reg write, |
input wire bl_ack, |
input wire [3:0] burst_adr, |
input wire [7:0] fifo_empty, |
input wire fifo_re_d, |
input wire [2:0] fifo_sel, |
input wire ref_delay_ack, |
input wire ref_req, |
input wire sdram_clk, |
input wire [35:0] tx_fifo_dat_o, |
input wire wb_rst |
); |
parameter |
IDLE = 0, |
ACT_ROW = 1, |
AREF = 2, |
AREF_0 = 3, |
AREF_1 = 4, |
AWAIT_CMD = 5, |
LEMR2 = 6, |
LEMR3 = 7, |
LEMR_0 = 8, |
LEMR_1 = 9, |
LEMR_2 = 10, |
LMR_0 = 11, |
LMR_1 = 12, |
NOP0 = 13, |
NOP1 = 14, |
NOP10 = 15, |
NOP11 = 16, |
NOP12 = 17, |
NOP14 = 18, |
NOP15 = 19, |
NOP2 = 20, |
NOP20 = 21, |
NOP21 = 22, |
NOP22 = 23, |
NOP3 = 24, |
NOP30 = 25, |
NOP31 = 26, |
NOP32 = 27, |
NOP4 = 28, |
NOP5 = 29, |
NOP6 = 30, |
NOP7 = 31, |
NOP8 = 32, |
NOP9 = 33, |
NOP_tRFC = 34, |
NOP_tWR = 35, |
PRECHARGE = 36, |
PRE_0 = 37, |
PRE_1 = 38, |
READ_ADDR = 39, |
READ_BURST = 40, |
WRITE_ADDR = 41, |
WRITE_BURST = 42; |
reg [42:0] state; |
reg [42:0] nextstate; |
always @* begin |
nextstate = 43'b0000000000000000000000000000000000000000000; |
adr_init = 1'b0; |
bl_en = 1'b0; |
fifo_re = 1'b0; |
read = 1'b0; |
ref_ack = 1'b0; |
ref_delay = 1'b0; |
write = 1'b0; |
case (1'b1) |
state[IDLE] : begin |
begin |
nextstate[NOP0] = 1'b1; |
end |
end |
state[ACT_ROW] : begin |
if (tx_fifo_dat_o[5]) begin |
nextstate[NOP14] = 1'b1; |
end |
else begin |
nextstate[NOP15] = 1'b1; |
end |
end |
state[AREF] : begin |
ref_ack = 1'b1; |
ref_delay = 1'b1; |
begin |
nextstate[NOP_tRFC] = 1'b1; |
end |
end |
state[AREF_0] : begin |
ref_ack = 1'b1; |
begin |
nextstate[NOP7] = 1'b1; |
end |
end |
state[AREF_1] : begin |
ref_ack = 1'b1; |
begin |
nextstate[NOP8] = 1'b1; |
end |
end |
state[AWAIT_CMD] : begin |
adr_init = !(&fifo_empty); |
if (ref_req) begin |
nextstate[AREF] = 1'b1; |
end |
else if (!(&fifo_empty)) begin |
nextstate[NOP12] = 1'b1; |
end |
else begin |
nextstate[AWAIT_CMD] = 1'b1; |
end |
end |
state[LEMR2] : begin |
ref_ack = 1'b1; |
begin |
nextstate[NOP2] = 1'b1; |
end |
end |
state[LEMR3] : begin |
ref_ack = 1'b1; |
begin |
nextstate[NOP3] = 1'b1; |
end |
end |
state[LEMR_0] : begin |
ref_ack = 1'b1; |
begin |
nextstate[NOP4] = 1'b1; |
end |
end |
state[LEMR_1] : begin |
ref_ack = 1'b1; |
begin |
nextstate[NOP10] = 1'b1; |
end |
end |
state[LEMR_2] : begin |
ref_ack = 1'b1; |
begin |
nextstate[NOP11] = 1'b1; |
end |
end |
state[LMR_0] : begin |
ref_ack = 1'b1; |
begin |
nextstate[NOP5] = 1'b1; |
end |
end |
state[LMR_1] : begin |
ref_ack = 1'b1; |
begin |
nextstate[NOP9] = 1'b1; |
end |
end |
state[NOP0] : begin |
begin |
nextstate[PRE_0] = 1'b1; |
end |
end |
state[NOP1] : begin |
if (ref_req) begin |
nextstate[LEMR2] = 1'b1; |
end |
else begin |
nextstate[NOP1] = 1'b1; |
end |
end |
state[NOP10] : begin |
if (ref_req) begin |
nextstate[LEMR_2] = 1'b1; |
end |
else begin |
nextstate[NOP10] = 1'b1; |
end |
end |
state[NOP11] : begin |
if (ref_req) begin |
nextstate[AWAIT_CMD] = 1'b1; |
end |
else begin |
nextstate[NOP11] = 1'b1; |
end |
end |
state[NOP12] : begin |
begin |
nextstate[ACT_ROW] = 1'b1; |
end |
end |
state[NOP14] : begin |
begin |
nextstate[WRITE_ADDR] = 1'b1; |
end |
end |
state[NOP15] : begin |
begin |
nextstate[READ_ADDR] = 1'b1; |
end |
end |
state[NOP2] : begin |
if (ref_req) begin |
nextstate[LEMR3] = 1'b1; |
end |
else begin |
nextstate[NOP2] = 1'b1; |
end |
end |
state[NOP20] : begin |
begin |
nextstate[NOP21] = 1'b1; |
end |
end |
state[NOP21] : begin |
adr_init = 1'b1; |
if (!fifo_re_d) begin |
nextstate[NOP22] = 1'b1; |
end |
else begin |
nextstate[NOP21] = 1'b1; |
end |
end |
state[NOP22] : begin |
begin |
nextstate[NOP_tWR] = 1'b1; |
end |
end |
state[NOP3] : begin |
if (ref_req) begin |
nextstate[LEMR_0] = 1'b1; |
end |
else begin |
nextstate[NOP3] = 1'b1; |
end |
end |
state[NOP30] : begin |
begin |
nextstate[NOP31] = 1'b1; |
end |
end |
state[NOP31] : begin |
adr_init = 1'b1; |
begin |
nextstate[NOP32] = 1'b1; |
end |
end |
state[NOP32] : begin |
begin |
nextstate[NOP_tWR] = 1'b1; |
end |
end |
state[NOP4] : begin |
if (ref_req) begin |
nextstate[LMR_0] = 1'b1; |
end |
else begin |
nextstate[NOP4] = 1'b1; |
end |
end |
state[NOP5] : begin |
if (ref_req) begin |
nextstate[PRE_1] = 1'b1; |
end |
else begin |
nextstate[NOP5] = 1'b1; |
end |
end |
state[NOP6] : begin |
if (ref_req) begin |
nextstate[AREF_0] = 1'b1; |
end |
else begin |
nextstate[NOP6] = 1'b1; |
end |
end |
state[NOP7] : begin |
if (ref_req) begin |
nextstate[AREF_1] = 1'b1; |
end |
else begin |
nextstate[NOP7] = 1'b1; |
end |
end |
state[NOP8] : begin |
if (ref_req) begin |
nextstate[LMR_1] = 1'b1; |
end |
else begin |
nextstate[NOP8] = 1'b1; |
end |
end |
state[NOP9] : begin |
if (ref_req) begin |
nextstate[LEMR_1] = 1'b1; |
end |
else begin |
nextstate[NOP9] = 1'b1; |
end |
end |
state[NOP_tRFC] : begin |
ref_delay = !ref_delay_ack; |
if (ref_delay_ack) begin |
nextstate[AWAIT_CMD] = 1'b1; |
end |
else begin |
nextstate[NOP_tRFC] = 1'b1; |
end |
end |
state[NOP_tWR] : begin |
if (!(tx_fifo_dat_o[5]) && (cur_row == tx_fifo_dat_o[26:14])) begin |
nextstate[READ_ADDR] = 1'b1; |
end |
else if (tx_fifo_dat_o[5] && (cur_row == tx_fifo_dat_o[26:14])) begin |
nextstate[WRITE_ADDR] = 1'b1; |
end |
else begin |
nextstate[PRECHARGE] = 1'b1; |
end |
end |
state[PRECHARGE] : begin |
begin |
nextstate[AWAIT_CMD] = 1'b1; |
end |
end |
state[PRE_0] : begin |
ref_ack = 1'b1; |
begin |
nextstate[NOP1] = 1'b1; |
end |
end |
state[PRE_1] : begin |
ref_ack = 1'b1; |
begin |
nextstate[NOP6] = 1'b1; |
end |
end |
state[READ_ADDR] : begin |
bl_en = 1'b1; |
read = 1'b1; |
begin |
nextstate[READ_BURST] = 1'b1; |
end |
end |
state[READ_BURST] : begin |
bl_en = !bl_ack; |
fifo_re = bl_ack; |
read = !bl_ack; |
if (bl_ack) begin |
nextstate[NOP30] = 1'b1; |
end |
else begin |
nextstate[READ_BURST] = 1'b1; |
end |
end |
state[WRITE_ADDR] : begin |
bl_en = 1'b1; |
fifo_re = 1'b1; |
write = 1'b1; |
begin |
nextstate[WRITE_BURST] = 1'b1; |
end |
end |
state[WRITE_BURST]: begin |
bl_en = !bl_ack; |
fifo_re = 1'b1; |
write = 1'b1; |
if (bl_ack) begin |
nextstate[NOP20] = 1'b1; |
end |
else begin |
nextstate[WRITE_BURST] = 1'b1; |
end |
end |
endcase |
end |
always @(posedge sdram_clk or posedge wb_rst) begin |
if (wb_rst) |
state <= 43'b0000000000000000000000000000000000000000001 << IDLE; |
else |
state <= nextstate; |
end |
always @(posedge sdram_clk or posedge wb_rst) begin |
if (wb_rst) begin |
a[14:0] <= 15'd0; |
cmd[2:0] <= 3'b111; |
cs_n <= 1'b1; |
cur_row[12:0] <= cur_row; |
end |
else begin |
a[14:0] <= 15'd0; |
cmd[2:0] <= 3'b111; |
cs_n <= 1'b0; |
cur_row[12:0] <= cur_row; |
case (1'b1) |
nextstate[IDLE] : begin |
cs_n <= 1'b1; |
end |
nextstate[ACT_ROW] : begin |
a[14:0] <= {tx_fifo_dat_o[28:27],tx_fifo_dat_o[26:14]}; |
cmd[2:0] <= 3'b011; |
cur_row[12:0] <= tx_fifo_dat_o[26:14]; |
end |
nextstate[AREF] : begin |
a[14:0] <= a; |
cmd[2:0] <= 3'b001; |
end |
nextstate[AREF_0] : begin |
a[14:0] <= a; |
cmd[2:0] <= 3'b001; |
end |
nextstate[AREF_1] : begin |
a[14:0] <= a; |
cmd[2:0] <= 3'b001; |
end |
nextstate[AWAIT_CMD] : begin |
a[14:0] <= a; |
cs_n <= 1'b1; |
end |
nextstate[LEMR2] : begin |
a[14:0] <= {2'b10,5'b00000,1'b0,7'b0000000}; |
cmd[2:0] <= 3'b000; |
end |
nextstate[LEMR3] : begin |
a[14:0] <= {2'b11,13'b0000000000000}; |
cmd[2:0] <= 3'b000; |
end |
nextstate[LEMR_0] : begin |
a[14:0] <= {2'b01,1'b0,1'b0,1'b0,3'b000,1'b0,3'b000,1'b0,1'b0,1'b0}; |
cmd[2:0] <= 3'b000; |
end |
nextstate[LEMR_1] : begin |
a[14:0] <= {2'b01,1'b0,1'b0,1'b0,3'b111,1'b0,3'b000,1'b0,1'b0,1'b0}; |
cmd[2:0] <= 3'b000; |
end |
nextstate[LEMR_2] : begin |
a[14:0] <= {2'b01,1'b0,1'b0,1'b0,3'b000,1'b0,3'b000,1'b0,1'b0,1'b0}; |
cmd[2:0] <= 3'b000; |
end |
nextstate[LMR_0] : begin |
a[14:0] <= {2'b00,1'b0,3'b001,1'b1,1'b0,3'b100,1'b0,3'b011}; |
cmd[2:0] <= 3'b000; |
end |
nextstate[LMR_1] : begin |
a[14:0] <= {2'b00,1'b0,3'b001,1'b0,1'b0,3'b100,1'b0,3'b011}; |
cmd[2:0] <= 3'b000; |
end |
nextstate[NOP0] : begin |
a[14:0] <= a; |
end |
nextstate[NOP1] : begin |
a[14:0] <= a; |
end |
nextstate[NOP10] : begin |
a[14:0] <= a; |
end |
nextstate[NOP11] : begin |
a[14:0] <= a; |
end |
nextstate[NOP14] : begin |
a[14:0] <= a; |
end |
nextstate[NOP15] : begin |
a[14:0] <= a; |
end |
nextstate[NOP2] : begin |
a[14:0] <= a; |
end |
nextstate[NOP20] : begin |
a[14:0] <= a; |
end |
nextstate[NOP21] : begin |
a[14:0] <= a; |
end |
nextstate[NOP22] : begin |
a[14:0] <= a; |
end |
nextstate[NOP3] : begin |
a[14:0] <= a; |
end |
nextstate[NOP30] : begin |
a[14:0] <= a; |
end |
nextstate[NOP31] : begin |
a[14:0] <= a; |
end |
nextstate[NOP32] : begin |
a[14:0] <= a; |
end |
nextstate[NOP4] : begin |
a[14:0] <= a; |
end |
nextstate[NOP5] : begin |
a[14:0] <= a; |
end |
nextstate[NOP6] : begin |
a[14:0] <= a; |
end |
nextstate[NOP7] : begin |
a[14:0] <= a; |
end |
nextstate[NOP8] : begin |
a[14:0] <= a; |
end |
nextstate[NOP9] : begin |
a[14:0] <= a; |
end |
nextstate[NOP_tRFC] : begin |
a[14:0] <= a; |
end |
nextstate[NOP_tWR] : begin |
a[14:0] <= a; |
end |
nextstate[PRECHARGE] : begin |
a[14:0] <= {2'b00,13'b0010000000000}; |
cmd[2:0] <= 3'b010; |
end |
nextstate[PRE_0] : begin |
a[14:0] <= {2'b00,13'b0010000000000}; |
cmd[2:0] <= 3'b010; |
end |
nextstate[PRE_1] : begin |
a[14:0] <= {2'b00,13'b0010000000000}; |
cmd[2:0] <= 3'b010; |
end |
nextstate[READ_ADDR] : begin |
a[14:0] <= {tx_fifo_dat_o[28:27],{4'b0000,tx_fifo_dat_o[13:10],burst_adr,1'b0}}; |
cmd[2:0] <= 3'b101; |
end |
nextstate[READ_BURST] : begin |
a[14:0] <= a; |
end |
nextstate[WRITE_ADDR] : begin |
a[14:0] <= {tx_fifo_dat_o[28:27],{4'b0000,tx_fifo_dat_o[13:10],burst_adr,1'b0}}; |
cmd[2:0] <= 3'b100; |
end |
nextstate[WRITE_BURST]: begin |
a[14:0] <= a; |
end |
endcase |
end |
end |
reg [87:0] statename; |
always @* begin |
case (1'b1) |
state[IDLE] : |
statename = "IDLE"; |
state[ACT_ROW] : |
statename = "ACT_ROW"; |
state[AREF] : |
statename = "AREF"; |
state[AREF_0] : |
statename = "AREF_0"; |
state[AREF_1] : |
statename = "AREF_1"; |
state[AWAIT_CMD] : |
statename = "AWAIT_CMD"; |
state[LEMR2] : |
statename = "LEMR2"; |
state[LEMR3] : |
statename = "LEMR3"; |
state[LEMR_0] : |
statename = "LEMR_0"; |
state[LEMR_1] : |
statename = "LEMR_1"; |
state[LEMR_2] : |
statename = "LEMR_2"; |
state[LMR_0] : |
statename = "LMR_0"; |
state[LMR_1] : |
statename = "LMR_1"; |
state[NOP0] : |
statename = "NOP0"; |
state[NOP1] : |
statename = "NOP1"; |
state[NOP10] : |
statename = "NOP10"; |
state[NOP11] : |
statename = "NOP11"; |
state[NOP12] : |
statename = "NOP12"; |
state[NOP14] : |
statename = "NOP14"; |
state[NOP15] : |
statename = "NOP15"; |
state[NOP2] : |
statename = "NOP2"; |
state[NOP20] : |
statename = "NOP20"; |
state[NOP21] : |
statename = "NOP21"; |
state[NOP22] : |
statename = "NOP22"; |
state[NOP3] : |
statename = "NOP3"; |
state[NOP30] : |
statename = "NOP30"; |
state[NOP31] : |
statename = "NOP31"; |
state[NOP32] : |
statename = "NOP32"; |
state[NOP4] : |
statename = "NOP4"; |
state[NOP5] : |
statename = "NOP5"; |
state[NOP6] : |
statename = "NOP6"; |
state[NOP7] : |
statename = "NOP7"; |
state[NOP8] : |
statename = "NOP8"; |
state[NOP9] : |
statename = "NOP9"; |
state[NOP_tRFC] : |
statename = "NOP_tRFC"; |
state[NOP_tWR] : |
statename = "NOP_tWR"; |
state[PRECHARGE] : |
statename = "PRECHARGE"; |
state[PRE_0] : |
statename = "PRE_0"; |
state[PRE_1] : |
statename = "PRE_1"; |
state[READ_ADDR] : |
statename = "READ_ADDR"; |
state[READ_BURST] : |
statename = "READ_BURST"; |
state[WRITE_ADDR] : |
statename = "WRITE_ADDR"; |
state[WRITE_BURST]: |
statename = "WRITE_BURST"; |
default : |
statename = "XXXXXXXXXXX"; |
endcase |
end |
endmodule |
`timescale 1ns/1ns |
module delay (d, q, clk, rst); |
|
parameter width = 4; |
parameter depth = 3; |
|
input [width-1:0] d; |
output [width-1:0] q; |
input clk; |
input rst; |
|
reg [width-1:0] dffs [1:depth]; |
|
integer i; |
|
always @ (posedge clk or posedge rst) |
if (rst) |
for ( i=1; i <= depth; i=i+1) |
dffs[i] <= {width{1'b0}}; |
else |
begin |
dffs[1] <= d; |
for ( i=2; i <= depth; i=i+1 ) |
dffs[i] <= dffs[i-1]; |
end |
|
assign q = dffs[depth]; |
|
endmodule //delay |
|
|
`include "versatile_mem_ctrl_defines.v" |
|
module ddr_ff_in |
( |
input C0, // clock |
input C1, // clock |
input D, // data input |
input CE, // clock enable |
output Q0, // data output |
output Q1, // data output |
input R, // reset |
input S // set |
); |
|
`ifdef XILINX |
IDDR2 #( |
.DDR_ALIGNMENT("NONE"), |
.INIT_Q0(1'b0), |
.INIT_Q1(1'b0), |
.SRTYPE("SYNC")) |
IDDR2_inst ( |
.Q0(Q0), |
.Q1(Q1), |
.C0(C0), |
.C1(C1), |
.CE(CE), |
.D(D), |
.R(R), |
.S(S) |
); |
`endif // XILINX |
|
`ifdef ALTERA |
altddio_in #( |
.WIDTH(1), |
.POWER_UP_HIGH("OFF"), |
.INTENDED_DEVICE_FAMILY("Stratix III")) |
altddio_in_inst ( |
.aset(), |
.datain(D), |
.inclocken(CE), |
.inclock(C0), |
.aclr(R), |
.dataout_h(Q0), |
.dataout_l(Q1) |
); |
`endif // ALTERA |
|
`ifdef GENERIC_PRIMITIVES |
reg Q0_i, Q1_i; |
always @ (posedge R or posedge C0) |
if (R) |
Q0_i <= 1'b0; |
else |
Q0_i <= D; |
|
assign Q0 = Q0_i; |
|
always @ (posedge R or posedge C1) |
if (R) |
Q1_i <= 1'b0; |
else |
Q1_i <= D; |
|
assign Q1 = Q1_i; |
`endif // GENERIC_PRIMITIVES |
|
endmodule // ddr_ff_in |
|
|
module ddr_ff_out |
( |
input C0, // clock |
input C1, // clock |
input D0, // data input |
input D1, // data input |
input CE, // clock enable |
output Q, // data output |
input R, // reset |
input S // set |
); |
|
`ifdef XILINX |
ODDR2 #( |
.DDR_ALIGNMENT("NONE"), |
.INIT(1'b0), |
.SRTYPE("SYNC")) |
ODDR2_inst ( |
.Q(Q), |
.C0(C0), |
.C1(C1), |
.CE(CE), |
.D0(D0), |
.D1(D1), |
.R(R), |
.S(S) |
); |
`endif // XILINX |
|
`ifdef ALTERA |
altddio_out #( |
.WIDTH(1), |
.POWER_UP_HIGH("OFF"), |
.INTENDED_DEVICE_FAMILY("Stratix III"), |
.OE_REG("UNUSED")) |
altddio_out_inst ( |
.aset(), |
.datain_h(D0), |
.datain_l(D1), |
.outclocken(CE), |
.outclock(C0), |
.aclr(R), |
.dataout(Q) |
); |
`endif // ALTERA |
|
`ifdef GENERIC_PRIMITIVES |
reg Q0, Q1; |
always @ (posedge R or posedge C0) |
if (R) |
Q0 <= 1'b0; |
else |
Q0 <= D0; |
|
always @ (posedge R or posedge C1) |
if (R) |
Q1 <= 1'b0; |
else |
Q1 <= D1; |
|
assign Q = C0 ? Q0 : Q1; |
`endif // GENERIC_PRIMITIVES |
|
endmodule // ddr_ff_out |
|
`include "versatile_mem_ctrl_defines.v" |
|
module dcm_pll |
( |
input rst, // reset |
input clk_in, // clock in |
input clkfb_in, // feedback clock in |
output clk0_out, // clock out |
output clk90_out, // clock out, 90 degree phase shift |
output clk180_out, // clock out, 180 degree phase shift |
output clk270_out, // clock out, 270 degree phase shift |
output clkfb_out // feedback clock out |
); |
|
`ifdef XILINX |
wire clk_in_ibufg; |
wire clk0_bufg, clk90_bufg, clk180_bufg, clk270_bufg; |
// DCM with internal feedback |
DCM #( |
.CLKDV_DIVIDE(2.0), |
.CLKFX_DIVIDE(1), |
.CLKFX_MULTIPLY(4), |
.CLKIN_DIVIDE_BY_2("FALSE"), |
.CLKIN_PERIOD(8.0), |
.CLKOUT_PHASE_SHIFT("NONE"), |
.CLK_FEEDBACK("1X"), |
.DESKEW_ADJUST("SYSTEM_SYNCHRONOUS"), |
.DLL_FREQUENCY_MODE("LOW"), |
.DUTY_CYCLE_CORRECTION("TRUE"), |
.PHASE_SHIFT(0), |
.STARTUP_WAIT("FALSE")) |
DCM_internal ( |
.CLK0(clk0_bufg), |
.CLK180(clk180_bufg), |
.CLK270(clk270_bufg), |
.CLK2X(), |
.CLK2X180(), |
.CLK90(clk90_bufg), |
.CLKDV(), |
.CLKFX(), |
.CLKFX180(), |
.LOCKED(), |
.PSDONE(), |
.STATUS(), |
.CLKFB(clk0_out), |
.CLKIN(clk_in_ibufg), |
.DSSEN(), |
.PSCLK(), |
.PSEN(), |
.PSINCDEC(), |
.RST(rst) |
); |
// DCM with external feedback |
DCM #( |
.CLKDV_DIVIDE(2.0), |
.CLKFX_DIVIDE(1), |
.CLKFX_MULTIPLY(4), |
.CLKIN_DIVIDE_BY_2("FALSE"), |
.CLKIN_PERIOD(8.0), |
.CLKOUT_PHASE_SHIFT("NONE"), |
.CLK_FEEDBACK("1X"), |
.DESKEW_ADJUST("SYSTEM_SYNCHRONOUS"), |
.DLL_FREQUENCY_MODE("LOW"), |
.DUTY_CYCLE_CORRECTION("TRUE"), |
.PHASE_SHIFT(0), |
.STARTUP_WAIT("FALSE")) |
DCM_external ( |
.CLK0(clkfb_bufg), |
.CLK180(), |
.CLK270(), |
.CLK2X(), |
.CLK2X180(), |
.CLK90(), |
.CLKDV(), |
.CLKFX(), |
.CLKFX180(), |
.LOCKED(), |
.PSDONE(), |
.STATUS(), |
.CLKFB(clkfb_ibufg), |
.CLKIN(clk_in_ibufg), |
.DSSEN(), |
.PSCLK(), |
.PSEN(), |
.PSINCDEC(), |
.RST(rst) |
); |
|
// Input buffer on DCM clock source |
IBUFG IBUFG_clk ( |
.I(clk_in), |
.O(clk_in_ibufg)); |
|
// Global buffers on DCM generated clocks |
BUFG BUFG_0 ( |
.I(clk0_bufg), |
.O(clk0_out)); |
BUFG BUFG_90 ( |
.I(clk90_bufg), |
.O(clk90_out)); |
BUFG BUFG_180 ( |
.I(clk180_bufg), |
.O(clk180_out)); |
BUFG BUFG_270 ( |
.I(clk270_bufg), |
.O(clk270_out)); |
|
// External feedback to DCM |
IBUFG IBUFG_clkfb ( |
.I(clkfb_in), |
.O(clkfb_ibufg)); |
OBUF OBUF_clkfb ( |
.I(clkfb_bufg), |
.O(clkfb_out)); |
`endif // XILINX |
|
|
`ifdef ALTERA |
wire [9:0] sub_wire0; |
wire [0:0] sub_wire8 = 1'h0; |
wire [3:3] sub_wire4 = sub_wire0[3:3]; |
wire [2:2] sub_wire3 = sub_wire0[2:2]; |
wire [1:1] sub_wire2 = sub_wire0[1:1]; |
wire [0:0] sub_wire1 = sub_wire0[0:0]; |
wire sub_wire6 = clk_in; |
wire [1:0] sub_wire7 = {sub_wire8, sub_wire6}; |
|
assign clk0_out = sub_wire1; |
assign clk90_out = sub_wire2; |
assign clk180_out = sub_wire3; |
assign clk270_out = sub_wire4; |
|
// PLL with external feedback |
altpll #( |
.bandwidth_type("AUTO"), |
.clk0_divide_by(1), |
.clk0_duty_cycle(50), |
.clk0_multiply_by(1), |
.clk0_phase_shift("0"), |
.clk1_divide_by(1), |
.clk1_duty_cycle(50), |
.clk1_multiply_by(1), |
.clk1_phase_shift("1250"), |
.clk2_divide_by(1), |
.clk2_duty_cycle(50), |
.clk2_multiply_by(1), |
.clk2_phase_shift("2500"), |
.clk3_divide_by(1), |
.clk3_duty_cycle(50), |
.clk3_multiply_by(1), |
.clk3_phase_shift("3750"), |
.compensate_clock("CLK0"), |
.inclk0_input_frequency(5000), |
.intended_device_family("Stratix III"), |
.lpm_hint("UNUSED"), |
.lpm_type("altpll"), |
.operation_mode("NORMAL"), |
// .operation_mode("SOURCE_SYNCHRONOUS"), |
.pll_type("AUTO"), |
.port_activeclock("PORT_UNUSED"), |
.port_areset("PORT_USED"), |
.port_clkbad0("PORT_UNUSED"), |
.port_clkbad1("PORT_UNUSED"), |
.port_clkloss("PORT_UNUSED"), |
.port_clkswitch("PORT_UNUSED"), |
.port_configupdate("PORT_UNUSED"), |
.port_fbin("PORT_USED"), |
.port_fbout("PORT_USED"), |
.port_inclk0("PORT_USED"), |
.port_inclk1("PORT_UNUSED"), |
.port_locked("PORT_UNUSED"), |
.port_pfdena("PORT_UNUSED"), |
.port_phasecounterselect("PORT_UNUSED"), |
.port_phasedone("PORT_UNUSED"), |
.port_phasestep("PORT_UNUSED"), |
.port_phaseupdown("PORT_UNUSED"), |
.port_pllena("PORT_UNUSED"), |
.port_scanaclr("PORT_UNUSED"), |
.port_scanclk("PORT_UNUSED"), |
.port_scanclkena("PORT_UNUSED"), |
.port_scandata("PORT_UNUSED"), |
.port_scandataout("PORT_UNUSED"), |
.port_scandone("PORT_UNUSED"), |
.port_scanread("PORT_UNUSED"), |
.port_scanwrite("PORT_UNUSED"), |
.port_clk0("PORT_USED"), |
.port_clk1("PORT_USED"), |
.port_clk2("PORT_USED"), |
.port_clk3("PORT_USED"), |
.port_clk4("PORT_UNUSED"), |
.port_clk5("PORT_UNUSED"), |
.port_clk6("PORT_UNUSED"), |
.port_clk7("PORT_UNUSED"), |
.port_clk8("PORT_UNUSED"), |
.port_clk9("PORT_UNUSED"), |
.port_clkena0("PORT_UNUSED"), |
.port_clkena1("PORT_UNUSED"), |
.port_clkena2("PORT_UNUSED"), |
.port_clkena3("PORT_UNUSED"), |
.port_clkena4("PORT_UNUSED"), |
.port_clkena5("PORT_UNUSED"), |
.using_fbmimicbidir_port("OFF"), |
.width_clock(10)) |
altpll_internal ( |
.fbin (),//(clkfb_in), |
.inclk (sub_wire7), |
.areset (rst), |
.clk (sub_wire0), |
.fbout (),//(clkfb_out), |
.activeclock (), |
.clkbad (), |
.clkena ({6{1'b1}}), |
.clkloss (), |
.clkswitch (1'b0), |
.configupdate (1'b0), |
.enable0 (), |
.enable1 (), |
.extclk (), |
.extclkena ({4{1'b1}}), |
.fbmimicbidir (), |
.locked (), |
.pfdena (1'b1), |
.phasecounterselect ({4{1'b1}}), |
.phasedone (), |
.phasestep (1'b1), |
.phaseupdown (1'b1), |
.pllena (1'b1), |
.scanaclr (1'b0), |
.scanclk (1'b0), |
.scanclkena (1'b1), |
.scandata (1'b0), |
.scandataout (), |
.scandone (), |
.scanread (1'b0), |
.scanwrite (1'b0), |
.sclkout0 (), |
.sclkout1 (), |
.vcooverrange (), |
.vcounderrange () |
); |
`endif // ALTERA |
|
//`ifdef GENERIC_PRIMITIVES |
//`endif // GENERIC_PRIMITIVES |
|
|
endmodule // dcm_pll |
|
|
////////////////////////////////////////////////////////////////////// |
//// //// |
//// Versatile counter //// |
//// //// |
//// Description //// |
//// Versatile counter, a reconfigurable binary, gray or LFSR //// |
//// counter //// |
//// //// |
//// To Do: //// |
//// - add LFSR with more taps //// |
//// //// |
//// Author(s): //// |
//// - Michael Unneback, unneback@opencores.org //// |
//// ORSoC AB //// |
//// //// |
////////////////////////////////////////////////////////////////////// |
//// //// |
//// Copyright (C) 2009 Authors and OPENCORES.ORG //// |
//// //// |
//// This source file may be used and distributed without //// |
//// restriction provided that this copyright statement is not //// |
//// removed from the file and that any derivative work contains //// |
//// the original copyright notice and the associated disclaimer. //// |
//// //// |
//// This source file is free software; you can redistribute it //// |
//// and/or modify it under the terms of the GNU Lesser General //// |
//// Public License as published by the Free Software Foundation; //// |
//// either version 2.1 of the License, or (at your option) any //// |
//// later version. //// |
//// //// |
//// This source is distributed in the hope that it will be //// |
//// useful, but WITHOUT ANY WARRANTY; without even the implied //// |
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// |
//// PURPOSE. See the GNU Lesser General Public License for more //// |
//// details. //// |
//// //// |
//// You should have received a copy of the GNU Lesser General //// |
//// Public License along with this source; if not, download it //// |
//// from http://www.opencores.org/lgpl.shtml //// |
//// //// |
////////////////////////////////////////////////////////////////////// |
|
module dff_sr ( aclr, aset, clock, data, q); |
|
input aclr; |
input aset; |
input clock; |
input data; |
output reg q; |
|
always @ (posedge clock or posedge aclr or posedge aset) |
if (aclr) |
q <= 1'b0; |
else if (aset) |
q <= 1'b1; |
else |
q <= data; |
|
endmodule |
module versatile_mem_ctrl_ddr ( |
// DDR2 SDRAM side |
ck_o, ck_n_o, |
dq_io, dqs_io, dqs_n_io, |
dm_rdqs_io, |
//rdqs_n_i, odt_o, |
// Memory controller side |
tx_dat_i, rx_dat_o, |
dq_en, dqm_en, |
wb_rst, sdram_clk_0, sdram_clk_90, sdram_clk_180, sdram_clk_270 |
); |
|
output ck_o; |
output ck_n_o; |
inout [15:0] dq_io; |
inout [1:0] dqs_io; |
inout [1:0] dqs_n_io; |
inout [1:0] dm_rdqs_io; |
//input [1:0] rdqs_n_i; |
//output odt_o; |
input [35:0] tx_dat_i; |
output [35:0] rx_dat_o; |
input dq_en; |
input dqm_en; |
input wb_rst; |
input sdram_clk_0; |
input sdram_clk_90; |
input sdram_clk_180; |
input sdram_clk_270; |
|
reg [31:0] dq_rx_reg; |
wire [31:0] dq_rx; |
wire [1:0] dqs_o, dqs_n_o, dqm_o; |
wire [15:0] dq_o; |
wire [1:0] dqs_delayed, dqs_n_delayed; |
|
wire [15:0] dq_iobuf; |
wire [1:0] dqs_iobuf, dqs_n_iobuf; |
|
genvar i; |
|
/////////////////////////////////////////////////////////////////////////////// |
// Common for both Xilinx and Altera |
/////////////////////////////////////////////////////////////////////////////// |
|
// Generate clock with equal delay as data |
ddr_ff_out ddr_ff_out_ck ( |
.Q(ck_o), |
.C0(sdram_clk_0), |
.C1(sdram_clk_180), |
.CE(1'b1), |
.D0(1'b1), |
.D1(1'b0), |
.R(1'b0), |
.S(1'b0)); |
|
ddr_ff_out ddr_ff_out_ck_n ( |
.Q(ck_n_o), |
.C0(sdram_clk_0), |
.C1(sdram_clk_180), |
.CE(1'b1), |
.D0(1'b0), |
.D1(1'b1), |
.R(wb_rst), |
.S(1'b0)); |
|
// Generate strobe with equal delay as data |
generate |
for (i=0; i<2; i=i+1) begin:dqs_oddr |
ddr_ff_out ddr_ff_out_dqs ( |
.Q(dqs_o[i]), |
.C0(sdram_clk_0), |
.C1(sdram_clk_180), |
.CE(1'b1), |
.D0(1'b1), |
.D1(1'b0), |
.R(1'b0), |
.S(1'b0)); |
end |
endgenerate |
|
generate |
for (i=0; i<2; i=i+1) begin:dqs_n_oddr |
ddr_ff_out ddr_ff_out_dqs_n ( |
.Q(dqs_n_o[i]), |
.C0(sdram_clk_0), |
.C1(sdram_clk_180), |
.CE(1'b1), |
.D0(1'b0), |
.D1(1'b1), |
.R(wb_rst), |
.S(1'b0)); |
end |
endgenerate |
|
|
|
/////////////////////////////////////////////////////////////////////////////// |
// Xilinx |
/////////////////////////////////////////////////////////////////////////////// |
|
`ifdef XILINX |
|
reg [15:0] dq_tx_reg; |
wire [15:0] dq_tx; |
reg [3:0] dqm_tx_reg; |
wire [3:0] dqm_tx; |
|
// IO BUFFER |
// DDR data to/from DDR2 SDRAM |
generate |
for (i=0; i<16; i=i+1) begin:iobuf_dq |
IOBUF u_iobuf_dq ( |
.I(dq_o[i]), |
.T(!dq_en), |
.IO(dq_io[i]), |
.O(dq_iobuf[i])); |
end |
endgenerate |
|
// DQS strobe to/from DDR2 SDRAM |
generate |
for (i=0; i<2; i=i+1) begin:iobuf_dqs |
IOBUF u_iobuf_dqs ( |
.I(dqs_o[i]), |
.T(!dq_en), |
.IO(dqs_io[i]), |
.O(dqs_iobuf[i])); |
end |
endgenerate |
|
// DQS strobe to/from DDR2 SDRAM |
generate |
for (i=0; i<2; i=i+1) begin:iobuf_dqs_n |
IOBUF u_iobuf_dqs_n ( |
.I(dqs_n_o[i]), |
.T(!dq_en), |
.IO(dqs_n_io[i]), |
.O(dqs_n_iobuf[i])); |
end |
endgenerate |
|
|
// Data from Tx FIFO |
always @ (posedge sdram_clk_270 or posedge wb_rst) |
if (wb_rst) |
dq_tx_reg[15:0] <= 16'h0; |
else |
if (dqm_en) |
dq_tx_reg[15:0] <= tx_dat_i[19:4]; |
else |
dq_tx_reg[15:0] <= tx_dat_i[19:4]; |
|
assign dq_tx[15:0] = tx_dat_i[35:20]; |
|
// Output Data DDR flip-flops |
generate |
for (i=0; i<16; i=i+1) begin:data_out_oddr |
ddr_ff_out ddr_ff_out_inst_0 ( |
.Q(dq_o[i]), |
.C0(sdram_clk_270), |
.C1(sdram_clk_90), |
.CE(dq_en), |
.D0(dq_tx[i]), |
.D1(dq_tx_reg[i]), |
.R(wb_rst), |
.S(1'b0)); |
end |
endgenerate |
|
// Data mask from Tx FIFO |
always @ (posedge sdram_clk_270 or posedge wb_rst) |
if (wb_rst) |
dqm_tx_reg[1:0] <= 2'b00; |
else |
if (dqm_en) |
dqm_tx_reg[1:0] <= 2'b00; |
else |
dqm_tx_reg[1:0] <= tx_dat_i[1:0]; |
|
always @ (posedge sdram_clk_180 or posedge wb_rst) |
if (wb_rst) |
dqm_tx_reg[3:2] <= 2'b00; |
else |
if (dqm_en) |
dqm_tx_reg[3:2] <= 2'b00; |
else |
dqm_tx_reg[3:2] <= tx_dat_i[3:2]; |
|
assign dqm_tx[1:0] = (dqm_en) ? 2'b00 : tx_dat_i[3:2]; |
|
// Mask output DDR flip-flops |
generate |
for (i=0; i<2; i=i+1) begin:data_mask_oddr |
ddr_ff_out ddr_ff_out_inst_1 ( |
.Q(dqm_o[i]), |
.C0(sdram_clk_270), |
.C1(sdram_clk_90), |
.CE(dq_en), |
.D0(!dqm_tx[i]), |
.D1(!dqm_tx_reg[i]), |
.R(wb_rst), |
.S(1'b0)); |
end |
endgenerate |
|
// Data mask to DDR2 SDRAM |
generate |
for (i=0; i<2; i=i+1) begin:iobuf_dqm |
IOBUF u_iobuf_dqm ( |
.I(dqm_o[i]), |
.T(!dq_en), |
.IO(dm_rdqs_io[i]), |
.O()); |
end |
endgenerate |
|
|
`ifdef INT_CLOCKED_DATA_CAPTURE |
// Data in |
// DDR flip-flops |
generate |
for (i=0; i<16; i=i+1) begin:iddr2gen |
ddr_ff_in ddr_ff_in_inst_0 ( |
.Q0(dq_rx[i]), |
.Q1(dq_rx[i+16]), |
.C0(sdram_clk_270), |
.C1(sdram_clk_90), |
.CE(1'b1), |
.D(dq_io[i]), |
.R(wb_rst), |
.S(1'b0)); |
end |
endgenerate |
|
// Data to Rx FIFO |
always @ (posedge sdram_clk_0 or posedge wb_rst) |
if (wb_rst) |
dq_rx_reg[31:16] <= 16'h0; |
else |
dq_rx_reg[31:16] <= dq_rx[31:16]; |
|
always @ (posedge sdram_clk_180 or posedge wb_rst) |
if (wb_rst) |
dq_rx_reg[15:0] <= 16'h0; |
else |
dq_rx_reg[15:0] <= dq_rx[15:0]; |
|
assign rx_dat_o = {dq_rx_reg, 4'h0}; |
`endif // INT_CLOCKED_DATA_CAPTURE |
|
|
`ifdef DEL_DQS_DATA_CAPTURE_1 |
|
wire [1:0] dqs_iodelay, dqs_n_iodelay; |
|
// Delay DQS |
assign # 2 dqs_iodelay = dqs_iobuf; |
assign # 2 dqs_n_iodelay = dqs_n_iobuf; |
|
// IDDR FF |
generate |
for (i=0; i<16; i=i+1) begin:iddr_dq |
ddr_ff_in ddr_ff_in_inst_0 ( |
.Q0(dq_rx[i]), |
.Q1(dq_rx[i+16]), |
.C0(dqs_iodelay[0]), |
.C1(dqs_n_iodelay[0]), |
.CE(1'b1), |
.D(dq_iobuf[i]), |
.R(wb_rst), |
.S(1'b0)); |
end |
endgenerate |
|
// Data to Rx FIFO |
always @ (posedge sdram_clk_0 or posedge wb_rst) |
if (wb_rst) |
dq_rx_reg[31:16] <= 16'h0; |
else |
dq_rx_reg[31:16] <= dq_rx[31:16]; |
|
always @ (posedge sdram_clk_0 or posedge wb_rst) |
if (wb_rst) |
dq_rx_reg[15:0] <= 16'h0; |
else |
dq_rx_reg[15:0] <= dq_rx[15:0]; |
|
assign rx_dat_o = {dq_rx_reg, 4'h0}; |
|
`endif // DEL_DQS_DATA_CAPTURE_1 |
|
|
`ifdef DEL_DQS_DATA_CAPTURE_2 |
|
wire [15:0] dq_iodelay; |
wire [1:0] dqs_iodelay, dqs_n_iodelay; |
wire [15:0] dq_iddr_fall, dq_iddr_rise; |
reg [15:0] dq_fall_1, dq_rise_1; |
reg [15:0] dq_fall_2, dq_rise_2; |
reg [15:0] dq_fall_3, dq_rise_3; |
|
|
// Delay data |
// IODELAY is available in the Xilinx Virtex FPGAs |
/*IODELAY # ( |
.DELAY_SRC(), |
.IDELAY_TYPE(), |
.HIGH_PERFORMANCE_MODE(), |
.IDELAY_VALUE(), |
.ODELAY_VALUE()) |
u_idelay_dq ( |
.DATAOUT(), |
.C(), |
.CE(), |
.DATAIN(), |
.IDATAIN(), |
.INC(), |
.ODATAIN(), |
.RST(), |
.T());*/ |
// IODELAY is NOT available in the Xilinx Spartan FPGAs, |
// equivalent delay can be implemented using a chain of LUT |
/*lut_delay lut_delay_dq ( |
.clk_i(), |
.d_i(dq_iobuf), |
.d_o(dq_iodelay));*/ |
|
// IDDR FF |
generate |
for (i=0; i<16; i=i+1) begin:iddr_dq |
ddr_ff_in ddr_ff_in_inst_0 ( |
.Q0(dq_iddr_fall[i]), |
.Q1(dq_iddr_rise[i]), |
.C0(dqs_iodelay[0]), |
.C1(dqs_n_iodelay[0]), |
.CE(1'b1), |
.D(dq_iobuf[i]), |
.R(wb_rst), |
.S(1'b0)); |
end |
endgenerate |
|
// Rise & fall clocked FF |
always @ (posedge sdram_clk_0 or posedge wb_rst) |
if (wb_rst) begin |
dq_fall_1 <= 16'h0; |
dq_rise_1 <= 16'h0; |
end else begin |
dq_fall_1 <= dq_iddr_fall; |
dq_rise_1 <= dq_iddr_rise; |
end |
|
always @ (posedge sdram_clk_180 or posedge wb_rst) |
if (wb_rst) begin |
dq_fall_2 <= 16'h0; |
dq_rise_2 <= 16'h0; |
end else begin |
dq_fall_2 <= dq_iddr_fall; |
dq_rise_2 <= dq_iddr_rise; |
end |
|
// Fall sync FF |
always @ (posedge sdram_clk_0 or posedge wb_rst) |
if (wb_rst) begin |
dq_fall_3 <= 16'h0; |
dq_rise_3 <= 16'h0; |
end else begin |
dq_fall_3 <= dq_fall_2; |
dq_rise_3 <= dq_rise_2; |
end |
|
// Mux |
assign rx_dat_o[35:32] = 4'h0; |
assign rx_dat_o[31:16] = dq_fall_1; |
assign rx_dat_o[15:0] = dq_rise_1; |
|
// DDR DQS to IODUFDS |
// Delay DQS |
// IODELAY is NOT available in the Xilinx Spartan FPGAs, |
// equivalent delay can be implemented using a chain of LUTs |
/* |
generate |
for (i=0; i<2; i=i+1) begin:lut_delay_dqs |
lut_delay lut_delay_dqs ( |
.d_i(dqs_iobuf[i]), |
.d_o(dqs_iodelay[i])); |
end |
endgenerate |
generate |
for (i=0; i<2; i=i+1) begin:lut_delay_dqs_n |
lut_delay lut_delay_dqs_n ( |
.d_i(dqs_n_iobuf[i]), |
.d_o(dqs_n_iodelay[i])); |
end |
endgenerate |
*/ |
|
assign # 2 dqs_iodelay = dqs_iobuf; |
assign # 2 dqs_n_iodelay = dqs_n_iobuf; |
|
|
// BUFIO (?) |
`endif // DEL_DQS_DATA_CAPTURE_2 |
|
`endif // XILINX |
|
|
/////////////////////////////////////////////////////////////////////////////// |
// Altera |
/////////////////////////////////////////////////////////////////////////////// |
|
`ifdef ALTERA |
|
wire [3:0] dqm_tx; |
|
// Data out |
// DDR flip-flops |
generate |
for (i=0; i<16; i=i+1) begin:data_out_oddr |
ddr_ff_out ddr_ff_out_inst_0 ( |
.Q(dq_o[i]), |
.C0(sdram_clk_270), |
.C1(sdram_clk_90), |
.CE(dq_en), |
.D0(tx_dat_i[i+16+4]), |
.D1(tx_dat_i[i+4]), |
.R(wb_rst), |
.S(1'b0)); |
end |
endgenerate |
|
// Assign outport |
assign dq_io = dq_en ? dq_o : {16{1'bz}}; |
|
// Data mask |
// Data mask from Tx FIFO |
assign dqm_tx = dqm_en ? {4{1'b0}} : tx_dat_i[3:0]; |
|
// DDR flip-flops |
generate |
for (i=0; i<2; i=i+1) begin:data_mask_oddr |
ddr_ff_out ddr_ff_out_inst_1 ( |
.Q(dqm_o[i]), |
.C0(sdram_clk_270), |
.C1(sdram_clk_90), |
.CE(dq_en), |
.D0(!dqm_tx[i+2]), |
.D1(!dqm_tx[i]), |
.R(wb_rst), |
.S(1'b0)); |
end |
endgenerate |
|
// Assign outport |
assign dm_rdqs_io = dq_en ? dqm_o : 2'bzz; |
|
|
// Data in |
`ifdef INT_CLOCKED_DATA_CAPTURE |
// DDR flip-flops |
generate |
for (i=0; i<16; i=i+1) begin:iddr2gen |
ddr_ff_in ddr_ff_in_inst_0 ( |
.Q0(dq_rx[i]), |
.Q1(dq_rx[i+16]), |
.C0(sdram_clk_270), |
.C1(sdram_clk_90), |
.CE(1'b1), |
.D(dq_io[i]), |
.R(wb_rst), |
.S(1'b0)); |
end |
endgenerate |
|
// Data to Rx FIFO |
always @ (posedge sdram_clk_180 or posedge wb_rst) |
if (wb_rst) |
dq_rx_reg <= 32'h0; |
else |
dq_rx_reg <= dq_rx; |
|
assign rx_dat_o = {dq_rx_reg, 4'h0}; |
`endif // INT_CLOCKED_DATA_CAPTURE |
|
`ifdef DEL_DQS_DATA_CAPTURE_1 |
// Delay DQS |
// DDR FF |
`endif // DEL_DQS_DATA_CAPTURE_1 |
|
`ifdef DEL_DQS_DATA_CAPTURE_2 |
// DDR data to IOBUFFER |
// Delay data (?) |
// DDR FF |
// Rise & fall clocked FF |
// Fall sync FF |
// Mux |
// DDR DQS to IODUFDS |
// Delay DQS |
// BUFIO (?) |
`endif // DEL_DQS_DATA_CAPTURE_2 |
|
`endif // ALTERA |
|
|
endmodule // versatile_mem_ctrl_ddr |
|
|
`timescale 1ns/1ns |
`ifdef DDR_16 |
`include "ddr_16_defines.v" |
`endif |
|
module versatile_mem_ctrl_top |
( |
// wishbone side |
wb_adr_i_0, wb_dat_i_0, wb_dat_o_0, |
wb_stb_i_0, wb_cyc_i_0, wb_ack_o_0, |
wb_adr_i_1, wb_dat_i_1, wb_dat_o_1, |
wb_stb_i_1, wb_cyc_i_1, wb_ack_o_1, |
wb_adr_i_2, wb_dat_i_2, wb_dat_o_2, |
wb_stb_i_2, wb_cyc_i_2, wb_ack_o_2, |
wb_adr_i_3, wb_dat_i_3, wb_dat_o_3, |
wb_stb_i_3, wb_cyc_i_3, wb_ack_o_3, |
wb_clk, wb_rst, |
|
`ifdef SDR_16 |
ba_pad_o, a_pad_o, cs_n_pad_o, ras_pad_o, cas_pad_o, we_pad_o, dq_o, dqm_pad_o, dq_i, dq_oe, cke_pad_o, |
`endif |
|
`ifdef DDR_16 |
ck_pad_o, ck_n_pad_o, cke_pad_o, ck_fb_pad_o, ck_fb_pad_i, |
cs_n_pad_o, ras_pad_o, cas_pad_o, we_pad_o, |
dm_rdqs_pad_io, ba_pad_o, addr_pad_o, dq_pad_io, dqs_pad_io, dqs_oe, dqs_n_pad_io, rdqs_n_pad_i, odt_pad_o, |
`endif |
// SDRAM signals |
sdram_clk, sdram_rst |
); |
|
// number of wb clock domains |
parameter nr_of_wb_clk_domains = 1; |
// number of wb ports in each wb clock domain |
parameter nr_of_wb_ports_clk0 = 1; |
parameter nr_of_wb_ports_clk1 = 0; |
parameter nr_of_wb_ports_clk2 = 0; |
parameter nr_of_wb_ports_clk3 = 0; |
|
parameter ba_size = 2; |
parameter row_size = 13; |
parameter col_size = 9; |
parameter [2:0] cl = 3'b010; // valid options 010, 011 used for SDR LMR |
|
input [36*nr_of_wb_ports_clk0-1:0] wb_adr_i_0; |
input [36*nr_of_wb_ports_clk0-1:0] wb_dat_i_0; |
output [32*nr_of_wb_ports_clk0-1:0] wb_dat_o_0; |
input [0:nr_of_wb_ports_clk0-1] wb_stb_i_0, wb_cyc_i_0, wb_ack_o_0; |
|
input [36*nr_of_wb_ports_clk1-1:0] wb_adr_i_1; |
input [36*nr_of_wb_ports_clk1-1:0] wb_dat_i_1; |
output [32*nr_of_wb_ports_clk1-1:0] wb_dat_o_1; |
input [0:nr_of_wb_ports_clk1-1] wb_stb_i_1, wb_cyc_i_1, wb_ack_o_1; |
|
input [36*nr_of_wb_ports_clk2-1:0] wb_adr_i_2; |
input [36*nr_of_wb_ports_clk2-1:0] wb_dat_i_2; |
output [32*nr_of_wb_ports_clk2-1:0] wb_dat_o_2; |
input [0:nr_of_wb_ports_clk2-1] wb_stb_i_2, wb_cyc_i_2, wb_ack_o_2; |
|
input [36*nr_of_wb_ports_clk3-1:0] wb_adr_i_3; |
input [36*nr_of_wb_ports_clk3-1:0] wb_dat_i_3; |
output [32*nr_of_wb_ports_clk3-1:0] wb_dat_o_3; |
input [0:nr_of_wb_ports_clk3-1] wb_stb_i_3, wb_cyc_i_3, wb_ack_o_3; |
|
input [0:nr_of_wb_clk_domains-1] wb_clk; |
input [0:nr_of_wb_clk_domains-1] wb_rst; |
|
`ifdef SDR_16 |
output [1:0] ba_pad_o; |
output [12:0] a_pad_o; |
output cs_n_pad_o; |
output ras_pad_o; |
output cas_pad_o; |
output we_pad_o; |
output reg [15:0] dq_o; |
output reg [1:0] dqm_pad_o; |
input [15:0] dq_i; |
output dq_oe; |
output cke_pad_o; |
`endif |
`ifdef DDR_16 |
output ck_pad_o; |
output ck_n_pad_o; |
output cke_pad_o; |
output ck_fb_pad_o; |
input ck_fb_pad_i; |
output cs_n_pad_o; |
output ras_pad_o; |
output cas_pad_o; |
output we_pad_o; |
inout [1:0] dm_rdqs_pad_io; |
output [1:0] ba_pad_o; |
output [12:0] addr_pad_o; |
inout [15:0] dq_pad_io; |
inout [1:0] dqs_pad_io; |
output dqs_oe; |
inout [1:0] dqs_n_pad_io; |
input [1:0] rdqs_n_pad_i; |
output odt_pad_o; |
`endif |
input sdram_clk, sdram_rst; |
|
wire [0:15] fifo_empty[0:3]; |
wire current_fifo_empty; |
wire [0:15] fifo_re[0:3]; |
wire [35:0] fifo_dat_o[0:3]; |
wire [31:0] fifo_dat_i; |
wire [0:15] fifo_we[0:3]; |
wire fifo_rd_adr, fifo_rd_data, fifo_wr, idle, count0; |
|
wire [0:15] fifo_sel_i, fifo_sel_dly; |
reg [0:15] fifo_sel_reg; |
wire [1:0] fifo_sel_domain_i, fifo_sel_domain_dly; |
reg [1:0] fifo_sel_domain_reg; |
|
reg refresh_req; |
|
wire [35:0] tx_fifo_dat_o; // tmp added /MF |
|
generate |
if (nr_of_wb_clk_domains > 0) begin |
versatile_mem_ctrl_wb |
# (.nr_of_wb_ports(nr_of_wb_ports_clk0)) |
wb0( |
// wishbone side |
.wb_adr_i_v(wb_adr_i_0), |
.wb_dat_i_v(wb_dat_i_0), |
.wb_dat_o_v(wb_dat_o_0), |
.wb_stb_i(wb_stb_i_0), |
.wb_cyc_i(wb_cyc_i_0), |
.wb_ack_o(wb_ack_o_0), |
.wb_clk(wb_clk[0]), |
.wb_rst(wb_rst[0]), |
// SDRAM controller interface |
.sdram_dat_o(fifo_dat_o[0]), |
.sdram_fifo_empty(fifo_empty[0][0:nr_of_wb_ports_clk0-1]), |
.sdram_fifo_rd_adr(fifo_rd_adr), |
.sdram_fifo_rd_data(fifo_rd_data), |
.sdram_fifo_re(fifo_re[0][0:nr_of_wb_ports_clk0-1]), |
.sdram_dat_i(fifo_dat_i), |
.sdram_fifo_wr(fifo_wr), |
.sdram_fifo_we(fifo_we[0][0:nr_of_wb_ports_clk0-1]), |
.sdram_clk(sdram_clk), |
.sdram_rst(sdram_rst) ); |
end |
if (nr_of_wb_ports_clk0 < 16) begin |
assign fifo_empty[0][nr_of_wb_ports_clk0:15] = {(16-nr_of_wb_ports_clk0){1'b1}}; |
end |
endgenerate |
|
generate |
if (nr_of_wb_clk_domains > 1) begin |
versatile_mem_ctrl_wb |
# (.nr_of_wb_ports(nr_of_wb_ports_clk1)) |
wb1( |
// wishbone side |
.wb_adr_i_v(wb_adr_i_1), |
.wb_dat_i_v(wb_dat_i_1), |
.wb_dat_o_v(wb_dat_o_1), |
.wb_stb_i(wb_stb_i_1), |
.wb_cyc_i(wb_cyc_i_1), |
.wb_ack_o(wb_ack_o_1), |
.wb_clk(wb_clk[1]), |
.wb_rst(wb_rst[1]), |
// SDRAM controller interface |
.sdram_dat_o(fifo_dat_o[1]), |
.sdram_fifo_empty(fifo_empty[1][0:nr_of_wb_ports_clk1-1]), |
.sdram_fifo_rd_adr(fifo_rd_adr), |
.sdram_fifo_rd_data(fifo_rd_data), |
.sdram_fifo_re(fifo_re[1][0:nr_of_wb_ports_clk1-1]), |
.sdram_dat_i(fifo_dat_i), |
.sdram_fifo_wr(fifo_wr), |
.sdram_fifo_we(fifo_we[1][0:nr_of_wb_ports_clk1-1]), |
.sdram_clk(sdram_clk), |
.sdram_rst(sdram_rst) ); |
if (nr_of_wb_ports_clk1 < 16) begin |
assign fifo_empty[1][nr_of_wb_ports_clk1:15] = {(16-nr_of_wb_ports_clk1){1'b1}}; |
end |
end else begin |
assign fifo_empty[1] = {16{1'b1}}; |
assign fifo_dat_o[1] = {36{1'b0}}; |
end |
endgenerate |
|
generate |
if (nr_of_wb_clk_domains > 2) begin |
versatile_mem_ctrl_wb |
# (.nr_of_wb_ports(nr_of_wb_ports_clk1)) |
wb2( |
// wishbone side |
.wb_adr_i_v(wb_adr_i_2), |
.wb_dat_i_v(wb_dat_i_2), |
.wb_dat_o_v(wb_dat_o_2), |
.wb_stb_i(wb_stb_i_2), |
.wb_cyc_i(wb_cyc_i_2), |
.wb_ack_o(wb_ack_o_2), |
.wb_clk(wb_clk[2]), |
.wb_rst(wb_rst[2]), |
// SDRAM controller interface |
.sdram_dat_o(fifo_dat_o[2]), |
.sdram_fifo_empty(fifo_empty[2][0:nr_of_wb_ports_clk2-1]), |
.sdram_fifo_rd_adr(fifo_rd_adr), |
.sdram_fifo_rd_data(fifo_rd_data), |
.sdram_fifo_re(fifo_re[2][0:nr_of_wb_ports_clk2-1]), |
.sdram_dat_i(fifo_dat_i), |
.sdram_fifo_wr(fifo_wr), |
.sdram_fifo_we(fifo_we[2][0:nr_of_wb_ports_clk2-1]), |
.sdram_clk(sdram_clk), |
.sdram_rst(sdram_rst) ); |
if (nr_of_wb_ports_clk2 < 16) begin |
assign fifo_empty[2][nr_of_wb_ports_clk2:15] = {(16-nr_of_wb_ports_clk2){1'b1}}; |
end |
end else begin |
assign fifo_empty[2] = {16{1'b1}}; |
assign fifo_dat_o[2] = {36{1'b0}}; |
end |
endgenerate |
|
generate |
if (nr_of_wb_clk_domains > 3) begin |
versatile_mem_ctrl_wb |
# (.nr_of_wb_ports(nr_of_wb_ports_clk3)) |
wb3( |
// wishbone side |
.wb_adr_i_v(wb_adr_i_3), |
.wb_dat_i_v(wb_dat_i_3), |
.wb_dat_o_v(wb_dat_o_3), |
.wb_stb_i(wb_stb_i_3), |
.wb_cyc_i(wb_cyc_i_3), |
.wb_ack_o(wb_ack_o_3), |
.wb_clk(wb_clk[3]), |
.wb_rst(wb_rst[3]), |
// SDRAM controller interface |
.sdram_dat_o(fifo_dat_o[3]), |
.sdram_fifo_empty(fifo_empty[3][0:nr_of_wb_ports_clk3-1]), |
.sdram_fifo_rd_adr(fifo_rd_adr), |
.sdram_fifo_rd_data(fifo_rd_data), |
.sdram_fifo_re(fifo_re[3][0:nr_of_wb_ports_clk3-1]), |
.sdram_dat_i(fifo_dat_i), |
.sdram_fifo_wr(fifo_wr), |
.sdram_fifo_we(fifo_we[3][0:nr_of_wb_ports_clk3-1]), |
.sdram_clk(sdram_clk), |
.sdram_rst(sdram_rst) ); |
if (nr_of_wb_ports_clk3 < 16) begin |
assign fifo_empty[3][nr_of_wb_ports_clk3:15] = {(16-nr_of_wb_ports_clk3){1'b1}}; |
end |
end else begin |
assign fifo_empty[3] = {16{1'b1}}; |
assign fifo_dat_o[3] = {36{1'b0}}; |
end |
endgenerate |
|
encode encode0 ( |
.fifo_empty_0(fifo_empty[0]), .fifo_empty_1(fifo_empty[1]), .fifo_empty_2(fifo_empty[2]), .fifo_empty_3(fifo_empty[3]), |
.fifo_sel(fifo_sel_i), .fifo_sel_domain(fifo_sel_domain_i) |
); |
|
always @ (posedge sdram_clk or posedge sdram_rst) |
begin |
if (sdram_rst) |
{fifo_sel_reg,fifo_sel_domain_reg} <= {16'h0,2'b00}; |
else |
if (idle) |
{fifo_sel_reg,fifo_sel_domain_reg} <= {fifo_sel_i,fifo_sel_domain_i}; |
end |
|
decode decode0 ( |
.fifo_sel(fifo_sel_reg), .fifo_sel_domain(fifo_sel_domain_reg), |
.fifo_we_0(fifo_re[0]), .fifo_we_1(fifo_re[1]), .fifo_we_2(fifo_re[2]), .fifo_we_3(fifo_re[3]) |
); |
|
// fifo_re[0-3] is a one-hot read enable structure |
// fifo_empty should go active when chosen fifo queue is empty |
assign current_fifo_empty = (idle) ? (!(|fifo_sel_i)) : (|(fifo_empty[0] & fifo_re[0])) | (|(fifo_empty[1] & fifo_re[1])) | (|(fifo_empty[2] & fifo_re[2])) | (|(fifo_empty[3] & fifo_re[3])); |
|
decode decode1 ( |
.fifo_sel(fifo_sel_dly), .fifo_sel_domain(fifo_sel_domain_dly), |
.fifo_we_0(fifo_we[0]), .fifo_we_1(fifo_we[1]), .fifo_we_2(fifo_we[2]), .fifo_we_3(fifo_we[3]) |
); |
|
`ifdef SDR_16 |
|
wire ref_cnt_zero; |
reg [15:0] dq_i_reg, dq_i_tmp_reg; |
reg [17:0] dq_o_tmp_reg; |
wire cmd_aref, cmd_read; |
|
// refresch counter |
ref_counter ref_counter0( .zq(ref_cnt_zero), .rst(sdram_rst), .clk(sdram_clk)); |
always @ (posedge sdram_clk or posedge sdram_rst) |
if (sdram_rst) |
refresh_req <= 1'b0; |
else |
if (ref_cnt_zero) |
refresh_req <= 1'b1; |
else if (cmd_aref) |
refresh_req <= 1'b0; |
|
// SDR SDRAM 16 FSM |
fsm_sdr_16 # ( .ba_size(ba_size), .row_size(row_size), .col_size(col_size), .init_cl(cl)) |
fsm_sdr_16( |
.adr_i({fifo_dat_o[fifo_sel_domain_reg][ba_size+row_size+col_size+6-2:6],1'b0}), |
.we_i(fifo_dat_o[fifo_sel_domain_reg][5]), |
.bte_i(fifo_dat_o[fifo_sel_domain_reg][4:3]), |
.fifo_empty(current_fifo_empty), .fifo_rd_adr(fifo_rd_adr), .fifo_rd_data(fifo_rd_data), |
.state_idle(idle), .count0(count0), |
.refresh_req(refresh_req), |
.cmd_aref(cmd_aref), .cmd_read(cmd_read), |
.ba(ba_pad_o), .a(a_pad_o), .cmd({ras_pad_o, cas_pad_o, we_pad_o}), .dq_oe(dq_oe), |
.sdram_clk(sdram_clk), .sdram_rst(sdram_rst) |
); |
|
assign cs_pad_o = 1'b0; |
assign cke_pad_o = 1'b1; |
|
genvar i; |
generate |
for (i=0; i < 16; i=i+1) begin : dly |
|
defparam delay0.depth=cl+2; |
defparam delay0.width=1; |
delay delay0 ( |
.d(fifo_sel_reg[i]), |
.q(fifo_sel_dly[i]), |
.clk(sdram_clk), |
.rst(sdram_rst) |
); |
end |
|
defparam delay1.depth=cl+2; |
defparam delay1.width=2; |
delay delay1 ( |
.d(fifo_sel_domain_reg), |
.q(fifo_sel_domain_dly), |
.clk(sdram_clk), |
.rst(sdram_rst) |
); |
|
defparam delay2.depth=cl+2; |
defparam delay2.width=1; |
delay delay2 ( |
.d(cmd_read), |
.q(fifo_wr), |
.clk(sdram_clk), |
.rst(sdram_rst) |
); |
|
endgenerate |
|
// output registers |
assign cs_n_pad_o = 1'b0; |
assign cke_pad_o = 1'b1; |
|
always @ (posedge sdram_clk or posedge sdram_rst) |
if (sdram_rst) |
{dq_i_reg, dq_i_tmp_reg} <= {16'h0000,16'h0000}; |
else |
{dq_i_reg, dq_i_tmp_reg} <= {dq_i, dq_i_reg}; |
|
assign fifo_dat_i = {dq_i_tmp_reg, dq_i_reg}; |
|
always @ (posedge sdram_clk or posedge sdram_rst) |
if (sdram_rst) begin |
{dq_o, dqm_pad_o} <= {16'h0000,2'b00}; |
dq_o_tmp_reg <= 18'h0; |
end else |
if (~count0) begin |
dq_o <= fifo_dat_o[fifo_sel_domain_reg][35:20]; |
dq_o_tmp_reg[17:2] <= fifo_dat_o[fifo_sel_domain_reg][19:4]; |
if (cmd_read) |
dqm_pad_o <= 2'b00; |
else |
dqm_pad_o <= ~fifo_dat_o[fifo_sel_domain_reg][3:2]; |
if (cmd_read) |
dq_o_tmp_reg[1:0] <= 2'b00; |
else |
dq_o_tmp_reg[1:0] <= ~fifo_dat_o[fifo_sel_domain_reg][1:0]; |
end else |
{dq_o,dqm_pad_o} <= dq_o_tmp_reg; |
|
|
`endif // `ifdef SDR_16 |
|
|
`ifdef DDR_16 |
wire read, write; |
wire sdram_clk_90, sdram_clk_180, sdram_clk_270; |
wire ck_fb; |
reg cke, ras, cas, we, cs_n; |
wire ras_o, cas_o, we_o, cs_n_o; |
wire [1:0] ba_o; |
wire [12:0] addr_o; |
reg [1:0] ba; |
reg [12:0] addr; |
wire dq_en, dqm_en; |
reg [15:0] dq_tx_reg; |
wire [15:0] dq_tx; |
reg [31:0] dq_rx_reg; |
wire [31:0] dq_rx; |
wire [15:0] dq_o; |
reg [3:0] dqm_tx_reg; |
wire [3:0] dqm_tx; |
wire [1:0] dqm_o, dqs_o, dqs_n_o; |
wire ref_delay, ref_delay_ack; |
wire bl_en, bl_ack; |
wire tx_fifo_re_i; |
wire adr_init_delay; |
reg adr_init_delay_i; |
reg [3:0] burst_cnt; |
wire [3:0] burst_next_cnt, burst_length; |
wire burst_mask; |
wire [12:0] cur_row; |
|
// DDR SDRAM 16 FSM |
ddr_16 ddr_16_0 |
( |
.adr_init(adr_init), |
.fifo_re(tx_fifo_re_i), |
.fifo_re_d(tx_fifo_re), |
.tx_fifo_dat_o(tx_fifo_dat_o), |
.burst_adr(burst_adr), |
.fifo_empty(tx_fifo_empty), |
.fifo_sel(tx_fifo_b_sel_i_cur), |
.read(read), |
.write(write), |
.ref_req(ref_req), |
.ref_ack(ref_ack), |
.ref_delay(ref_delay), |
.ref_delay_ack(ref_delay_ack), |
.bl_en(bl_en), |
.bl_ack(bl_ack), |
.a({ba_o,addr_o}), |
.cmd({ras_o,cas_o,we_o}), |
.cs_n(cs_n_o), |
.cur_row(cur_row), |
.sdram_clk(sdram_clk_0), |
.wb_rst(wb_rst) |
); |
|
inc_adr inc_adr0 |
( |
.adr_i(tx_fifo_dat_o[9:6]), |
.bte_i(tx_fifo_dat_o[4:3]), |
.cti_i(tx_fifo_dat_o[2:0]), |
.init(adr_init), |
.inc(), |
.adr_o(burst_adr), |
.done(done), |
.clk(sdram_clk_0), |
.rst(wb_rst) |
); |
|
// Delay, refresh to activate/refresh |
ref_delay_counter ref_delay_counter0 |
( |
.cke(ref_delay), |
.zq(ref_delay_ack), |
.clk(sdram_clk_0), |
.rst(wb_rst) |
); |
|
// Burst length, DDR2 SDRAM |
burst_length_counter burst_length_counter0 |
( |
.cke(bl_en), |
.zq(bl_ack), |
.clk(sdram_clk_0), |
.rst(wb_rst) |
); |
|
// Wishbone burst length |
assign burst_length = (adr_init && tx_fifo_dat_o[2:0] == 3'b000) ? 4'd1 : // classic cycle |
(adr_init && tx_fifo_dat_o[2:0] == 3'b010) ? 4'd4 : // incremental burst cycle |
burst_length; |
|
// Burst mask |
// Burst length counter |
assign burst_next_cnt = (burst_cnt == 3) ? 4'd0 : burst_cnt + 4'd1; |
always @ (posedge sdram_clk_0 or posedge wb_rst) |
if (wb_rst) |
burst_cnt <= 4'h0; |
else |
if (~count0) |
{dq_o,dqm_pad_o} <= {fifo_dat_o[fifo_sel_domain_reg][35:20],~fifo_dat_o[fifo_sel_domain_reg][3:2]}; |
else |
{dq_o,dqm_pad_o} <= {fifo_dat_o[fifo_sel_domain_reg][19:4],~fifo_dat_o[fifo_sel_domain_reg][1:0]}; |
endmodule |
if (bl_en) |
burst_cnt <= burst_next_cnt; |
// Burst Mask |
assign burst_mask = (burst_cnt >= burst_length) ? 1'b1 : 1'b0; |
|
// Control outports, DDR2 SDRAM |
always @ (posedge sdram_clk_180 or posedge wb_rst) |
if (wb_rst) begin |
cs_n <= 1'b0; |
cke <= 1'b0; |
ras <= 1'b0; |
cas <= 1'b0; |
we <= 1'b0; |
ba <= 2'b00; |
addr <= 13'b0000000000000; |
end |
else begin |
cs_n <= cs_n_o; |
cke <= 1'b1; |
ras <= ras_o; |
cas <= cas_o; |
we <= we_o; |
ba <= ba_o; |
addr <= addr_o; |
end |
|
assign cke_pad_o = cke; |
assign ras_pad_o = ras; |
assign cas_pad_o = cas; |
assign we_pad_o = we; |
assign ba_pad_o = ba; |
assign addr_pad_o = addr; |
assign cs_n_pad_o = cs_n; |
|
|
// Read latency, delay the control signals to fit latency of the DDR2 SDRAM |
defparam delay0.depth=`CL+`AL+2; |
defparam delay0.width=4; |
delay delay0 ( |
.d({read && !burst_mask,tx_fifo_b_sel_i_cur}), |
.q({rx_fifo_we,rx_fifo_a_sel_i}), |
.clk(sdram_clk_0), |
.rst(wb_rst) |
); |
|
// write latency, delay the control signals to fit latency of the DDR2 SDRAM |
defparam delay1.depth=`CL+`AL-1; |
defparam delay1.width=2; |
delay delay1 ( |
.d({write, burst_mask}), |
.q({dq_en, dqm_en}), |
.clk(sdram_clk_270), |
.rst(wb_rst) |
); |
|
// if CL>3 delay read from Tx FIFO |
defparam delay2.depth=`CL+`AL-3; |
defparam delay2.width=1; |
delay delay2 ( |
.d(tx_fifo_re_i && !burst_mask), |
.q(tx_fifo_re), |
.clk(sdram_clk_0), |
.rst(wb_rst) |
); |
|
// if CL=3, no delay |
//assign tx_fifo_re = tx_fifo_re_i && !burst_mask; |
|
// Increment address |
defparam delay3.depth=`CL+`AL-1; |
defparam delay3.width=1; |
delay delay3 ( |
.d({write|read}), |
.q({adr_inc}), |
.clk(sdram_clk_0), |
.rst(wb_rst) |
); |
|
// DCM/PLL with internal and external feedback |
// Remove skew from internal and external clock |
// Parameters are set in dcm_pll.v |
dcm_pll dcm_pll_0 ( |
.rst(wb_rst), |
.clk_in(sdram_clk), |
.clkfb_in(ck_fb_pad_i), |
.clk0_out(sdram_clk_0), |
.clk90_out(sdram_clk_90), |
.clk180_out(sdram_clk_180), |
.clk270_out(sdram_clk_270), |
.clkfb_out(ck_fb) |
); |
|
// DDR2 IF |
versatile_mem_ctrl_ddr versatile_mem_ctrl_ddr_0 ( |
// DDR2 SDRAM ports |
.ck_o(ck_pad_o), |
.ck_n_o(ck_n_pad_o), |
.dq_io(dq_pad_io), |
.dqs_io(dqs_pad_io), |
.dqs_n_io(dqs_n_pad_io), |
.dm_rdqs_io(dm_rdqs_pad_io), |
// Memory controller side |
.tx_dat_i(tx_fifo_dat_o), |
.rx_dat_o(rx_fifo_dat_i), |
.dq_en(dq_en), |
.dqm_en(dqm_en), |
.wb_rst(wb_rst), |
.sdram_clk_0(sdram_clk_0), |
.sdram_clk_90(sdram_clk_90), |
.sdram_clk_180(sdram_clk_180), |
.sdram_clk_270(sdram_clk_270)); |
|
// Assing outputs |
// Non-DDR outputs |
assign ba_pad_o = ba; |
assign addr_pad_o = addr; |
assign dqs_oe = dq_en; |
assign cke_pad_o = cke; |
assign ras_pad_o = ras; |
assign cas_pad_o = cas; |
assign we_pad_o = we; |
assign cs_n_pad_o = cs_n; |
assign ck_fb_pad_o = ck_fb; |
|
`endif // `ifdef DDR_16 |
|
endmodule // wb_sdram_ctrl_top |
/trunk/rtl/verilog/Makefile
1,61 → 1,64
svn_export: versatile_fifo_dual_port_ram.v versatile_fifo_async_cmp.v |
VERSATILE_FIFO_PROJECT_FILES =versatile_fifo_dual_port_ram.v |
VERSATILE_FIFO_PROJECT_FILES +=versatile_fifo_async_cmp.v |
VERSATILE_FIFO_PROJECT_FILES +=dff_sr.v |
VERSATILE_FIFO_PROJECT_FILES +=async_fifo_mq.v |
VERSATILE_FIFO_PROJECT_FILES +=async_fifo_mq_md.v |
VERSATILE_FIFO_PROJECT_FILES +=versatile_fifo_dual_port_ram_dc_sw.v |
|
versatile_fifo_dual_port_ram.v: |
svn export http://opencores.org/ocsvn/versatile_fifo/versatile_fifo/trunk/rtl/verilog/versatile_fifo_dual_port_ram.v |
$(VERSATILE_FIFO_PROJECT_FILES): |
svn export http://opencores.org/ocsvn/versatile_fifo/versatile_fifo/trunk/rtl/verilog/$@ |
|
dff_sr.v: |
svn export http://opencores.org/ocsvn/versatile_fifo/versatile_fifo/trunk/rtl/verilog/dff_sr.v |
VERSATILE_COUNTER_PROJECT_FILES =versatile_counter_generator.php |
VERSATILE_COUNTER_PROJECT_FILES +=CSV.class.php |
|
versatile_fifo_async_cmp.v: dff_sr.v |
svn export http://opencores.org/ocsvn/versatile_fifo/versatile_fifo/trunk/rtl/verilog/versatile_fifo_async_cmp.v |
$(VERSATILE_COUNTER_PROJECT_FILES): |
svn export http://opencores.org/ocsvn/versatile_counter/versatile_counter/trunk/rtl/verilog/$@ |
|
async_fifo_mq.v: |
svn export http://opencores.org/ocsvn/versatile_fifo/versatile_fifo/trunk/rtl/verilog/async_fifo_mq.v |
|
async_fifo_mq_md.v: |
svn export http://opencores.org/ocsvn/versatile_fifo/versatile_fifo/trunk/rtl/verilog/async_fifo_mq_md.v |
|
versatile_counter_generator.php: |
svn export http://opencores.org/ocsvn/versatile_counter/versatile_counter/trunk/rtl/verilog/versatile_counter_generator.php |
|
CSV.class.php: |
svn export http://opencores.org/ocsvn/versatile_counter/versatile_counter/trunk/rtl/verilog/CSV.class.php |
|
versatile_fifo_dual_port_ram_dc_dw.v: versatile_fifo_dual_port_ram.v |
vppreproc +define+TYPE+"dc_dw" +define+DC +define+DW +define+DATA_WIDTH+36 +define+ADDR_WIDTH+8 --simple versatile_fifo_dual_port_ram.v > versatile_fifo_dual_port_ram_dc_dw.v |
|
versatile_fifo_dual_port_ram_dc_sw.v: |
svn export http://opencores.org/ocsvn/versatile_fifo/versatile_fifo/trunk/rtl/verilog/versatile_fifo_dual_port_ram_dc_sw.v |
# These rules will generate counters as they're required, but some CSVs stil hang around (the ones we don't use, ironically.) |
counter_csvs:versatile_counter.xls versatile_counter_generator.php CSV.class.php |
excel2csv $< -S , |
|
versatile_counter: versatile_counter_generator.php CSV.class.php |
excel2csv versatile_counter.xls -S , |
./versatile_counter_generator.php gray_counter.csv > gray_counter.v |
./versatile_counter_generator.php ctrl_counter.csv > ctrl_counter.v |
./versatile_counter_generator.php ref_counter.csv > ref_counter.v |
./versatile_counter_generator.php ref_delay_counter.csv > ref_delay_counter.v |
./versatile_counter_generator.php pre_delay_counter.csv > pre_delay_counter.v |
./versatile_counter_generator.php burst_length_counter.csv > burst_length_counter.v |
%.csv: |
$(MAKE) counter_csvs |
|
%.v: %.csv |
@if [ ! -e $< ]; then ls $<; fi |
./versatile_counter_generator.php $^ > $@ |
|
fifo_fill.v: fifo_fill.fzm |
perl fizzim.pl -encoding onehot < fifo_fill.fzm > fifo_fill.v |
|
ddr_16.v: ddr_16.fzm ddr_16_defines.v |
perl fizzim.pl -encoding onehot < ddr_16.fzm > tmp1.v |
vppreproc --simple tmp1.v > ddr_16.v |
ddr_16_generated.v: ddr_16.fzm ddr_16_defines.v |
perl fizzim.pl -encoding onehot < ddr_16.fzm > $@ |
|
versatile_mem_ctrl_ip.v: versatile_fifo_async_cmp.v versatile_fifo_dual_port_ram_dc_dw.v fifo_adr_counter.v ctrl_counter.v ref_counter.v ref_delay_counter.v pre_delay_counter.v burst_length_counter.v fifo.v fifo_fill.v inc_adr.v sdr_16.v ddr_16.v delay.v ddr_ff.v dcm_pll.v dff_sr.v versatile_mem_ctrl_ddr.v versatile_mem_ctrl_top.v |
cat versatile_fifo_async_cmp.v versatile_fifo_dual_port_ram_dc_dw.v fifo_adr_counter.v ctrl_counter.v fifo.v fifo_fill.v inc_adr.v ref_counter.v ref_delay_counter.v pre_delay_counter.v burst_length_counter.v sdr_16.v ddr_16.v delay.v ddr_ff.v dcm_pll.v dff_sr.v versatile_mem_ctrl_ddr.v versatile_mem_ctrl_top.v | cat copyright.v - > versatile_mem_ctrl_ip.v |
ddr_16.v: ddr_16_generated.v |
vppreproc --simple $^ > $@ |
|
all: svn_export versatile_fifo_dual_port_ram_dc_dw.v versatile_counter fifo_fill.v sdr_16.v ddr_16.v versatile_mem_ctrl_ip.v |
fifo_adr_counter.v: |
@echo;echo "\tThis file,"$@", doesn't exist, is it still needed?!. \n\tMake will now stop";echo |
ls notexisting |
|
sdr_16.v: versatile_fifo_async_cmp.v versatile_fifo_dual_port_ram_dc_sw.v async_fifo_mq.v versatile_counter |
vppreproc --simple +define+SDR_16 delay.v codec.v gray_counter.v async_fifo_mq.v egress_fifo.v versatile_fifo_dual_port_ram_dc_sw.v dff_sr.v versatile_fifo_async_cmp.v ref_counter.v fsm_sdr_16.v versatile_mem_ctrl_wb.v versatile_mem_ctrl_top.v > sdr_16.v |
VERSATILE_MEM_CTRL_IP_FILES=versatile_fifo_async_cmp.v versatile_fifo_dual_port_ram_dc_dw.v fifo_adr_counter.v ctrl_counter.v fifo.v fifo_fill.v inc_adr.v ref_counter.v ref_delay_counter.v pre_delay_counter.v burst_length_counter.v sdr_16.v ddr_16.v delay.v ddr_ff.v dcm_pll.v dff_sr.v versatile_mem_ctrl_ddr.v versatile_mem_ctrl_top.v |
|
all: sdr_16.v |
versatile_mem_ctrl_ip.v: $(VERSATILE_MEM_CTRL_IP_FILES) |
cat $^ | cat copyright.v - > $@ |
|
# SDRAM 16-bit wide databus dependency files - force a recompile |
SDR_16_FILES=versatile_fifo_async_cmp.v async_fifo_mq.v delay.v codec.v gray_counter.v egress_fifo.v versatile_fifo_dual_port_ram_dc_sw.v dff_sr.v versatile_fifo_async_cmp.v ref_counter.v fsm_sdr_16.v versatile_mem_ctrl_wb.v versatile_mem_ctrl_top.v |
sdr_16.v: $(SDR_16_FILES) |
vppreproc --simple +define+SDR_16 $^ > $@ |
|
# the single all rule |
all: versatile_fifo_dual_port_ram.v versatile_fifo_async_cmp.v versatile_fifo_dual_port_ram_dc_dw.v counter_csvs fifo_fill.v sdr_16.v ddr_16.v versatile_mem_ctrl_ip.v |
|
|
clean: |
rm -rf versatile_fifo_dual_port_ram_dc_dw.v versatile_fifo_async_cmp.v |
rm -rf $(VERSATILE_FIFO_PROJECT_FILES) $(VERSATILE_COUNTER_PROJECT_FILES) |
rm -rf fifo_fill.v sdr_16.v ddr_16.v |
rm -f versatile_fifo_dual_port_ram_dc_dw.v ddr_16_generated.v |
rm -rf *_counter.v |
rm -rf *.csv |
rm -rf *~ |