📄 hssdrc_data_path_p1.v
字号:
//
// Project : High-Speed SDRAM Controller with adaptive bank management and command pipeline
//
// Project Nick : HSSDRC
//
// Version : 1.0-beta
//
// Revision : $Revision: 1.1 $
//
// Date : $Date: 2008-03-06 13:52:43 $
//
// Workfile : hssdrc_data_path_p1.v
//
// Description : sdram data (data & mask) path unit
//
// HSSDRC is licensed under MIT License
//
// Copyright (c) 2007-2008, Denis V.Shekhalev (des00@opencores.org)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
`include "hssdrc_timescale.vh"
`include "hssdrc_timing.vh"
`include "hssdrc_define.vh"
module hssdrc_data_path_p1 (
clk ,
reset ,
sclr ,
//
sys_wdata ,
sys_wdatam ,
sys_use_wdata ,
sys_vld_rdata ,
sys_chid_o ,
sys_rdata ,
//
arb_read ,
arb_write ,
arb_chid ,
arb_burst ,
//
dq ,
dqm
);
input wire clk;
input wire reset;
input wire sclr;
//--------------------------------------------------------------------------------------------------
// system data interface
//--------------------------------------------------------------------------------------------------
input data_t sys_wdata ;
input datam_t sys_wdatam ;
output logic sys_use_wdata ;
output logic sys_vld_rdata ;
output chid_t sys_chid_o ;
output data_t sys_rdata ;
//--------------------------------------------------------------------------------------------------
// interface from arbiter throw multiplexer
//--------------------------------------------------------------------------------------------------
input wire arb_read ;
input wire arb_write ;
input chid_t arb_chid ;
input sdram_burst_t arb_burst ;
//--------------------------------------------------------------------------------------------------
// interface sdram chip
//--------------------------------------------------------------------------------------------------
inout wire [pDataBits-1 :0] dq;
output logic [pDatamBits-1 :0] dqm;
//--------------------------------------------------------------------------------------------------
// Mask paramters count via pBL, pCL parameters only for clarify.
// unit has been designed to use fixed lengh mask patterns
//--------------------------------------------------------------------------------------------------
localparam cWDataMask = cSdramBL - 1; // - 1 cycle for write command itself
localparam cRDataMask = cSdramBL - 1 + pCL - 2; // - 1 cycle for read command itself,
// - 2 cycle for read dqm latency
localparam cDataMask = max(cWDataMask, cRDataMask);
localparam cReadAllign = pCL + 1 + 1; // + 1 is capture register cycle
// + 1 is additition command latency
//--------------------------------------------------------------------------------------------------
//
//--------------------------------------------------------------------------------------------------
data_t wdata_delayed;
logic use_wdata_delayed;
logic [3:0] use_wdata_srl;
wire use_wdata;
wire use_wdatam;
logic [cDataMask-1 : 0] datam_srl;
logic datam;
logic [3:0] vld_rdata_srl;
logic vld_rdata;
logic vld_rdata_allign_srl [cReadAllign-1 : 0];
chid_t chid_srl [3:0];
chid_t chid;
chid_t chid_allign_srl [cReadAllign-1 : 0];
//--------------------------------------------------------------------------------------------------
// use write data & mask
//--------------------------------------------------------------------------------------------------
always_ff @(posedge clk or posedge reset) begin : use_wdata_generate
if (reset)
use_wdata_srl <= 4'b0000;
else if (sclr)
use_wdata_srl <= 4'b0000;
else if (arb_write)
unique case (arb_burst)
2'h0 : use_wdata_srl <= 4'b1000;
2'h1 : use_wdata_srl <= 4'b1100;
2'h2 : use_wdata_srl <= 4'b1110;
2'h3 : use_wdata_srl <= 4'b1111;
endcase
else
use_wdata_srl <= (use_wdata_srl << 1);
end
assign use_wdata = use_wdata_srl[3];
assign use_wdatam = use_wdata_srl[3];
//
// read/write data mask for command terminate
//
always_ff @(posedge clk or posedge reset) begin : data_burst_mask_generate
if (reset)
datam_srl <= '0;
else if (sclr)
datam_srl <= '0;
else begin
if (arb_write)
datam_srl <= WriteMaskBits(arb_burst);
else if (arb_read)
datam_srl <= ReadMaskBits(arb_burst);
else
datam_srl <= (datam_srl << 1);
end
end
always_ff @(posedge clk or posedge reset) begin : data_mask_generate
if (reset)
datam <= 1'b0;
else if (sclr)
datam <= 1'b0;
else begin
if (arb_write)
datam <= 1'b0;
else if (arb_read)
datam <= FirstReadMaskBit(arb_burst);
else
datam <= datam_srl [cDataMask-1];
end
end
//
// dqm
//
always_ff @(posedge clk or posedge reset) begin
if (reset)
dqm <= '0;
else if (sclr)
dqm <= '0;
else
dqm <= use_wdatam ? sys_wdatam : {pDatamBits{datam}};
end
//--------------------------------------------------------------------------------------------------
// write data request
//--------------------------------------------------------------------------------------------------
`ifndef HSSDRC_COMBINATORY_USE_WDATA
assign sys_use_wdata = use_wdata;
`else
logic [2:0] use_wdata_srl_small;
always_ff @(posedge clk or posedge reset) begin : use_wdata_small_generate
if (reset)
use_wdata_srl_small <= 3'b000;
else if (sclr)
use_wdata_srl_small <= 3'b000;
else if (arb_write)
unique case (arb_burst)
2'h0 : use_wdata_srl_small <= 3'b000;
2'h1 : use_wdata_srl_small <= 3'b100;
2'h2 : use_wdata_srl_small <= 3'b110;
2'h3 : use_wdata_srl_small <= 3'b111;
endcase
else
use_wdata_srl_small <= (use_wdata_srl_small << 1);
end
assign sys_use_wdata = arb_write | use_wdata_srl_small[2];
`endif
//
// dq
//
always_ff @(posedge clk) begin : wdata_reclock
wdata_delayed <= sys_wdata;
end
always_ff @(posedge clk or posedge reset) begin : use_wdata_reclock
if (reset)
use_wdata_delayed <= 1'b0;
else
use_wdata_delayed <= use_wdata;
end
assign dq = use_wdata_delayed ? wdata_delayed : {pDataBits{1'bz}};
//--------------------------------------------------------------------------------------------------
// read data
//--------------------------------------------------------------------------------------------------
always_ff @(posedge clk or posedge reset) begin : vld_rdata_generate
if (reset)
vld_rdata_srl <= 4'b0000;
else if (sclr)
vld_rdata_srl <= 4'b0000;
else if (arb_read)
unique case (arb_burst)
2'h0 : vld_rdata_srl <= 4'b1000;
2'h1 : vld_rdata_srl <= 4'b1100;
2'h2 : vld_rdata_srl <= 4'b1110;
2'h3 : vld_rdata_srl <= 4'b1111;
endcase
else
vld_rdata_srl <= (vld_rdata_srl << 1);
end
assign vld_rdata = vld_rdata_srl [3];
//
//
//
always_ff @(posedge clk) begin : chid_rdata_generate
int i;
if (arb_read) begin
for (i = 0; i < 4; i++)
chid_srl[i] <= arb_chid; // load all with chid
end
else begin
for (i = 1; i < 4; i++)
chid_srl[i] <= chid_srl[i-1]; // shift left with last data stable
end
end
assign chid = chid_srl [3];
//
//
//
always_ff @(posedge clk or posedge reset) begin : vld_rdata_allign_generate
int i;
if (reset) begin
for (i = 0; i < cReadAllign; i++)
vld_rdata_allign_srl[i] <= 1'b0;
end
else if (sclr) begin
for (i = 0; i < cReadAllign; i++)
vld_rdata_allign_srl[i] <= 1'b0;
end
else begin
vld_rdata_allign_srl[0] <= vld_rdata; // shift left
for (i = 1; i < cReadAllign; i++)
vld_rdata_allign_srl[i] <= vld_rdata_allign_srl [i-1];
end
end
assign sys_vld_rdata = vld_rdata_allign_srl [cReadAllign-1];
//
//
//
always_ff @(posedge clk) begin : chid_allign_generate
int i;
chid_allign_srl[0] <= chid; // shift left
for (i = 1; i < cReadAllign; i++)
chid_allign_srl[i] <= chid_allign_srl[i-1];
end
assign sys_chid_o = chid_allign_srl [cReadAllign-1];
//
//
//
always_ff @(posedge clk) begin : rdata_reclock
sys_rdata <= dq;
end
//--------------------------------------------------------------------------------------------------
// function to count write bit mask pattern for different burst value and
// for different Cas Latency paramter value
// full burst == 2'h3 no need to be masked
//--------------------------------------------------------------------------------------------------
function automatic bit [cDataMask-1:0] WriteMaskBits (input bit [1:0] burst);
if (pCL == 3) begin
WriteMaskBits = 4'b0000;
case (burst)
2'h0 : WriteMaskBits = 4'b1110;
2'h1 : WriteMaskBits = 4'b0110;
2'h2 : WriteMaskBits = 4'b0010;
endcase
end
else if (pCL == 2) begin
WriteMaskBits = 3'b000;
case (burst)
2'h0 : WriteMaskBits = 3'b111;
2'h1 : WriteMaskBits = 3'b011;
2'h2 : WriteMaskBits = 3'b001;
endcase
end
else if (pCL == 1) begin
WriteMaskBits = 3'b000;
case (burst)
2'h0 : WriteMaskBits = 3'b111;
2'h1 : WriteMaskBits = 3'b011;
2'h2 : WriteMaskBits = 3'b001;
endcase
end
else begin
WriteMaskBits = '0;
end
endfunction
//--------------------------------------------------------------------------------------------------
// function to count first read bit mask pattern for different burst value and
// for different Cas Latency paramter value
//--------------------------------------------------------------------------------------------------
function automatic bit FirstReadMaskBit (input bit [1:0] burst);
if ((pCL == 1) && (burst == 0))
FirstReadMaskBit = 1'b1;
else
FirstReadMaskBit = 1'b0;
endfunction
//--------------------------------------------------------------------------------------------------
// function to count read bit mask pattern for different burst value and
// for different Cas Latency paramter value
// full burst == 2'h3 no need to be masked
//--------------------------------------------------------------------------------------------------
function automatic bit [cDataMask-1:0] ReadMaskBits (input bit [1:0] burst);
if (pCL == 3) begin
ReadMaskBits = 4'b0000;
case (burst)
2'h0 : ReadMaskBits = 4'b0111;
2'h1 : ReadMaskBits = 4'b0011;
2'h2 : ReadMaskBits = 4'b0001;
endcase
end
else if (pCL == 2) begin
ReadMaskBits = 3'b000;
case (burst)
2'h0 : ReadMaskBits = 3'b111;
2'h1 : ReadMaskBits = 3'b011;
2'h2 : ReadMaskBits = 3'b001;
endcase
end
else if (pCL == 1) begin
ReadMaskBits = 3'b000;
case (burst)
2'h0 : ReadMaskBits = 3'b110;
2'h1 : ReadMaskBits = 3'b110;
2'h2 : ReadMaskBits = 3'b010;
endcase
end
else begin
ReadMaskBits = '0;
end
endfunction
endmodule
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -