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

Subversion Repositories wbddr3

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /wbddr3/trunk
    from Rev 16 to Rev 17
    Reverse comparison

Rev 16 → Rev 17

/rtl/xioddrserdes.v
0,0 → 1,134
////////////////////////////////////////////////////////////////////////////////
//
// Filename: xioddrserdes.v
//
// Project: A wishbone controlled DDR3 SDRAM memory controller.
//
// Purpose:
//
// Creator: Dan Gisselquist, Ph.D.
// Gisselquist Technology, LLC
//
////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2015-2016, Gisselquist Technology, LLC
//
// This program is free software (firmware): you can redistribute it and/or
// modify it under the terms of the GNU General Public License as published
// by the Free Software Foundation, either version 3 of the License, or (at
// your option) any later version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program. (It's in the $(ROOT)/doc directory, run make with no
// target there if the PDF file isn't present.) If not, see
// <http://www.gnu.org/licenses/> for a copy.
//
// License: GPL, v3, as defined and found on www.gnu.org,
// http://www.gnu.org/licenses/gpl.html
//
//
////////////////////////////////////////////////////////////////////////////////
//
//
module xioddrserdes(i_clk_fast, i_clk_fast_inv, i_clk_slow, i_reset,
i_oe, i_data, o_data, io_pin);
input i_clk_fast, i_clk_fast_inv, i_clk_slow, i_reset;
input i_oe;
input [7:0] i_data;
output wire [7:0] o_data;
inout io_pin;
 
wire feedback;
wire oe_for_fabric__unconnected;
wire [1:0] local_shiftout__unconnected;
wire local_tbyte_out__unconnected;
wire send_to_iob;
wire oe_for_iob;
wire [1:0] iserdes_shiftout__unconnected;
 
