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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [orpsocv2/] [boards/] [actel/] [ordb1a3pe1500/] [rtl/] [verilog/] [versatile_mem_ctrl/] [rtl/] [verilog/] [versatile_mem_ctrl_ip.v] - Rev 411

Compare with Previous | Blame | View Log

//////////////////////////////////////////////////////////////////////
////                                                              ////
////  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;   
 
`ifndef GENERATE_DIRECTION_AS_LATCH   
   wire direction;
`endif
`ifdef GENERATE_DIRECTION_AS_LATCH
   reg direction;
`endif
   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
// async FIFO with multiple queues
 
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
 
// and-or mux write address
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
 
// and-or mux read address
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
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] /*synthesis syn_ramstyle = "no_rw_check"*/;
   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 = 2;
   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 == wrap_value) ? {length{1'b0}} :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
 `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 state_idle,
  output reg write,
  input wire bl_ack,
  input wire [3:0] burst_adr,
  input wire clk,
  input wire fifo_empty,
  input wire fifo_re_d,
  input wire [2:0] fifo_sel,
  input wire ref_delay_ack,
  input wire ref_req,
  input wire rst,
  input wire [35:0] tx_fifo_dat_o 
);
  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; 
    state_idle = 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;
        state_idle = 1'b1;
        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;
        fifo_re = 1'b1;
        begin
          nextstate[NOP22] = 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;
        fifo_re = 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 
        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;
        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;
        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 clk or posedge rst) begin
    if (rst)
      state <= 43'b0000000000000000000000000000000000000000001 << IDLE;
    else
      state <= nextstate;
  end
  always @(posedge clk or posedge rst) begin
    if (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
module fsm_wb (
	       stall_i, stall_o,
	       we_i, cti_i, bte_i, stb_i, cyc_i, ack_o,
	       egress_fifo_we, egress_fifo_full,
	       ingress_fifo_re, ingress_fifo_empty,
	       state_idle,
	       sdram_burst_reading,
	       debug_state,
	       wb_clk, wb_rst
	       );
 
   input stall_i;
   output stall_o;
 
   input [2:0] cti_i;
   input [1:0] bte_i;
   input       we_i, stb_i, cyc_i;
   output      ack_o;
   output      egress_fifo_we, ingress_fifo_re;
   input       egress_fifo_full, ingress_fifo_empty;
   input       sdram_burst_reading;
   output      state_idle;
   input       wb_clk, wb_rst;
   output [1:0] debug_state;
 
 
 
   reg 	       ingress_fifo_read_reg;
 
   // bte
   parameter linear       = 2'b00;
   parameter wrap4        = 2'b01;
   parameter wrap8        = 2'b10;
   parameter wrap16       = 2'b11;
   // cti
   parameter classic      = 3'b000;
   parameter endofburst   = 3'b111;
 
   parameter idle = 2'b00;
   parameter rd   = 2'b01;
   parameter wr   = 2'b10;
   parameter fe   = 2'b11;
   reg [1:0]   state;
 
   assign debug_state = state;
 
 
   reg 	       sdram_burst_reading_1, sdram_burst_reading_2;
   wire        sdram_burst_reading_wb_clk;
 
 
   always @ (posedge wb_clk or posedge wb_rst)
     if (wb_rst)
       state <= idle;
     else
       case (state)
         idle:
           if (we_i & stb_i & cyc_i & !egress_fifo_full & !stall_i)
             state <= wr;
           else if (!we_i & stb_i & cyc_i & !egress_fifo_full & !stall_i)
             state <= rd;
         wr:
           if ((cti_i==classic | cti_i==endofburst | bte_i==linear) & 
	       stb_i & cyc_i & !egress_fifo_full & !stall_i)
             state <= idle;
         rd:
           if ((cti_i==classic | cti_i==endofburst | bte_i==linear) & 
	       stb_i & cyc_i & ack_o)
             state <= fe;
         fe:
           if (ingress_fifo_empty & !sdram_burst_reading_wb_clk)
             state <= idle;
         default: ;
       endcase
 
   assign state_idle = (state==idle);
 
   assign stall_o = (stall_i) ? 1'b1 :
                    (state==idle & stb_i & cyc_i & !egress_fifo_full) ? 1'b1 :
                    (state==wr   & stb_i & cyc_i & !egress_fifo_full) ? 1'b1 :
                    (state==rd   & stb_i & cyc_i & !ingress_fifo_empty) ? 1'b1 :
                    (state==fe   & !ingress_fifo_empty) ? 1'b1 :
                    1'b0;
 
   assign egress_fifo_we = (state==idle & stb_i & cyc_i & !egress_fifo_full & !stall_i) ? 1'b1 :
                           (state==wr   & stb_i & cyc_i & !egress_fifo_full & !stall_i) ? 1'b1 :
                           1'b0;
 
   assign ingress_fifo_re = (state==rd & stb_i & cyc_i & !ingress_fifo_empty & !stall_i) ? 1'b1 :
                            (state==fe & !ingress_fifo_empty & !stall_i) ? 1'b1:
                            1'b0;
 
   always @ (posedge wb_clk or posedge wb_rst)
     if (wb_rst)
       ingress_fifo_read_reg <= 1'b0;
     else
       ingress_fifo_read_reg <= ingress_fifo_re;
 
   /*assign ack_o = (ingress_fifo_read_reg & stb_i) ? 1'b1 :
                  (state==fe) ? 1'b0 :
                  (state==wr & stb_i & cyc_i & !egress_fifo_full & !stall_i) ? 1'b1 :
                  1'b0;*/
 
   assign ack_o = !(state==fe) & ((ingress_fifo_read_reg & stb_i) | (state==wr & stb_i & cyc_i & !egress_fifo_full & !stall_i));
 
 
   // Sample the SDRAM burst reading signal in WB domain
   always @(posedge wb_clk)
     sdram_burst_reading_1 <= sdram_burst_reading;
 
   always @(posedge wb_clk)
     sdram_burst_reading_2 <= sdram_burst_reading_1;
 
   assign sdram_burst_reading_wb_clk = sdram_burst_reading_2;
 
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,
  rst, clk_0, clk_90, clk_180, 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 [31:0] rx_dat_o;
  input         dq_en;
  input         dqm_en;
  input         rst;
  input         clk_0;
  input         clk_90;
  input         clk_180;
  input         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(clk_0),
    .C1(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(clk_0),
    .C1(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(clk_0),
        .C1(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(clk_0),
        .C1(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 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(clk_270),
        .C1(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 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 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(clk_270),
        .C1(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(clk_270), 
        .C1(clk_90),
        .CE(1'b1), 
        .D(dq_io[i]),   
        .R(wb_rst),  
        .S(1'b0));
    end
  endgenerate
 
  // Data to Rx FIFO
  always @ (posedge 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 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;
`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 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 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;
 
`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 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 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 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[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(clk_270),
        .C1(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(clk_270),
        .C1(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(clk_270), 
        .C1(clk_90),
        .CE(1'b1), 
        .D(dq_io[i]),   
        .R(wb_rst),  
        .S(1'b0));
    end
  endgenerate
 
  // Data to Rx FIFO
  always @ (posedge 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;
`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
 
 
//
// Specify either type of memory
// or
// BA_SIZE, ROW_SIZE, COL_SIZE and SDRAM_DATA_WIDTH
//
// either in this file or as command line option; +define+MT48LC16M16
//
 
// number of adr lines to use
// 2^2 = 4 32 bit word burst
//`define BURST_SIZE 2
 
 
// DDR2 SDRAM
// MT47H32M16 – 8 Meg x 16 x 4 banks
`define MT47H32M16
`ifdef MT47H32M16
// using 1 of MT47H32M16
// SDRAM data width is 16
`define BURST_SIZE 4  
`define SDRAM_DATA_WIDTH 16
`define COL_SIZE 10  
`define ROW_SIZE 13
`define BA_SIZE 2
 
`define SDRAM16
`define BA tx_fifo_dat_o[28:27]
`define ROW tx_fifo_dat_o[26:14]
`define COL {4'b0000,tx_fifo_dat_o[13:10],burst_adr,1'b0}
`define WORD_SIZE 1
`define WB_ADR_HI 24
`define WB_ADR_LO 2
 
// Mode Register (MR) Definition
// [16]    (BA2)   1'b0
// [15:14] (BA1-0) Mode Register Definition (MR): 2'b00 - Mode Register (MR)
// [13]    (A13)   1'b0
// [12]    (A12)   PD Mode (PD): 1'b0 - Fast exit (normal), 1'b1 - Slow exit (low power)
// [11:9]  (A11-9) Write Recovery (WR): 3'b000 - reserved, 3b'001 - 2, ... , 3b'111 - 8
// [8]     (A8)    DLL Reset (DLL): 1'b0 - No, 1'b1 - Yes
// [7]     (A7)    Mode (TM): 1'b0 - Normal, 1'b1 - Test
// [6:4]   (A5-4)  CAS Latency (CL): 3'b011 - 3, ... , 3'b111 - 7
// [3]     (A3)    Burst Type (BT): 1'b0 - Sequential, 1'b1 - Interleaved
// [2:0]   (A2-0)  Burst Length (BL): 3'b010 - 4, 3'b011 - 8
`define MR  2'b00
`define PD  1'b0
`define WR  3'b001
`define DLL 1'b0
`define DLL_RST 1'b1
`define TM  1'b0
`define CL  3'b100
`define BT  1'b0
`define BL  3'b011
 
// Extended Mode Register (EMR) Definition
// [16]    (BA2)    1'b0
// [15:14] (BA1-0)  Mode Register Set (MRS): 2'b01 - Extended Mode Register (EMR)
// [13]    (A13)    1'b0
// [12]    (A12)    Outputs (OUT): 1'b0 - Enabled, 1'b1 - Disabled
// [11]    (A11)    RDQS Enable (RDQS): 1'b0 - Enabled, 1'b1 - Disabled
// [10]    (A10)    DQS# Enable (DQS): 1'b0 - Enabled, 1'b1 - Disabled
// [9:7]   (A9-7)   OCD Opearation (OCD): 3'b000 - OCD exit, 3b'111 - Enable OCD defaults
// [6,2]   (A6, A2) RTT Nominal (RTT6,2): 2'b00 - Disabled, 2'b01 - 75 ohm, 
//                                        2'b10 - 150 ohm, 2'b11 - 50 ohm,
// [5:3]   (A5-3)   Posted CAS# Additive Latenct (AL): 3'b000 - 0, ... , 3'b110 - 6
// [1]     (A1)     Output Drive Strength (ODS): 1'b0 - Full, 1'b1 - Reduced
// [0]     (A0)     DLL Enable (DLL_EN): 1'b0 - Enable (normal), 1'b1 - Disable (test/debug)
`define MRS    2'b01
`define OUT    1'b0
`define RDQS   1'b0
`define DQS    1'b0
`define OCD    3'b000
`define OCD_DEFAULT 3'b111
`define RTT6   1'b0
`define RTT2   1'b0
`define AL     3'b000
`define ODS    1'b0
`define DLL_EN 1'b0
 
// Extended Mode Register 2 (EMR2) Definition
// [16]    (BA2)    1'b0
// [15:14] (BA1-0)  Mode Register Set (MRS2): 2'b10 - Extended Mode Register 2 (EMR2)
// [13:8]  (A13-8)  6'b000000
// [7]     (A7)     SRT Enable (SRT): 1'b0 - 1x refresh rate (0 - 85 C), 
//                                    1'b1 - 2x refresh rate (> 85 C)
// [6:0]   (A6-0)   7'b0000000
`define MRS2 2'b10
`define SRT  1'b0
 
// Extended Mode Register 3 (EMR3) Definition
// [16]    (BA2)    1'b0
// [15:14] (BA1-0)  Mode Register Set (MRS): 2'b11 - Extended Mode Register 2 (EMR2)
// [13:0]  (A13-0)  14'b00000000000000
`define MRS3 2'b11
 
// Addr to SDRAM {ba[1:0],a[12:0]}
`define A_LMR     {`MR,`PD,`WR,`DLL,`TM,`CL,`BT,`BL}
`define A_LMR_DLL_RST {`MR,`PD,`WR,`DLL_RST,`TM,`CL,`BT,`BL}
`define A_LEMR    {`MRS,`OUT,`RDQS,`DQS,`OCD,`RTT6,`AL,`RTT2,`ODS,`DLL_EN}
`define A_LEMR_OCD_DEFAULT {`MRS,`OUT,`RDQS,`DQS,`OCD_DEFAULT,`RTT6,`AL,`RTT2,`ODS,`DLL}
`define A_LEMR2   {`MRS2,5'b00000,`SRT,7'b0000000}
`define A_LEMR3   {`MRS3,13'b0000000000000}
`define A_PRE     {2'b00,13'b0010000000000}
`define A_ACT     {`BA,`ROW}
`define A_READ    {`BA,`COL}
`define A_WRITE   {`BA,`COL}
`define A_DEFAULT {2'b00,13'b0000000000000}
 
// Command
`define CMD {ras, cas, we}
`define CMD_NOP   3'b111
`define CMD_AREF  3'b001
`define CMD_LMR   3'b000
`define CMD_LEMR  3'b000
`define CMD_LEMR2 3'b000
`define CMD_LEMR3 3'b000
`define CMD_PRE   3'b010
`define CMD_ACT   3'b011
`define CMD_READ  3'b101
`define CMD_WRITE 3'b100
`define CMD_BT    3'b110
 
`endif //  `ifdef MT47H32M16
 
//
// Specify either type of memory
// or
// BA_SIZE, ROW_SIZE, COL_SIZE and SDRAM_DATA_WIDTH
//
// either in this file or as command line option; +define+MT48LC16M16
//
 
// Most of these defines have an effect on things in fsm_sdr_16.v
 
//`define MT48LC32M16   // 64MB part
`define MT48LC16M16   // 32MB part
//`define MT48LC4M16    //  8MB part
 
// Define this to allow indication that a burst read is still going
// to the wishbone state machine, so it doesn't start emptying the
// ingress fifo after a aborted burst before the burst read is
// actually finished.
`define SDRAM_WB_SAME_CLOCKS
 
// If intending to burst write, and the wishbone clock is about 1/4 the speed
// of the SDRAM clock, then the data may come late, and this triggers a bug
// during write. To avoid this we can just wait a little longer for data when
// burst reading (there's no almost_empty signal from the FIFO)
`define SLOW_WB_CLOCK
 
 
`ifdef MT48LC32M16
// using 1 of MT48LC32M16
// SDRAM data width is 16
 
`define SDRAM_DATA_WIDTH 16
`define COL_SIZE 10
`define ROW_SIZE 13
`define BA_SIZE 2
 
`endif //  `ifdef MT48LC16M16
 
`ifdef MT48LC16M16
// using 1 of MT48LC16M16
// SDRAM data width is 16
 
`define SDRAM_DATA_WIDTH 16
`define COL_SIZE 9  
`define ROW_SIZE 13
`define BA_SIZE 2
 
`endif //  `ifdef MT48LC16M16
 
`ifdef MT48LC4M16
// using 1 of MT48LC4M16
// SDRAM data width is 16
 
`define SDRAM_DATA_WIDTH 16
`define COL_SIZE 8  
`define ROW_SIZE 12
`define BA_SIZE 2
 
`endif //  `ifdef MT48LC4M16
 
// LMR
// [12:10] reserved
// [9]     WB, write burst; 0 - programmed burst length, 1 - single location
// [8:7]   OP Mode, 2'b00
// [6:4]   CAS Latency; 3'b010 - 2, 3'b011 - 3
// [3]     BT, Burst Type; 1'b0 - sequential, 1'b1 - interleaved
// [2:0]   Burst length; 3'b000 - 1, 3'b001 - 2, 3'b010 - 4, 3'b011 - 8, 3'b111 - full page
`define INIT_WB 1'b0
`define INIT_CL 3'b010
`define INIT_BT 1'b0
`define INIT_BL 3'b001
`timescale 1ns/1ns
module encode (
    fifo_empty_0, fifo_empty_1, fifo_empty_2, fifo_empty_3,
    fifo_sel, fifo_sel_domain
);
 
input  [0:15] fifo_empty_0, fifo_empty_1, fifo_empty_2, fifo_empty_3;
output [0:15] fifo_sel;
output [1:0]  fifo_sel_domain;
 
function [0:15] encode;
input [0:15] a;
input [0:15] b;
input [0:15] c;
input [0:15] d;
integer i;
begin
    if (!(&d))
        casex (d)
        16'b0xxxxxxxxxxxxxxx: encode = 16'b1000000000000000;
        16'b10xxxxxxxxxxxxxx: encode = 16'b0100000000000000;
        16'b110xxxxxxxxxxxxx: encode = 16'b0010000000000000;
        16'b1110xxxxxxxxxxxx: encode = 16'b0001000000000000;
        16'b11110xxxxxxxxxxx: encode = 16'b0000100000000000;
        16'b111110xxxxxxxxxx: encode = 16'b0000010000000000;
        16'b1111110xxxxxxxxx: encode = 16'b0000001000000000;
        16'b11111110xxxxxxxx: encode = 16'b0000000100000000;
        16'b111111110xxxxxxx: encode = 16'b0000000010000000;
        16'b1111111110xxxxxx: encode = 16'b0000000001000000;
        16'b11111111110xxxxx: encode = 16'b0000000000100000;
        16'b111111111110xxxx: encode = 16'b0000000000010000;
        16'b1111111111110xxx: encode = 16'b0000000000001000;
        16'b11111111111110xx: encode = 16'b0000000000000100;
        16'b111111111111110x: encode = 16'b0000000000000010;
        16'b1111111111111110: encode = 16'b0000000000000001;
        default:              encode = 16'b0000000000000000;
        endcase
    else if (!(&c))
        casex (c)
        16'b0xxxxxxxxxxxxxxx: encode = 16'b1000000000000000;
        16'b10xxxxxxxxxxxxxx: encode = 16'b0100000000000000;
        16'b110xxxxxxxxxxxxx: encode = 16'b0010000000000000;
        16'b1110xxxxxxxxxxxx: encode = 16'b0001000000000000;
        16'b11110xxxxxxxxxxx: encode = 16'b0000100000000000;
        16'b111110xxxxxxxxxx: encode = 16'b0000010000000000;
        16'b1111110xxxxxxxxx: encode = 16'b0000001000000000;
        16'b11111110xxxxxxxx: encode = 16'b0000000100000000;
        16'b111111110xxxxxxx: encode = 16'b0000000010000000;
        16'b1111111110xxxxxx: encode = 16'b0000000001000000;
        16'b11111111110xxxxx: encode = 16'b0000000000100000;
        16'b111111111110xxxx: encode = 16'b0000000000010000;
        16'b1111111111110xxx: encode = 16'b0000000000001000;
        16'b11111111111110xx: encode = 16'b0000000000000100;
        16'b111111111111110x: encode = 16'b0000000000000010;
        16'b1111111111111110: encode = 16'b0000000000000001;
        default:              encode = 16'b0000000000000000;
        endcase
    else if (!(&b))
        casex (b)
        16'b0xxxxxxxxxxxxxxx: encode = 16'b1000000000000000;
        16'b10xxxxxxxxxxxxxx: encode = 16'b0100000000000000;
        16'b110xxxxxxxxxxxxx: encode = 16'b0010000000000000;
        16'b1110xxxxxxxxxxxx: encode = 16'b0001000000000000;
        16'b11110xxxxxxxxxxx: encode = 16'b0000100000000000;
        16'b111110xxxxxxxxxx: encode = 16'b0000010000000000;
        16'b1111110xxxxxxxxx: encode = 16'b0000001000000000;
        16'b11111110xxxxxxxx: encode = 16'b0000000100000000;
        16'b111111110xxxxxxx: encode = 16'b0000000010000000;
        16'b1111111110xxxxxx: encode = 16'b0000000001000000;
        16'b11111111110xxxxx: encode = 16'b0000000000100000;
        16'b111111111110xxxx: encode = 16'b0000000000010000;
        16'b1111111111110xxx: encode = 16'b0000000000001000;
        16'b11111111111110xx: encode = 16'b0000000000000100;
        16'b111111111111110x: encode = 16'b0000000000000010;
        16'b1111111111111110: encode = 16'b0000000000000001;
        default:              encode = 16'b0000000000000000;
        endcase
    else
        casex (a)
        16'b0xxxxxxxxxxxxxxx: encode = 16'b1000000000000000;
        16'b10xxxxxxxxxxxxxx: encode = 16'b0100000000000000;
        16'b110xxxxxxxxxxxxx: encode = 16'b0010000000000000;
        16'b1110xxxxxxxxxxxx: encode = 16'b0001000000000000;
        16'b11110xxxxxxxxxxx: encode = 16'b0000100000000000;
        16'b111110xxxxxxxxxx: encode = 16'b0000010000000000;
        16'b1111110xxxxxxxxx: encode = 16'b0000001000000000;
        16'b11111110xxxxxxxx: encode = 16'b0000000100000000;
        16'b111111110xxxxxxx: encode = 16'b0000000010000000;
        16'b1111111110xxxxxx: encode = 16'b0000000001000000;
        16'b11111111110xxxxx: encode = 16'b0000000000100000;
        16'b111111111110xxxx: encode = 16'b0000000000010000;
        16'b1111111111110xxx: encode = 16'b0000000000001000;
        16'b11111111111110xx: encode = 16'b0000000000000100;
        16'b111111111111110x: encode = 16'b0000000000000010;
        16'b1111111111111110: encode = 16'b0000000000000001;
        default:              encode = 16'b0000000000000000;
        endcase
end
endfunction
 
assign fifo_sel = encode( fifo_empty_0, fifo_empty_1, fifo_empty_2, fifo_empty_3);
assign fifo_sel_domain = (!(&fifo_empty_3)) ? 2'b11 :
                         (!(&fifo_empty_2)) ? 2'b10 :
                         (!(&fifo_empty_1)) ? 2'b01 :
                         2'b00;
 
endmodule
 
`timescale 1ns/1ns
module decode (
    fifo_sel, fifo_sel_domain,
    fifo_we_0, fifo_we_1, fifo_we_2, fifo_we_3
);
 
input  [0:15] fifo_sel;
input  [1:0]  fifo_sel_domain;
output [0:15] fifo_we_0, fifo_we_1, fifo_we_2, fifo_we_3;
 
assign fifo_we_0 = (fifo_sel_domain == 2'b00) ? fifo_sel : {16{1'b0}};
assign fifo_we_1 = (fifo_sel_domain == 2'b01) ? fifo_sel : {16{1'b0}};
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
//////////////////////////////////////////////////////////////////////
////                                                              ////
////  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                     ////
////                                                              ////
//////////////////////////////////////////////////////////////////////
 
// GRAY counter
module gray_counter ( cke, q, q_bin, rst, clk);
 
   parameter length = 4;
   input cke;
   output reg [length:1] q;
   output [length:1] q_bin;
   input rst;
   input clk;
 
   parameter clear_value = 0;
 
   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)
       q <= {length{1'b0}};
     else
       if (cke)
         q <= (q_next>>1) ^ q_next;
 
   assign q_bin = qi;
 
endmodule
// async FIFO with multiple queues, multiple data
`define ORIGINAL_EGRESS_FIFO
`ifdef ORIGINAL_EGRESS_FIFO
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 reg [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 [data_width-1:0] fifo_q;
 
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
 
// a pipeline stage for address read gives higher clock frequency but adds one 
// clock latency for adr read
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
 
// and-or mux write address
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
 
// and-or mux read address
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
 
// and-or mux write data
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(fifo_q),
    .adr_b({onehot2bin(read_enable_reg),radr}),
    .clk_b(clk2) );
 
   // Added registering of FIFO output to break a timing path
   always@(posedge clk2)
     q <= fifo_q;
 
 
endmodule
`else // !`ifdef ORIGINAL_EGRESS_FIFO
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 = 2;
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 reg [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 [data_width-1:0] fifo_q;
 
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];
wire [a_lo_size-1:0] wadr;
wire [a_lo_size-1:0] radr;
wire [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;
 
// a pipeline stage for address read gives higher clock frequency but adds one 
// clock latency for adr read
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;
 
   // 0        
   gray_counter wadrcnt0
     (
      .cke(write & write_enable[0]),
      .q(fifo_wadr_gray[0]),
      .q_bin(fifo_wadr_bin[0]),
      .rst(rst1),
      .clk(clk1)
      );
 
   gray_counter radrcnt0
     (
      .cke((read_adr_reg | read_data) & read_enable_reg[0]),
      .q(fifo_radr_gray[0]),
      .q_bin(fifo_radr_bin[0]),
      .rst(rst2),
      .clk(clk2)
      );
 
   versatile_fifo_async_cmp
     #(
      .ADDR_WIDTH(a_lo_size)
      )
   egresscmp0
     ( 
       .wptr(fifo_wadr_gray[0]), 
       .rptr(fifo_radr_gray[0]), 
       .fifo_empty(fifo_empty[0]), 
       .fifo_full(fifo_full[0]), 
       .wclk(clk1), 
       .rclk(clk2), 
       .rst(rst1)
       );
 
   // 1
      gray_counter wadrcnt1
     (
      .cke(write & write_enable[1]),
      .q(fifo_wadr_gray[1]),
      .q_bin(fifo_wadr_bin[1]),
      .rst(rst1),
      .clk(clk1)
      );
 
   gray_counter radrcnt1
     (
      .cke((read_adr_reg | read_data) & read_enable_reg[1]),
      .q(fifo_radr_gray[1]),
      .q_bin(fifo_radr_bin[1]),
      .rst(rst2),
      .clk(clk2)
      );
 
   versatile_fifo_async_cmp
     #(
      .ADDR_WIDTH(a_lo_size)
      )
   egresscmp1
     ( 
       .wptr(fifo_wadr_gray[1]), 
       .rptr(fifo_radr_gray[1]), 
       .fifo_empty(fifo_empty[1]), 
       .fifo_full(fifo_full[1]), 
       .wclk(clk1), 
       .rclk(clk2), 
       .rst(rst1)
       );
 
   // 2
      gray_counter wadrcnt2
     (
      .cke(write & write_enable[2]),
      .q(fifo_wadr_gray[2]),
      .q_bin(fifo_wadr_bin[2]),
      .rst(rst1),
      .clk(clk1)
      );
 
   gray_counter radrcnt2
     (
      .cke((read_adr_reg | read_data) & read_enable_reg[2]),
      .q(fifo_radr_gray[2]),
      .q_bin(fifo_radr_bin[2]),
      .rst(rst2),
      .clk(clk2)
      );
 
   versatile_fifo_async_cmp
     #(
      .ADDR_WIDTH(a_lo_size)
      )
   egresscmp2
     ( 
       .wptr(fifo_wadr_gray[2]), 
       .rptr(fifo_radr_gray[2]), 
       .fifo_empty(fifo_empty[2]), 
       .fifo_full(fifo_full[2]), 
       .wclk(clk1), 
       .rclk(clk2), 
       .rst(rst1)
       );
 
 
   assign wadr = (fifo_wadr_bin[0] & {a_lo_size{write_enable[0]}}) |
		 (fifo_wadr_bin[1] & {a_lo_size{write_enable[1]}}) |
		 (fifo_wadr_bin[2] & {a_lo_size{write_enable[2]}});
 
   assign radr = (fifo_radr_bin[0] & {a_lo_size{read_enable_reg[0]}}) |
		 (fifo_radr_bin[1] & {a_lo_size{read_enable_reg[1]}}) |
		 (fifo_radr_bin[2] & {a_lo_size{read_enable_reg[2]}});
 
 
   assign wdataa[0] = d[108-1:72];
   assign wdataa[1] = d[72-1:36];
   assign wdataa[2] = d[36-1:0];
 
   assign wdata = ( d[108-1:72] & {data_width{write_enable[0]}}) |
		  ( d[72-1:36]  & {data_width{write_enable[1]}}) |
		  ( d[36-1:0]   & {data_width{write_enable[2]}});   
 
   wire [1:0] wadr_top;
   assign wadr_top = write_enable[1] ? 2'b01 :
		     write_enable[2] ? 2'b10 :
		     2'b00;
   wire [1:0] radr_top;
   assign radr_top = read_enable_reg[1] ? 2'b01 :
		     read_enable_reg[2] ? 2'b10 :
		     2'b00;
 
