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 |