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

Subversion Repositories openarty

[/] [openarty/] [trunk/] [rtl/] [ddr3insert.v] - Rev 53

Go to most recent revision | Compare with Previous | Blame | View Log

////////////////////////////////////////////////////////////////////////////////
//
// 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;
 
 
 

Go to most recent revision | 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.