vfifo_dual_port_ram_dc_sw 
  # ( 
      .DATA_WIDTH(data_width), 
      .ADDR_WIDTH(2+a_lo_size)
      )
    dpram (
    .d_a(wdata),
    .adr_a({wadr_top,wadr}), 
    .we_a(write),
    .clk_a(clk1),
    .q_b(fifo_q),
    .adr_b({radr_top,radr}),
    .clk_b(clk2) );
 
   // Added registering of FIFO output to break a timing path
   always@(posedge clk2)
     q <= fifo_q;
 
 
endmodule
`endif // !`ifdef ORIGINAL_EGRESS_FIFO
// true dual port RAM, sync
 
`ifdef ACTEL
	`define SYN 
`endif
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] /*synthesis syn_ramstyle = "no_rw_check"*/;
   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 
`timescale 1ns/1ns
`include "sdr_16_defines.v"
module fsm_sdr_16 (
		   adr_i, we_i, bte_i, cti_i, sel_i,
		   fifo_empty, fifo_rd_adr, fifo_rd_data, count0,
		   refresh_req, cmd_aref, cmd_read, state_idle,
		   ba, a, cmd, dqm, dq_oe,
		   sdram_burst_reading,
		   debug_state, debug_fifo_we_record,
		   sdram_clk, sdram_fifo_wr, sdram_rst
		   );
 
   /* Now these are defined
    parameter ba_size = 2;   
    parameter row_size = 13;
    parameter col_size = 9;   
    */
 
   input [`BA_SIZE+`ROW_SIZE+`COL_SIZE-1:0] adr_i;
   input 				 we_i;
   input [1:0] 				 bte_i;
   input [2:0] 				 cti_i;
   input [3:0] 				 sel_i;
 
   input 				 fifo_empty;
   output 				 fifo_rd_adr, fifo_rd_data;
   output reg 				 count0;
 
   input 				 refresh_req;
   output reg 				 cmd_aref; // used for rerfresh ack
   output reg 				 cmd_read; // used for ingress fifo control
   output 				 state_idle; // state=idle
 
   output reg [1:0] 			 ba /*synthesis syn_useioff=1 syn_allow_retiming=0 */;
   output reg [12:0] 			 a /*synthesis syn_useioff=1 syn_allow_retiming=0 */;
   output reg [2:0] 			 cmd /*synthesis syn_useioff=1 syn_allow_retiming=0 */;
   output reg [1:0] 			 dqm /*synthesis syn_useioff=1 syn_allow_retiming=0 */;
   output reg 				 dq_oe;
 
   output 				 sdram_burst_reading;   
   input 				 sdram_clk, sdram_fifo_wr, sdram_rst;
 
   output [2:0] 			 debug_state;
   output [3:0] 			 debug_fifo_we_record;
 
   wire [`BA_SIZE-1:0] 			 bank;
   wire [`ROW_SIZE-1:0] 			 row;
   wire [`COL_SIZE-1:0] 			 col;
   wire [12:0] 				 col_reg_a10_fix;
   reg [0:31] 				 shreg;
   wire 				 stall; // active if write burst need data
 
   reg [0:15] 				 fifo_sel_reg_int;
   reg [1:0] 				 fifo_sel_domain_reg_int;
 
   // adr_reg {ba,row,col,we}
   reg [1:0] 				 ba_reg;  
   reg [`ROW_SIZE-1:0] 			 row_reg;
   reg [`COL_SIZE-1:0] 			 col_reg;
   reg 					 we_reg;
   reg [1:0] 				 bte_reg;
   reg [2:0] 				 cti_reg;
 
   // to keep track of open rows per bank
   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 [2:0] classic=3'b000,
		constant=3'b001,
		increment=3'b010,
		endburst=3'b111;
 
   parameter [1:0] linear = 2'b00,
                beat4  = 2'b01,
                beat8  = 2'b10,
                beat16 = 2'b11;
 
   parameter [2:0] cmd_nop = 3'b111,
                cmd_act = 3'b011,
                cmd_rd  = 3'b101,
                cmd_wr  = 3'b100,
                cmd_pch = 3'b010,
                cmd_rfr = 3'b001,
                cmd_lmr = 3'b000;
 
   // ctrl FSM
 
/*    define instead of param, as synplify is doing weird things
 parameter [2:0] init = 3'b000,
                idle = 3'b001,
                rfr  = 3'b010,
                adr  = 3'b011,
                pch  = 3'b100,
                act  = 3'b101,
                w4d  = 3'b110,
                rw   = 3'b111;
 */
`define FSM_INIT 3'b000
`define FSM_IDLE 3'b001
`define FSM_RFR  3'b010
`define FSM_ADR  3'b011
`define FSM_PCH  3'b100
`define FSM_ACT  3'b101
`define FSM_W4D  3'b110
`define FSM_RW   3'b111
 
   reg [2:0] 				 state, next;
 
   assign debug_state = state;
 
   function [12:0] a10_fix;
      input [`COL_SIZE-1:0] 		 a;
      integer 				 i;
      begin
	 for (i=0;i<13;i=i+1) begin
            if (i<10)
              if (i<`COL_SIZE)
                a10_fix[i] = a[i];
              else
                a10_fix[i] = 1'b0;
            else if (i==10)
              a10_fix[i] = 1'b0;
            else
              if (i<`COL_SIZE)
                a10_fix[i] = a[i-1];
              else
                a10_fix[i] = 1'b0;
	 end
      end
   endfunction
 
 
   assign {bank,row,col} = adr_i;
 
   always @ (posedge sdram_clk or posedge sdram_rst)
     if (sdram_rst)
       state <= `FSM_INIT;
     else
       state <= next;
 
   always @*
     begin
	next = 3'bx;
	case (state)
	  `FSM_INIT:
	    if (shreg[31])          
	      next = `FSM_IDLE;
            else                    
	      next = `FSM_INIT;
	  `FSM_IDLE:   
	    if (refresh_req)        
	      next = `FSM_RFR;
            else if (!shreg[0] & !fifo_empty)   
	      next = `FSM_ADR;
            else                    
	      next = `FSM_IDLE;
	  `FSM_RFR: 
	    if (shreg[5])           
	      next = `FSM_IDLE;
            else                    
	      next = `FSM_RFR;
	  `FSM_ADR:
	    if (shreg[5])
	      begin
		 if (current_bank_closed_reg)   
		   next = `FSM_ACT;
		 else if (current_row_open_reg)
		   next = (we_reg) ?  `FSM_W4D : `FSM_RW;
		 else 		                     
		   next = `FSM_PCH;
	      end
            else                                            
	      next = `FSM_ADR;
	  `FSM_PCH:    
	    if (shreg[1])         
	      next = `FSM_ACT;
            else                    
	      next = `FSM_PCH;
	  `FSM_ACT:
	    if (shreg[2])
	      begin
`ifdef SLOW_WB_CLOCK
		 // Automatiacally go to wait for data if burst writing
		 if ((|bte_reg) & we_reg & cti_reg==increment) 
		   next = `FSM_W4D;
		 else if ((!fifo_empty | !we_reg)) 
		   next = `FSM_RW;
