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

Subversion Repositories vg_z80_sbc

[/] [vg_z80_sbc/] [trunk/] [rtl/] [ddr_wpath.v] - Rev 3

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

//----------------------------------------------------------------------------
//
// Wishbone DDR Controller -- fast write data-path
// 
// (c) Joerg Bornschein (<jb@capsec.org>)
//
//----------------------------------------------------------------------------
 
`include "ddr_include.v"
 
module ddr_wpath (
	input                  clk,
	input                  clk90,
	input                  reset,
	// CBA async fifo
	input                  cba_clk,
	input [`CBA_RNG]       cba_din,
	input                  cba_wr,
	output                 cba_full,
	// WDATA async fifo
	input                  wdata_clk,
	input [`WFIFO_RNG]     wdata_din,
	input                  wdata_wr,
	output                 wdata_full,
	// sample to rdata
	output                 sample,
	// DDR 
	output                 ddr_clk,
	output                 ddr_clk_n,
	output                 ddr_ras_n,
	output                 ddr_cas_n,
	output                 ddr_we_n,
	output [  `A_RNG]      ddr_a,
	output [ `BA_RNG]      ddr_ba,
	output [ `DM_RNG]      ddr_dm,
	output [ `DQ_RNG]      ddr_dq,
	output [`DQS_RNG]      ddr_dqs,
 	output                 ddr_dqs_oe
);
 
wire gnd = 1'b0;
wire vcc = 1'b1;
 
//----------------------------------------------------------------------------
// CBA async. fifo
//----------------------------------------------------------------------------
wire [`CBA_RNG]        cba_data;
wire                   cba_empty;
wire                   cba_ack;
 
wire                   cba_avail = ~cba_empty;
 
async_fifo #(
	.DATA_WIDTH( `CBA_WIDTH ),
	.ADDRESS_WIDTH( 3 )
) cba_fifo (
	.Data_out(   cba_data  ),
	.Empty_out(  cba_empty ),
	.ReadEn_in(  cba_ack   ),
	.RClk(       clk       ),
	//
	.Data_in(    cba_din   ),
	.WriteEn_in( cba_wr    ),
	.Full_out(   cba_full  ),
	.WClk(       cba_clk   ),
	.Clear_in(   reset     )
);
 
//----------------------------------------------------------------------------
// WDATA async. fifo
//----------------------------------------------------------------------------
wire [`WFIFO_RNG]      wdata_data;
wire                   wdata_empty;
wire                   wdata_ack;
 
wire                   wdata_avail = ~wdata_empty;
 
async_fifo #(
	.DATA_WIDTH( `WFIFO_WIDTH ),
	.ADDRESS_WIDTH( 3 )
) wdata_fifo (
	.Data_out(   wdata_data  ),
	.Empty_out(  wdata_empty ),
	.ReadEn_in(  wdata_ack   ),
	.RClk(      ~clk90       ),
	//
	.Data_in(    wdata_din   ),
	.WriteEn_in( wdata_wr    ),
	.Full_out(   wdata_full  ),
	.WClk(       wdata_clk   ),
	.Clear_in(   reset       )
);
 
 
//----------------------------------------------------------------------------
// Handle CBA 
//----------------------------------------------------------------------------
reg  [3:0]      delay_count;
 
reg [`CBA_RNG]  ddr_cba;
wire [`CBA_RNG] CBA_NOP = { `DDR_CMD_NOP, 15'b0 };
 
assign cba_ack = cba_avail & (delay_count == 0);
 
wire [`CMD_RNG] cba_cmd = cba_data[(`CBA_WIDTH-1):(`CBA_WIDTH-3)];
 
always @(posedge clk)
begin
	if (reset) begin
		delay_count <= 0;
		ddr_cba     <= CBA_NOP;
	end else begin
		if (delay_count != 0) begin
			delay_count <= delay_count - 1;
			ddr_cba     <= CBA_NOP;
        end
 
		if (!cba_ack) begin
			ddr_cba  <= CBA_NOP;
		end else begin
			ddr_cba <= cba_data;
 
			case (cba_cmd)
				`DDR_CMD_MRS   : delay_count <= 2;
				`DDR_CMD_AR    : delay_count <= 14;
				`DDR_CMD_ACT   : delay_count <= 4;
				`DDR_CMD_PRE   : delay_count <= 2;
				`DDR_CMD_READ  : delay_count <= 6;   // XXX
				`DDR_CMD_WRITE : delay_count <= 8;   // XXX
			endcase
		end
	end