OSERDESE2 #(
.DATA_RATE_OQ("DDR"),
.DATA_RATE_TQ("BUF"),
.DATA_WIDTH(8), // 8 data wires sent per clkdiv
.INIT_OQ(1'b1),
.SERDES_MODE("MASTER"),
//
.TRISTATE_WIDTH(1),
.INIT_TQ(1'b1),
.TBYTE_CTL("FALSE"),
.TBYTE_SRC("FALSE")
) oserdes_i(
.CLK(i_clk_fast),
.CLKDIV(i_clk_slow),
.OCE(1'b1),
.OFB(feedback),
.OQ(send_to_iob),
.RST(i_reset),
//
.TCE(1'b1),
.TQ(oe_for_iob),
.TFB(oe_for_fabric__unconnected),
.T1(~i_oe), .T2(~i_oe), .T3(~i_oe), .T4(~i_oe),
//
.SHIFTOUT1(local_shiftout__unconnected[0]),
.SHIFTOUT2(local_shiftout__unconnected[1]),
.SHIFTIN1(1'b0),
.SHIFTIN2(1'b0),
.TBYTEIN(1'b0),
.TBYTEOUT(local_tbyte_out__unconnected),
//
// And now for the actual data we wish to send
//
.D1(i_data[0]), .D2(i_data[1]),
.D3(i_data[2]), .D4(i_data[3]),
.D5(i_data[4]), .D6(i_data[5]),
.D7(i_data[6]), .D8(i_data[7])
);
 
IOBUF iobuf_i(
.T(oe_for_iob),
.I(send_to_iob),
.IO(io_pin),
.O(input_from_iobuf));
 
ISERDESE2 #(
.DATA_RATE("DDR"),
.DATA_WIDTH(8), // 8 data wires sent per clkdiv
.INTERFACE_TYPE("OVERSAMPLE"),
.IOBDELAY("NONE"),
.NUM_CE(1),
.OFB_USED("FALSE"),
.SERDES_MODE("MASTER")
) iserdes_i(
.BITSLIP(1'b0),
.CE1(1'b1),
.CE2(1'b1),
.CLK(i_clk_fast),
.CLKB(i_clk_fast_inv),
.CLKDIV(i_clk_slow),
.CLKDIVP(1'b0), // Only used in MEMORY_DDR3 mode?
.D(input_from_iobuf),
.DDLY(1'b0),
.DYNCLKDIVSEL(1'b0),
.DYNCLKSEL(1'b0),
.O(iserdes_unconnected_output),
.OCLK(i_clk_fast),
.OCLKB(i_clk_fast_inv),
.OFB(feedback),
.Q1(o_data[0]), .Q2(o_data[1]),
.Q3(o_data[2]), .Q4(o_data[3]),
.Q5(o_data[4]), .Q6(o_data[5]),
.Q7(o_data[6]), .Q8(o_data[7]),
.RST(i_reset),
.SHIFTIN1(1'b0), .SHIFTIN2(1'b0),
.SHIFTOUT1(iserdes_shiftout__unconnected[0]),
.SHIFTOUT2(iserdes_shiftout__unconnected[1])
);
 
endmodule
 
/rtl/ddr3insert.v
0,0 → 1,198
////////////////////////////////////////////////////////////////////////////////
//
// Filename: ddr3insert.v
//
// Project: A wishbone controlled DDR3 SDRAM memory controller.
//
// Purpose: Since the DDR3 RAM requires I/O resources not available
// in Verilog alone, this insert (i.e. include file) is designed
// to be included from a top-level block that would otherwise use the
// DDR3 SDRAM. It is meant to encapsulate the I/O resource requirements
// and connections required to make the DDR3 SDRAM work.
//
//
// This file is not a module in its own right, but rather a file
// included in a larger module.
//
//
// Creator: Dan Gisselquist, Ph.D.
// Gisselquist Technology, LLC
//
////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2015-2016, Gisselquist Technology, LLC
//
// This program is free software (firmware): you can redistribute it and/or
// modify it under the terms of the GNU General Public License as published
// by the Free Software Foundation, either version 3 of the License, or (at
// your option) any later version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program. (It's in the $(ROOT)/doc directory, run make with no
// target there if the PDF file isn't present.) If not, see
// <http://www.gnu.org/licenses/> for a copy.
//
// License: GPL, v3, as defined and found on www.gnu.org,
// http://www.gnu.org/licenses/gpl.html
//
//
////////////////////////////////////////////////////////////////////////////////
//
//
 
// EXTERNAL PINS (BOTH INPUT AND OUTPUT):
// o_ddr_reset_n, o_ddr_cke, o_ddr_ck_p, o_ddr_ck_n
// o_ddr_cs_n, o_ddr_ras_n, o_ddr_cas_n, o_ddr_we_n,
// io_ddr_dqs_p, io_ddr_dqs_n,
// o_ddr_addr, o_ddr_ba,
// io_ddr_data, o_ddr_dm, o_ddr_odt
//
// INPUTS: (from elsewhere in the toplevel module)
// pwr_reset True for one clock at power on
// i_clk 200 MHz clock used in fabric
// clk_for_ddr 800 MHz clock to send to memory clk pins
// mem_serial_clk 800 MHz clock to drive serdes's
// mem_serial_clk_inv The inverse of the 800 MHz clock ...
//
//
// LOCAL VARIABLES PROVIDED:
// (These come from the controller)
// [3:0] w_ddr_cs_n, w_ddr_ras_n, w_ddr_cas_n, w_ddr_we_n
// [11:0] w_ddr_ba, divided into
// { w_ddr_ba[11:9], w_ddr_ba[8:6], w_ddr[5:3], w_ddr_ba[2:0] }
// [55:0] w_ddr_addr
// { w_ddr_addr[55:42], w_ddr_addr[41:28], w_ddr_addr[27:14],
// w_ddr_addr[13:0] }
// [7:0] w_ddr_odt // On-die termination
// [7:0] w_ddr_odt // On-die termination
// [15:0] w_ddr_dm // Data mask, headed to memory
// [127:0] wo_ddr_data // Data going to the memory
// [127:0] wi_ddr_data // The data returned by the memory
//
//
 
//
wire w_ddr_reset_n, w_ddr_cke, w_ddr_bus_oe;
wire [26:0] w_ddr_cmd_a, w_ddr_cmd_b;
wire [63:0] wi_ddr_data, wo_ddr_data;
wire [127:0] wide_ddr_data;
 
//
//
// Wires for setting up the DDR3 memory
//
//
 
// First, let's set up the clock(s)
xoddrserdesb ddrclk(mem_serial_clk, i_clk, pwr_reset, 8'h66,
o_ddr_ck_p, o_ddr_ck_n);
 
wire [7:0] w_udqs_in, w_ldqs_in;
 
xioddrserdesb ddrudqs(mem_serial_clk, mem_serial_clk_inv, i_clk,
~w_ddr_reset_n, w_ddr_cmd_a[0],
(w_ddr_cmd_b[0])? 8'h66 : 8'h06,
w_udqs_in,
io_ddr_dqs_p[1], io_ddr_dqs_n[1]);
 
xioddrserdesb ddrldqs(mem_serial_clk, mem_serial_clk_inv, i_clk,
~w_ddr_reset_n, w_ddr_cmd_a[0],
(w_ddr_cmd_b[0])? 8'h66 : 8'h06,
w_ldqs_in,
io_ddr_dqs_p[0], io_ddr_dqs_n[0]);
 
// The command wires: CS_N, RAS_N, CAS_N, and WE_N
xoddrserdes ddrcsn(mem_serial_clk, i_clk, ~w_ddr_reset_n,
{ w_ddr_cmd_a[26], w_ddr_cmd_a[26],
w_ddr_cmd_a[26], w_ddr_cmd_a[26],
w_ddr_cmd_b[26], w_ddr_cmd_b[26],
w_ddr_cmd_b[26], w_ddr_cmd_b[26] }, o_ddr_cs_n);
 
xoddrserdes ddrrasn(mem_serial_clk, i_clk, ~w_ddr_reset_n,
{ w_ddr_cmd_a[25], w_ddr_cmd_a[25],
w_ddr_cmd_a[25], w_ddr_cmd_a[25],
w_ddr_cmd_b[25], w_ddr_cmd_b[25],
w_ddr_cmd_b[25], w_ddr_cmd_b[25] }, o_ddr_ras_n);
 
xoddrserdes ddrcasn(mem_serial_clk, i_clk, ~w_ddr_reset_n,
{ w_ddr_cmd_a[24], w_ddr_cmd_a[24],
w_ddr_cmd_a[24], w_ddr_cmd_a[24],
w_ddr_cmd_b[24], w_ddr_cmd_b[24],
w_ddr_cmd_b[24], w_ddr_cmd_b[24] }, o_ddr_cas_n);
 
xoddrserdes ddrwen(mem_serial_clk, i_clk, ~w_ddr_reset_n,
{ w_ddr_cmd_a[23], w_ddr_cmd_a[23],
w_ddr_cmd_a[23], w_ddr_cmd_a[23],
w_ddr_cmd_b[23], w_ddr_cmd_b[23],
w_ddr_cmd_b[23], w_ddr_cmd_b[23] }, o_ddr_we_n);
 
// Data mask wires, first the upper byte
xoddrserdes ddrudm(mem_serial_clk, i_clk, ~w_ddr_reset_n,
{ w_ddr_cmd_a[4], w_ddr_cmd_a[4],
w_ddr_cmd_a[2], w_ddr_cmd_a[2],
w_ddr_cmd_b[4], w_ddr_cmd_b[4],
w_ddr_cmd_b[2], w_ddr_cmd_b[2] }, o_ddr_dm[1]);
// then the lower byte
xoddrserdes ddrldm(mem_serial_clk, i_clk, ~w_ddr_reset_n,
{ w_ddr_cmd_a[3], w_ddr_cmd_a[3],
w_ddr_cmd_a[1], w_ddr_cmd_a[1],
w_ddr_cmd_b[3], w_ddr_cmd_b[3],
w_ddr_cmd_b[1], w_ddr_cmd_b[1] }, o_ddr_dm[0]);
 
// and the On-Die termination wire
xoddrserdes ddrodt(mem_serial_clk, i_clk, ~w_ddr_reset_n,
{ w_ddr_cmd_a[0], w_ddr_cmd_a[0],
w_ddr_cmd_a[0], w_ddr_cmd_a[0],
w_ddr_cmd_b[0], w_ddr_cmd_b[0],
w_ddr_cmd_b[0], w_ddr_cmd_b[0] }, o_ddr_odt);
 
//
// Now for the data, bank, and address wires
//
genvar k;
generate begin
//
for(k=0; k<16; k=k+1)
xioddrserdes ddrdata(mem_serial_clk, mem_serial_clk_inv, i_clk, ~w_ddr_reset_n,
w_ddr_bus_oe,
{ wo_ddr_data[48+k], wo_ddr_data[48+k],
wo_ddr_data[32+k], wo_ddr_data[32+k],
wo_ddr_data[16+k], wo_ddr_data[16+k],
wo_ddr_data[ k], wo_ddr_data[ k] },
{ wide_ddr_data[112+k], wide_ddr_data[96+k],
wide_ddr_data[ 80+k], wide_ddr_data[64+k],
wide_ddr_data[ 48+k], wide_ddr_data[32+k],
wide_ddr_data[ 16+k], wide_ddr_data[ k] },
io_ddr_data[k]);
//
for(k=0; k<3; k=k+1)
xoddrserdes ddrbank(mem_serial_clk, i_clk, ~w_ddr_reset_n,
{ w_ddr_cmd_a[20+k], w_ddr_cmd_a[20+k],
w_ddr_cmd_a[20+k], w_ddr_cmd_a[20+k],
w_ddr_cmd_b[20+k], w_ddr_cmd_b[20+k],
w_ddr_cmd_b[20+k], w_ddr_cmd_b[20+k] },
o_ddr_ba[k]);
//
for(k=0; k<14; k=k+1)
xoddrserdes ddraddr(mem_serial_clk, i_clk, ~w_ddr_reset_n,
{ w_ddr_cmd_a[ 6+k], w_ddr_cmd_a[ 6+k],
w_ddr_cmd_a[ 6+k], w_ddr_cmd_a[ 6+k],
w_ddr_cmd_b[ 6+k], w_ddr_cmd_b[ 6+k],
w_ddr_cmd_b[ 6+k], w_ddr_cmd_b[ 6+k] },
o_ddr_addr[k]);
//
 
for(k=0; k<64; k=k+1)
assign wi_ddr_data[k] = (w_ddr_bus_oe) ? wide_ddr_data[2*k+1]
: wide_ddr_data[2*k];
end endgenerate
 
assign o_ddr_reset_n = w_ddr_reset_n;
assign o_ddr_cke = w_ddr_cke;
 
 
/rtl/xoddrserdes.v
0,0 → 1,94
////////////////////////////////////////////////////////////////////////////////
//
// Filename: xoddrserdes.v
//
// Project: A wishbone controlled DDR3 SDRAM memory controller.
//
// Purpose: Provide DDR outputs at 8x the clock rate (with a 4x clock given)
// for such things as the memory clock output, and the data strobe
// output (DQS) which needs to be synchronous with the memory clock output.
//
// Creator: Dan Gisselquist, Ph.D.
// Gisselquist Technology, LLC
//
////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2015-2016, Gisselquist Technology, LLC
//
// This program is free software (firmware): you can redistribute it and/or
// modify it under the terms of the GNU General Public License as published
// by the Free Software Foundation, either version 3 of the License, or (at
// your option) any later version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program. (It's in the $(ROOT)/doc directory, run make with no
// target there if the PDF file isn't present.) If not, see
// <http://www.gnu.org/licenses/> for a copy.
//
// License: GPL, v3, as defined and found on www.gnu.org,
// http://www.gnu.org/licenses/gpl.html
//
//
////////////////////////////////////////////////////////////////////////////////
//
//
module xoddrserdes(i_clk_fast, i_clk_slow, i_reset, i_data, o_pin);
input i_clk_fast, i_clk_slow, i_reset;
input [7:0] i_data;
output o_pin;
 
wire local_monitor_pin__unconnected;
wire oe_for_fabric__unconnected;
wire [1:0] local_shiftout__unconnected;
wire local_tbyte_out__unconnected;
wire send_to_iob;
wire oe_for_iob;
 
OSERDESE2 #(
.DATA_RATE_OQ("DDR"),
.DATA_RATE_TQ("BUF"),
.DATA_WIDTH(8), // 8 data wires sent per clkdiv
.INIT_OQ(1'b1),
.SERDES_MODE("MASTER"),
//
.TRISTATE_WIDTH(1),
.INIT_TQ(1'b1),
.TBYTE_CTL("FALSE"),
.TBYTE_SRC("FALSE")
) oserdes_i(
.CLK(i_clk_fast),
.CLKDIV(i_clk_slow),
.OCE(1'b1),
.OFB(local_monitor_pin__unconnected),
.OQ(send_to_iob),
.RST(i_reset),
//
.TCE(1'b1),
.TQ(oe_for_iob),
.TFB(oe_for_fabric__unconnected),
.T1(1'b0), .T2(1'b0), .T3(1'b0), .T4(1'b0),
//
.SHIFTOUT1(local_shiftout__unconnected[0]),
.SHIFTOUT2(local_shiftout__unconnected[1]),
.SHIFTIN1(1'b0),
.SHIFTIN2(1'b0),
.TBYTEIN(1'b0),
.TBYTEOUT(local_tbyte_out__unconnected),
//
// And now for the actual data we wish to send
//
.D1(i_data[0]), .D2(i_data[1]),
.D3(i_data[2]), .D4(i_data[3]),
.D5(i_data[4]), .D6(i_data[5]),
.D7(i_data[6]), .D8(i_data[7])
);
 
OBUF iobuf_i(.I(send_to_iob), .O(o_pin));
 
endmodule
 
/rtl/wbddrsdram.v
84,8 → 84,10
i_wb_sel,
// Wishbone outputs
o_wb_ack, o_wb_stall, o_wb_data,
// Memory command wires
o_ddr_reset_n, o_ddr_cke, o_ddr_bus_oe,
o_ddr_cmd_a, o_ddr_cmd_b,
// And the data wires to go with them ....
o_ddr_data, i_ddr_data);
// These parameters are not really meant for adjusting from the
// top level. These are more internal variables, recorded here

powered by: WebSVN 2.1.0

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