`else
		 if ((!fifo_empty | !we_reg)) 
		   next = `FSM_RW;
`endif
		 else if (fifo_empty)         
		   next = `FSM_W4D;
	      end
            else                                    
	      next = `FSM_ACT;
`ifdef SLOW_WB_CLOCK
	  // Add some wait here if bursting and the wishbone clock is slow
	  `FSM_W4D:    
	    if (!fifo_empty & ((cti_reg!=increment)|(cti_reg==increment /*& bte_reg==beat4*/  & shreg[14])))
	      next = `FSM_RW;
`else
	  `FSM_W4D:    
	    if (!fifo_empty) 
	      next = `FSM_RW;
`endif	  
            else             
	      next = `FSM_W4D;
	  `FSM_RW:     
	    if ((bte_reg==linear | !(cti_reg==increment)) & shreg[1])
              next = `FSM_IDLE;
            else if (bte_reg==beat4 & shreg[7])
              next = `FSM_IDLE;
`ifdef BEAT8
            else if (bte_reg==beat8 & shreg[15])
              next = `FSM_IDLE;
`endif
`ifdef BEAT16
            else if (bte_reg==beat16 & shreg[31])
              next = `FSM_IDLE;
`endif
            else
              next = `FSM_RW;
	endcase
     end // always @ *
 
 
   // active if write burst need data
   assign stall = state==`FSM_RW & next==`FSM_RW & fifo_empty & count0 & we_reg;
 
   // counter
   always @ (posedge sdram_clk or posedge sdram_rst)
     begin
	if (sdram_rst) begin
           shreg   <= {1'b1,{31{1'b0}}};
           count0  <= 1'b0;
	end else
          if (state!=next) begin
             shreg   <= {1'b1,{31{1'b0}}};
             count0  <= 1'b0;
          end else 
            if (~stall) begin
               shreg   <= shreg >> 1;
               count0  <= ~count0;
            end
     end
 
   // ba, a, cmd
   // col_reg_a10 has bit [10] set to zero to disable auto precharge
   assign col_reg_a10_fix = a10_fix(col_reg);
 
   // outputs dependent on state vector
   always @ (posedge sdram_clk or posedge sdram_rst)
     begin
	if (sdram_rst) begin
           {ba,a,cmd} <= {2'b00,13'd0,cmd_nop};
           dqm <= 2'b11;
           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}}};
           {ba_reg,row_reg,col_reg,we_reg,cti_reg,bte_reg} <= 
                     {2'b00, {`ROW_SIZE{1'b0}}, {`COL_SIZE{1'b0}}, 1'b0,3'b000, 2'b00 };
	end else begin
           {ba,a,cmd} <= {2'b00,13'd0,cmd_nop};
           dqm <= 2'b11;
           cmd_aref <= 1'b0;
           cmd_read <= 1'b0;
           dq_oe <= 1'b0;
           case (state)
             `FSM_INIT:
               if (shreg[3]) begin
                  {ba,a,cmd} <= {2'b00, 13'b0010000000000, cmd_pch};
                  open_ba[ba_reg] <= 1'b0;
               end else if (shreg[7] | shreg[19])
                 {ba,a,cmd,cmd_aref} <= {2'b00, 13'd0, cmd_rfr,1'b1};
               else if (shreg[31])
                 {ba,a,cmd} <= 
		  {2'b00,3'b000,`INIT_WB,2'b00,`INIT_CL,`INIT_BT,`INIT_BL, cmd_lmr};
             `FSM_RFR:
               if (shreg[0]) begin
                  {ba,a,cmd} <= {2'b00, 13'b0010000000000, cmd_pch};
                  open_ba <= 4'b0000;
               end else if (shreg[2])
                 {ba,a,cmd,cmd_aref} <= {2'b00, 13'd0, cmd_rfr,1'b1};
             `FSM_ADR:
               if (shreg[4])
                 {ba_reg,row_reg,col_reg,we_reg,cti_reg,bte_reg} <= 
		                                {bank,row,col,we_i,cti_i,bte_i};
             `FSM_PCH:
               if (shreg[0]) begin
                  {ba,a,cmd} <= {ba_reg,13'd0,cmd_pch};
                  //open_ba <= 4'b0000;
		  open_ba[ba_reg] <= 1'b0;
               end
             `FSM_ACT:
               if (shreg[0]) 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
             `FSM_RW:
               begin
                  if (we_reg & !count0)
                    cmd <= cmd_wr;
                  else if (!count0)
                    {cmd,cmd_read} <= {cmd_rd,1'b1};
                  else
                    cmd <= cmd_nop;
                  if (we_reg)
		    begin
		       dqm <= count0 ? ~sel_i[1:0] : ~sel_i[3:2];
		    end
                  else
                    dqm <= 2'b00;
                  //if (we_reg)
                  dq_oe <= we_reg;//1'b1;
                  if (!stall)
		    begin
		       if (cti_reg==increment)
			 case (bte_reg)
			   linear: {ba,a} <= {ba_reg,col_reg_a10_fix};
			   beat4:  {ba,a,col_reg[2:0]} <= 
				  {ba_reg,col_reg_a10_fix, col_reg[2:0] + 3'd1};
          `ifdef BEAT8
			   beat8:  {ba,a,col_reg[3:0]} <= 
				  {ba_reg,col_reg_a10_fix, col_reg[3:0] + 4'd1};
          `endif
          `ifdef BEAT16
			   beat16: {ba,a,col_reg[4:0]} <= 
				  {ba_reg,col_reg_a10_fix, col_reg[4:0] + 5'd1};
          `endif
			 endcase // case (bte_reg)
		       else
			 {ba,a} <= {ba_reg,col_reg_a10_fix};
 
		    end // if (!stall)
               end
			   endcase
	end
     end
 
   reg fifo_read_data_en;
   always @(posedge sdram_clk)
     if (sdram_rst)
       fifo_read_data_en <= 1;
     else if (next==`FSM_RW)
       fifo_read_data_en <= ~fifo_read_data_en;
     else
       fifo_read_data_en <= 1;
 
   reg [3:0] beat4_data_read_limiter; // Use this to record how many times we've pulsed fifo_rd_data
   // Only 3 bits, becuase we're looking at when fifo_read_data_en goes low - should only happen 3
   // times for a 4-beat burst
   always @(posedge sdram_clk)
     if (sdram_rst)
       beat4_data_read_limiter <= 0;
     else if(state==`FSM_ADR)
       beat4_data_read_limiter <= 0;
     else if (!fifo_read_data_en)
       beat4_data_read_limiter <= {beat4_data_read_limiter[2:0],1'b1};
 
 
 
   // rd_adr goes high when next adr is fetched from sync RAM and during write burst
   assign fifo_rd_adr  = state==`FSM_ADR & shreg[1];
 
   assign fifo_rd_data = (((state!=`FSM_RW & next==`FSM_RW)|(state==`FSM_RW & (cti_reg==increment && bte_reg==beat4 & fifo_read_data_en & !(&beat4_data_read_limiter)))) & we_reg & !fifo_empty);
 
   /*
   assign fifo_rd_data = ((state==`FSM_RW & next==`FSM_RW) & 
			  we_reg & !count0 & !fifo_empty);
*/
   assign state_idle = (state==`FSM_IDLE);
 
   // bank and row open ?
   assign current_bank_closed = !(open_ba[bank]);
   assign current_row_open = open_row[bank]==row;
 
   always @ (posedge sdram_clk or posedge sdram_rst)
     if (sdram_rst)
       {current_bank_closed_reg, current_row_open_reg} <= {1'b1, 1'b0};
     else
       //if (state==adr & counter[1:0]==2'b10)
       {current_bank_closed_reg, current_row_open_reg} <= 
				        {current_bank_closed, current_row_open};
 
   // Record the number of write enables going to INGRESS fifo (ie. that we 
   // generate when we're reading) - this makes sure we keep track of when a
   // burst read is in progress, and we can signal the wishbone bus to wait
   // for this data to be put into the FIFO before it'll empty it when it's
   // had a terminated burst transfer.
   reg [3:0] fifo_we_record;
   assign debug_fifo_we_record = fifo_we_record;   
   always @(posedge sdram_clk) 
     if (sdram_rst)
       fifo_we_record <= 0;
     else if (next==`FSM_RW & ((state==`FSM_ADR)|(state==`FSM_ACT)) & 
	      cti_reg==increment & (bte_reg==beat4) & !we_reg)
       fifo_we_record <= 4'b0001;
     else if (sdram_fifo_wr)
       fifo_we_record <= {fifo_we_record[2:0],1'b0};
`ifdef SDRAM_WB_SAME_CLOCKS   
   assign sdram_burst_reading = |fifo_we_record;
`else   
   assign sdram_burst_reading = 0;
`endif
 
 
endmodule
`timescale 1ns/1ns
module versatile_mem_ctrl_wb 
  (
   // wishbone side
   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 controller interface
   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_burst_reading,
   debug_wb_fsm_state, debug_ingress_fifo_empty, debug_egress_fifo_empty,
   sdram_clk, sdram_rst
 
);
 
parameter nr_of_wb_ports = 3;
 
input  [36*nr_of_wb_ports-1:0]  wb_adr_i_v;
input  [36*nr_of_wb_ports-1:0]  wb_dat_i_v;
input  [0:nr_of_wb_ports-1]     wb_stb_i;
input  [0:nr_of_wb_ports-1]     wb_cyc_i;
output [32*nr_of_wb_ports-1:0]  wb_dat_o_v;
output [0:nr_of_wb_ports-1]     wb_ack_o;
input                           wb_clk;
input                           wb_rst;
 
output [35:0]               sdram_dat_o;
output [0:nr_of_wb_ports-1] sdram_fifo_empty;
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                       sdram_fifo_wr;
input  [0:nr_of_wb_ports-1] sdram_fifo_we;
input   		    sdram_burst_reading;
input                       sdram_clk;
input                       sdram_rst;
 
   output [(2*nr_of_wb_ports)-1:0] debug_wb_fsm_state;
   output [nr_of_wb_ports-1:0] 	debug_ingress_fifo_empty;
   output [nr_of_wb_ports-1:0] 	debug_egress_fifo_empty;
 
 
 
parameter linear       = 2'b00;
parameter wrap4        = 2'b01;
parameter wrap8        = 2'b10;
parameter wrap16       = 2'b11;
parameter classic      = 3'b000;
parameter endofburst   = 3'b111;
 
`define CTI_I 2:0
`define BTE_I 4:3
`define WE_I  5
 
parameter idle = 2'b00;
parameter rd   = 2'b01;
parameter wr   = 2'b10;
parameter fe   = 2'b11;
 
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 [36*nr_of_wb_ports-1:0] egress_fifo_di;
wire [31:0] wb_dat_o;
 
wire [0:nr_of_wb_ports] stall;
wire [0:nr_of_wb_ports-1] state_idle;
wire [0:nr_of_wb_ports-1] egress_fifo_we,  egress_fifo_full;
wire [0:nr_of_wb_ports-1] ingress_fifo_re, ingress_fifo_empty;
 
   wire [1:0] 		  debug_each_wb_fsm_state [0:nr_of_wb_ports-1];
 
 
genvar i;
 
assign stall[0] = 1'b0;
 
`define INDEX (nr_of_wb_ports-i)*36-1:(nr_of_wb_ports-1-i)*36 
generate
    for (i=0;i<nr_of_wb_ports;i=i+1) begin : vector2array
        assign wb_adr_i[i] = wb_adr_i_v[`INDEX];
        assign wb_dat_i[i] = wb_dat_i_v[`INDEX];
        assign egress_fifo_di[`INDEX] = (state_idle[i]) ? 
					wb_adr_i[i] : wb_dat_i[i];
 
    end
endgenerate
 
   // Debug output assignments
   generate
      for (i=0;i<nr_of_wb_ports;i=i+1) begin : vector2debugarray
	 assign debug_wb_fsm_state[(nr_of_wb_ports-i)*2-1:(nr_of_wb_ports-1-i)*2] = debug_each_wb_fsm_state[i];
      end
   endgenerate
   assign debug_ingress_fifo_empty = ingress_fifo_empty;
   assign debug_egress_fifo_empty = egress_fifo_we;
 
 
generate
    for (i=0;i<nr_of_wb_ports;i=i+1) begin : fsm
        fsm_wb fsm_wb_i 
	  (
           .stall_i(stall[i]),
           .stall_o(stall[i+1]),
           .we_i (wb_adr_i[i][`WE_I]),
           .cti_i(wb_adr_i[i][`CTI_I]),
           .bte_i(wb_adr_i[i][`BTE_I]),
           .stb_i(wb_stb_i[i]),
           .cyc_i(wb_cyc_i[i]),
           .ack_o(wb_ack_o[i]),
           .egress_fifo_we(egress_fifo_we[i]),
           .egress_fifo_full(egress_fifo_full[i]),
            .ingress_fifo_re(ingress_fifo_re[i]),
           .ingress_fifo_empty(ingress_fifo_empty[i]),
           .state_idle(state_idle[i]),
	   .sdram_burst_reading(sdram_burst_reading),
	   .debug_state(debug_each_wb_fsm_state[i]),
           .wb_clk(wb_clk),
           .wb_rst(wb_rst)
           );
    end
endgenerate
 
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(|(egress_fifo_we)), 
	       .write_enable(egress_fifo_we),
	       .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(|(ingress_fifo_re)), 
		.read_enable(ingress_fifo_re), .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
`ifdef DDR_16
 `include "ddr_16_defines.v"
`endif
`ifdef SDR_16
 `include "sdr_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  = 3;
   parameter nr_of_wb_ports_clk1  = 0;
   parameter nr_of_wb_ports_clk2  = 0;
   parameter nr_of_wb_ports_clk3  = 0;
 
   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;
   output [0:nr_of_wb_ports_clk0-1]    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;   
   output [0:nr_of_wb_ports_clk1-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;
   output [0:nr_of_wb_ports_clk2-1]    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;
   output [0:nr_of_wb_ports_clk3-1]    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 [(`SDRAM_DATA_WIDTH)-1:0] dq_o /*synthesis syn_useioff=1 syn_allow_retiming=0 */;
   output [1:0] 		       dqm_pad_o;
   input [(`SDRAM_DATA_WIDTH)-1: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;
 
   wire 			       burst_reading;
   reg 				       sdram_fifo_wr_r;
 
 
   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_burst_reading(burst_reading),
	    .debug_wb_fsm_state(),
	    .debug_ingress_fifo_empty(),
	    .debug_egress_fifo_empty(),
            .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_burst_reading(burst_reading),
            .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_burst_reading(burst_reading),
            .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_burst_reading(burst_reading),
            .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 [(`SDRAM_DATA_WIDTH)-1:0] dq_i_reg /*synthesis syn_useioff=1 syn_allow_retiming=0 */;
   reg [(`SDRAM_DATA_WIDTH)-1:0] 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));
   ref_counter
`ifdef MT48LC32M16     
     #(.length(9), .wrap_value(67))
`endif   
   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;
 
   reg 	      current_fifo_empty_r;
   always @(posedge sdram_clk)
     current_fifo_empty_r <= current_fifo_empty;
 
   always @(posedge sdram_clk)
     sdram_fifo_wr_r <= fifo_wr;
 
 
 
   // SDR SDRAM 16 FSM
   fsm_sdr_16 fsm_sdr_16_0 
     (
      .adr_i({fifo_dat_o[0][`BA_SIZE+`ROW_SIZE+`COL_SIZE+6-2:6],1'b0}),
      .we_i(fifo_dat_o[0][5]),
      .bte_i(fifo_dat_o[0][4:3]),
      .cti_i(fifo_dat_o[0][2:0]),
      .sel_i({fifo_dat_o[0][3:2],dq_o_tmp_reg[1:0]}),
      .fifo_empty(current_fifo_empty_r),
      .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),
      .dqm(dqm_pad_o),
      .sdram_fifo_wr(sdram_fifo_wr_r),
      .sdram_burst_reading(burst_reading),
      .debug_state(),
      .debug_fifo_we_record(),
      .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=`INIT_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=`INIT_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=`INIT_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)
     dq_i_reg <= dq_i;
 
   always @(posedge sdram_clk)
     dq_i_tmp_reg <= 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)
       dq_o_tmp_reg <= 18'h0;
     else
       dq_o_tmp_reg <= {fifo_dat_o[0][19:4],fifo_dat_o[0][1:0]};
 
   // output dq_o mux and dffs
   always @ (posedge sdram_clk or posedge sdram_rst)
     if (sdram_rst)
       dq_o <= 16'h0000;
     else
       if (~count0)
         dq_o <= fifo_dat_o[0][35:20];
       else
         dq_o <= dq_o_tmp_reg[17:2];
 
   /*
    // data mask signals should be not(sel_i) for write and 2'b00 for read
    always @ (posedge sdram_clk or posedge sdram_rst)
    if (sdram_rst)
    dqm_pad_o <= 2'b00;
    else
    if (~count0)
    dqm_pad_o <= ~fifo_dat_o[fifo_sel_domain_reg][3:2];
    else
    dqm_pad_o <= ~dq_o_tmp_reg[1:0];
    */
   /*
    always @ (posedge sdram_clk or posedge sdram_rst)
    if (sdram_rst) begin
    {dq_o, dqm_pad_o} <= {16'h0000,2'b00};
 
    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        cke_d, ras_d, cas_d, we_d, cs_n_d;
   wire        ras_o, cas_o, we_o, cs_n_o;
   wire [1:0]  ba_o;
   wire [12:0] addr_o;
   reg  [1:0]  ba;
   wire [1:0]  ba_d;
   reg [12:0]  addr;
   wire [12:0] addr_d;
   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, 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;
   reg         burst_mask;
   wire [12:0] cur_row;
   wire  [3:0] burst_adr;
   //wire  [2:0] tx_fifo_b_sel_i_cur;
   wire  [2:0] rx_fifo_a_sel_i;
   //wire  [7:0] tx_fifo_empty;
   wire        rx_fifo_we;
 
   wire ref_cnt_zero;
   wire cmd_aref;
 
   // refresh 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;
 
   // 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(fifo_dat_o[fifo_sel_domain_reg]),
      .burst_adr(burst_adr),
      .fifo_empty(current_fifo_empty),
      .fifo_sel(),
      .read(read),
      .write(write),
      .ref_req(refresh_req),
      .ref_ack(cmd_aref),
      .ref_delay(ref_delay),
      .state_idle(idle),
      .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),
      .clk(sdram_clk_0),
      .rst(sdram_rst)
      );
 
   inc_adr inc_adr0
     (
      .adr_i(fifo_dat_o[fifo_sel_domain_reg][9:6]),
      .bte_i(fifo_dat_o[fifo_sel_domain_reg][4:3]),
      .cti_i(fifo_dat_o[fifo_sel_domain_reg][2:0]),
      .init(adr_init),
      .inc(),
      .adr_o(burst_adr),
      .done(done),
      .clk(sdram_clk_0),
      .rst(sdram_rst)
      );
 
   // Delay, refresh to activate/refresh
   ref_delay_counter ref_delay_counter0
     (
      .cke(ref_delay),
      .zq(ref_delay_ack),
      .clk(sdram_clk_0),
      .rst(sdram_rst)
      );
 
   // Burst length, DDR2 SDRAM
   burst_length_counter burst_length_counter0
     (
      .cke(bl_en),
      .zq(bl_ack),
      .clk(sdram_clk_0),
      .rst(sdram_rst)
      );
 
   // Wishbone burst length
   assign burst_length = (adr_init && fifo_dat_o[fifo_sel_domain_reg][2:0] == 3'b000) ? 4'd1 :   // classic cycle
                         (adr_init && fifo_dat_o[fifo_sel_domain_reg][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 sdram_rst)
     if (sdram_rst)
       burst_cnt <= 4'h0;
     else
       if (bl_en)
         burst_cnt <= burst_next_cnt;
   // Burst Mask
   //assign burst_mask = (burst_cnt >= burst_length) ? 1'b1 : 1'b0;
 
   // Burst Mask
   always @ (posedge sdram_clk_0 or posedge sdram_rst)
     if (sdram_rst)
       burst_mask <= 1'b0;
     else
       burst_mask <= (burst_cnt >= burst_length) ? 1'b1 : 1'b0;
 
   // Delay address and control to compensate for delay in Tx FIOFs
   defparam delay0.depth=3; 
   defparam delay0.width=20;
   delay delay0 (
      .d({cs_n_o,1'b1,ras_o,cas_o,we_o,ba_o,addr_o}),
      .q({cs_n_d,cke_d,ras_d,cas_d,we_d,ba_d,addr_d}),
      .clk(sdram_clk_180),
      .rst(sdram_rst));
 
   // Assing outputs
   // Non-DDR outputs
   assign cs_n_pad_o  = cs_n_d;
   assign cke_pad_o   = cke_d;
   assign ras_pad_o   = ras_d;
   assign cas_pad_o   = cas_d;
   assign we_pad_o    = we_d;
   assign ba_pad_o    = ba_d;
   assign addr_pad_o  = addr_d;
   assign ck_fb_pad_o = ck_fb;
   assign dqs_oe      = dq_en;
 
   // Read latency, delay the control signals to fit latency of the DDR2 SDRAM
   defparam delay1.depth=`CL+`AL+4; 
   defparam delay1.width=1;
   delay delay1 
     (
      .d(read && !burst_mask),
      .q(fifo_wr),
      .clk(sdram_clk_0),
      .rst(sdram_rst)
      );
 
   // write latency, delay the control signals to fit latency of the DDR2 SDRAM
   defparam delay2.depth=`CL+`AL+1;
   defparam delay2.width=1;
   delay delay2 
     (
      .d(write),
      .q(dq_en),
      .clk(sdram_clk_270),
      .rst(sdram_rst)
      );
 
   // write latency, delay the control signals to fit latency of the DDR2 SDRAM
   defparam delay21.depth=`CL+`AL;
   defparam delay21.width=1;
   delay delay21 
     (
      .d(burst_mask),
      .q(dqm_en),
      .clk(sdram_clk_270),
      .rst(sdram_rst)
      );
 
/*   // if CL>3 delay read from Tx FIFO
   defparam delay3.depth=`CL+`AL-3;
   defparam delay3.width=1;
   delay delay3 
     (		 
		 .d(tx_fifo_re_i && !burst_mask),
		 .q(tx_fifo_re),
		 .clk(sdram_clk_0),
		 .rst(sdram_rst)
		 );
*/
 
   // if CL=3, no delay
   assign tx_fifo_re = tx_fifo_re_i && !burst_mask;
   assign fifo_rd_adr = tx_fifo_re;
 
   //
   genvar i;
   generate
     for (i=0; i < 16; i=i+1) begin : dly
 
       defparam delay4.depth=`CL+2;   
       defparam delay4.width=1;
       delay delay4 (
         .d(fifo_sel_reg[i]),
         .q(fifo_sel_dly[i]),
         .clk(sdram_clk),
         .rst(sdram_rst)
       );
     end
 
     defparam delay5.depth=`CL+2;   
     defparam delay5.width=2;
     delay delay5 (
       .d(fifo_sel_domain_reg),
       .q(fifo_sel_domain_dly),
       .clk(sdram_clk),
       .rst(sdram_rst)
     );
endgenerate  
 
 
   // Increment address
   defparam delay6.depth=`CL+`AL-1;
   defparam delay6.width=1;
   delay delay6 
     (
      .d({write|read}),
      .q({adr_inc}),
      .clk(sdram_clk_0),
      .rst(sdram_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(sdram_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(fifo_dat_o[fifo_sel_domain_reg]),
      .rx_dat_o(fifo_dat_i),
      .dq_en(dq_en),
      .dqm_en(dqm_en),
      .rst(sdram_rst),
      .clk_0(sdram_clk_0),
      .clk_90(sdram_clk_90),
      .clk_180(sdram_clk_180),
      .clk_270(sdram_clk_270));
 
`endif //  `ifdef DDR_16
 
endmodule // wb_sdram_ctrl_top
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

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