end
 
 
//----------------------------------------------------------------------------
// READ-SHIFT-REGISTER
//----------------------------------------------------------------------------
reg [0:7] read_shr;
wire      read_cmd = (cba_cmd == `DDR_CMD_READ) & cba_ack;
assign    sample   = read_shr[1];
 
always @(posedge clk)
begin
	if (reset)
		read_shr <= 'b0;
	else begin
		if (read_cmd)
 			read_shr <= { 8'b00011111 };
 		else
 			read_shr <= { read_shr[1:7], 1'b0 };
 	end
end
 
//----------------------------------------------------------------------------
// WRITE-SHIFT-REGISTER
//----------------------------------------------------------------------------
 
reg [0:4] write_shr;
wire      write_cmd = (cba_cmd == `DDR_CMD_WRITE) & cba_ack;
 
always @(posedge clk)
begin
	if (reset)
		write_shr <= 'b0;
	else begin
		if (write_cmd)
 			write_shr <= { 5'b11111 };
 		else
 			write_shr <= { write_shr[1:4], 1'b0 };
 	end
end
 
//----------------------------------------------------------------------------
// DDR_DQS, DDR_DQS_OE
//----------------------------------------------------------------------------
genvar i;
 
reg ddr_dqs_oe_reg;
assign ddr_dqs_oe = ddr_dqs_oe_reg;
 
always @(negedge clk)
begin
  ddr_dqs_oe_reg <= write_shr[0];
end
 
FDDRRSE ddr_clk_reg (
	.Q(   ddr_clk      ),
	.C0(  clk90        ),
	.C1( ~clk90        ),
	.CE(  vcc          ),
	.D0(  vcc          ),
	.D1(  gnd          ),
	.R(   gnd          ),
	.S(   gnd          )
);
 
FDDRRSE ddr_clk_n_reg (
	.Q(   ddr_clk_n    ),
	.C0(  clk90        ),
	.C1( ~clk90        ),
	.CE(  vcc          ),
	.D0(  gnd          ),
	.D1(  vcc          ),
	.R(   gnd          ),
	.S(   gnd          )
);
 
 
generate 
for (i=0; i<`DQS_WIDTH; i=i+1) begin : DQS
	FDDRRSE ddr_dqs_reg (
		.Q(   ddr_dqs[i]   ),
		.C0(  clk          ),
		.C1( ~clk          ),
		.CE(  vcc          ),
		.D0(  write_shr[1] ),
		.D1(  gnd          ),
		.R(   gnd          ),
		.S(   gnd          )
	);
end
endgenerate
 
 
//----------------------------------------------------------------------------
// DQ data output
//----------------------------------------------------------------------------
wire [`DQ_RNG] buf_d0;        
wire [`DM_RNG] buf_m0;
reg  [`DQ_RNG] buf_d1;       // pipleine high word data
reg  [`DM_RNG] buf_m1;       // pipleine high word mask
 
assign buf_d0 = wdata_data[`WFIFO_D0_RNG];
assign buf_m0 = wdata_data[`WFIFO_M0_RNG];
 
always @(negedge clk90)
begin
	buf_d1 <= wdata_data[`WFIFO_D1_RNG];
	buf_m1 <= wdata_data[`WFIFO_M1_RNG];
end
 
assign wdata_ack = write_shr[1];
 
// generate DDR_DQ register
generate 
for (i=0; i<`DQ_WIDTH; i=i+1) begin : DQ_REG
	FDDRRSE ddr_dq_reg (
		.Q(   ddr_dq[i]    ),
		.C0( ~clk90        ),
		.C1(  clk90        ),
		.CE(  vcc          ),
		.D0(  buf_d0[i]    ),
		.D1(  buf_d1[i]    ),
		.R(   gnd          ),
		.S(   gnd          )
	);
end
endgenerate
 
// generate DDR_DM register
generate 
for (i=0; i<`DM_WIDTH; i=i+1) begin : DM_REG
	FDDRRSE ddr_dm_reg (
		.Q(   ddr_dm[i]    ),
		.C0( ~clk90        ),
		.C1(  clk90        ),
		.CE(  vcc          ),
		.D0(  buf_m0[i]    ),
		.D1(  buf_m1[i]    ),
		.R(   gnd          ),
		.S(   gnd          )
	);
end
endgenerate
 
//----------------------------------------------------------------------------
// Connect ddr_cba to actual DDR pins
//----------------------------------------------------------------------------
assign ddr_a     = ddr_cba[(`A_WIDTH-1):0];
assign ddr_ba    = ddr_cba[(`A_WIDTH+`BA_WIDTH-1):(`A_WIDTH)];
assign ddr_ras_n = ddr_cba[(`CBA_WIDTH-1)];
assign ddr_cas_n = ddr_cba[(`CBA_WIDTH-2)];
assign ddr_we_n  = ddr_cba[(`CBA_WIDTH-3)];
 
endmodule
 

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.