Mini Project Code
Mini Project Code
sys_add;
outputsys_init_done;
output [3:0]
istate;
output [3:0]
cstate;
output
wren;
output [RA_MSB:CA_LSB]
addr;
istate;
reg [3:0]
cstate;
reg [3:0]
cs_clkcnt;
reg [3:0]
i_clkcnt;
addr;
wren;
q;
1
regref_req_c;
regref_req;
reglatch_ref_req;
regref_ack;
regsys_adsn_r;
reg [RA_MSB:CA_LSB]
sys_add_r ;
regsys_r_wn_r;
// local definitions
`defineendOf_tRP_ii_clkcnt == NUM_CLK_tRP
`defineendOf_tRFC_ii_clkcnt == NUM_CLK_tRFC
`defineendOf_tMRD_ii_clkcnt == NUM_CLK_tMRD
`defineendOf_tRPcs_clkcnt == NUM_CLK_tRP
`defineendOf_tRFCcs_clkcnt == NUM_CLK_tRFC
`defineendOf_tMRDcs_clkcnt == NUM_CLK_tMRD
`defineendOf_tRCDcs_clkcnt == NUM_CLK_tRCD
`defineendOf_Cas_Latencycs_clkcnt == NUM_CLK_CL
`defineendOf_Read_Burstcs_clkcnt == NUM_CLK_READ - 1
`defineendOf_Write_Burstcs_clkcnt == NUM_CLK_WRITE - 1
`defineendOf_tDALcs_clkcnt == NUM_CLK_WAIT
// INIT_FSM state machine
always @(posedgeclk or negedgereset_n) begin
if (reset_n == 1'b0) begin
istate<= i_IDLE;
load_mrs_done<= 1'b0;
load_mrs_af<= 1'b0;
end else
2
case (istate)
i_IDLE: begin
istate<= i_PRE;
end
i_PRE: begin
// precharge all
if (`endOf_tRP_i)
istate<= load_mrs_done ? i_AR1 :i_EMRS;
end
i_EMRS: begin //Enable DLL in Extended Mode Reg
istate<= (NUM_CLK_tMRD == 0) ? i_MRS :i_tMRD;
end
i_tMRD: begin // wait until tMRD satisfied
if (`endOf_tMRD_i)
istate<= load_mrs_done ? (load_mrs_af ?i_ready : i_PRE) : i_MRS;
end
i_MRS: begin
load_mrs_done<= 1'b1;
istate<= (NUM_CLK_tMRD == 0) ? (load_mrs_af ?i_ready : i_PRE) : i_tMRD;
end
i_AR1: begin
// auto referesh
end
i_tRFC1: begin // wait until tRFC satisfied
if (`endOf_tRFC_i) istate<= i_AR2;
end
i_AR2: begin
// auto referesh
istate<= i_ready;
end
default: begin
istate<= i_NOP;
end
endcase
end
// sys_init_done generation
always @(posedgeclk or negedgereset_n) begin
if (reset_n == 1'b0) begin
sys_init_done<= 0;
end else begin
case (istate)
i_ready: sys_init_done<= 1;
default: sys_init_done<= 0;
4
endcase
end
end
// Latching the address and looking at
// READ or Write request during Refresh and address latching
always @(posedgeclk or negedgereset_n) begin
if (reset_n == 1'b0) begin
rd_wr_req_during_ref_req<= 1'b0;
addr<= {RA_MSB {1'b0}};
sys_adsn_r<= 1'b0;
sys_add_r<= {RA_MSB {1'b0}};
sys_r_wn_r<= 1'b0;
end else begin
sys_adsn_r<= sys_adsn;
sys_add_r<= sys_add;
sys_r_wn_r<= sys_r_wn;
// Store the address whenever there is address strobe
if (!sys_adsn_r&&sys_init_done)
addr<= sys_add_r;
// New (rd or wr) during refresh command getting serviced
case (cstate)
c_idle: begin
if (!rd_wr_req_during_ref_req)
if (!sys_adsn_r&&latch_ref_req)
rd_wr_req_during_ref_req<= 1'b1;
else
rd_wr_req_during_ref_req<= 1'b0;
5
end
// After completing write (c_tDAL)
// Durinfc_tDAL, system can make a request and
// refresh can be pending.
c_tRFC,
c_tDAL,
c_AR: begin
if (!sys_adsn_r)
rd_wr_req_during_ref_req<= sys_init_done;
end
default: begin
rd_wr_req_during_ref_req<= 1'b0;
end
endcase
end
end
// CMD_FSM state machine
always @(posedgeclk or negedgereset_n) begin
if (reset_n == 1'b0) begin
cstate<= c_idle;
wren<= 1'b0;
end else begin
case (cstate)
c_idle: // wait until refresh request or addr strobe asserted
if (latch_ref_req&&sys_init_done)
cstate<= c_AR;
else if ((!sys_adsn_r&&sys_init_done) || rd_wr_req_during_ref_req)
6
cstate<= c_ACTIVE;
c_ACTIVE: // assert row/bank addr
if (NUM_CLK_tRCD == 0)
cstate<= (sys_r_wn_r) ? c_READA :c_WRITEA;
else
cstate<= c_tRCD;
c_tRCD: // wait until tRCD satisfied
if (`endOf_tRCD)
cstate<= (sys_r_wn_r) ? c_READA :c_WRITEA;
c_READA: // assert col/bank addr for read with auto-precharge
cstate<= c_cl;
c_cl:
// CASn latency
// auto-refresh
<= 0;
ref_req<= 1'b0;
end else begin
q[0]
<= ~(q[10]^q[8]^ref_req_c);
if (REF_INTERVAL == REF_INT_NON128MBIT_100MHZ)
/*605*/ref_req_c =
q[10]&q[9]&~q[8]&~q[7]&~q[6]&~q[5]&~q[4]&~q[3]&q[2]&~q[1]&q[0];
if (REF_INTERVAL == REF_INT_128MBIT_133MHZ)
/*300*/ref_req_c =
~q[10]&q[9]&q[8]&~q[7]&~q[6]&~q[5]&~q[4]&~q[3]&~q[2]&~q[1]&~q[0];
if (REF_INTERVAL == REF_INT_NON128MBIT_133MHZ)
/*350*/ref_req_c =
~q[10]&q[9]&q[8]&~q[7]&q[6]&~q[5]&q[4]&~q[3]&~q[2]&~q[1]&~q[0];
end
always @(posedgeclk or negedgereset_n) begin
if (reset_n == 1'b0) begin
ref_ack<= 0;
latch_ref_req<= 1'b0;
end else begin
if (ref_req)
latch_ref_req<= 1'b1;
else if (ref_ack)
latch_ref_req<= 1'b0;
case (cstate)
c_idle:
ref_ack<= sys_init_done&&latch_ref_req;
default:
ref_ack<= 1'b0;
endcase
end
end
// Clock Counter
i_tRP:
i_syncResetClkCNT= (`endOf_tRP_i) ? 1 : 0;
i_tMRD:
i_syncResetClkCNT= (`endOf_tMRD_i) ? 1 : 0;
i_tRFC1,
i_tRFC2:
i_syncResetClkCNT= (`endOf_tRFC_i) ? 1 : 0;
default:
i_syncResetClkCNT= 1;
endcase
end
// cstatesyncResetClkCNT generation
always @(cstate or cs_clkcnt) begin
case (cstate)
c_idle:
cs_syncResetClkCNT= 1;
c_ACTIVE:
cs_syncResetClkCNT= (NUM_CLK_tRCD == 0) ? 1 : 0;
c_tRCD:
cs_syncResetClkCNT= (`endOf_tRCD) ? 1 : 0;
c_tRFC:
cs_syncResetClkCNT= (`endOf_tRFC) ? 1 : 0;
c_cl:
cs_syncResetClkCNT= (`endOf_Cas_Latency) ? 1 : 0;
c_rdata:
cs_syncResetClkCNT= (cs_clkcnt == NUM_CLK_READ) ? 1 : 0;
c_wdata:
11
cs_syncResetClkCNT= (`endOf_Write_Burst) ? 1 : 0;
c_tDAL:
cs_syncResetClkCNT= (`endOf_tDAL) ? 1 : 0;
default:
cs_syncResetClkCNT= 1;
endcase // case(cstate)
end
endmodule
//DATA PATH
`timescale 1ns / 1ps
module ddr_data( clk, clk2x, reset_n, sys_dataout, sys_dataout_en, sys_datain, sys_dmsel,cstate
wren, sys_rdyn, dqin, dqout, dqout_en, dqsout, dqsout_en, dqm_out );
`include "ddr_par.v"
input
input[3:0]
cstate;
input [DSIZE-1:0]
sys_datain;
// System data in
input [DSIZE/8-1:0]
sys_dmsel;
input [DSIZE/2-1:0]
dqin;
output [DSIZE/2-1:0]
dqout_en;
output [DSIZE/2-1:0]
dqout;
output [DSIZE/16-1:0]
dqsout_en;
output [DSIZE/16-1:0]
dqsout;
output
sys_rdyn;
output [DSIZE-1:0]
sys_dataout
/*synthesis dout="" */ ;
12
output [DSIZE-1:0]
output [DSIZE/16-1:0]
dqm_out;
reg [DSIZE/2-1:0]
dqout_en
reg [DSIZE/2-1:0]
dqout
reg [DSIZE/16-1:0]
dqsout_en
reg [DSIZE/16-1:0]
dqsout
reg
sys_rdyn;
reg [DSIZE-1:0]
reg [DSIZE/16-1:0]
signals
dqm_out
/*synthesis dout="" */ ;
/*synthesis syn_preserve=1 */ /*synthesis dout="" */ ;
/*synthesis dout="" */ ;
reg [DSIZE/2-1:0]
dqin_x_reg;
reg [DSIZE/2-1:0]
dqin_xn_reg;
reg [DSIZE/2-1:0]
dqin_xnx_reg;
reg [DSIZE/2-1:0]
reg [DSIZE/2-1:0]
dqout_reg;
reg [DSIZE/16-1:0]
dqm_outreg;
reg [DSIZE/2-1:0]
reg [DSIZE/16-1:0]
reg [DSIZE-1:0]
datain_nx ;
reg [DSIZE/8-1:0]
dmsel_nx ;
13
reg
dqsout_reg;
reg
select_lower_half;
reg
write_rdy_d1;
reg
write_rdy_d2;
reg
write_rdy_d3;
reg
read_rdy;
reg
read_rdy_d;
reg
write_rdy;
reg
wren_d2x;
reg
wren_dx;
reg [DSIZE/16-1:0]
dqsout_en_nx;
//--- WIRES
wire [DSIZE-1:0]
sys_dataout;
<= {DSIZE/2{1'b0}};
14
dqin_xnx_reg
<= {DSIZE/2{1'b0}};
end
else begin
dqin_x_reg
<= dqin_2x_sync_reg;
// For ORCA
dqout_and_dqsout_en <= {DSIZE/2+DSIZE/16 {1'b1}};
end
endcase
end
end
// Both dq_out, and dqout_en should be clocked by the
// same clock and the same edge (+ve clk2x). This is required
// otherwise PAR tool will not place output flops in PIC.
always @(posedge clk2x or negedge reset_n) begin
if (reset_n == 1'b0) begin
dqout_en
<= dqout_and_dqsout_en[DSIZE/2-1:0];
end
end
always @(negedge clk or negedge reset_n) begin
if (reset_n == 1'b0) begin
dqsout_en_nx
end
end
17
<= dqsout_en_nx;
end
end
// Generation of dqsout
always @(posedge clk2x or negedge reset_n) begin
if (reset_n == 1'b0) begin
wren_dx <= 1'b0;
end else begin
wren_dx <= wren_d2x ? ~wren_dx : 1'b0;
end
end
// Note that dqsout and dqsout_en are clocked
// with the same clock and the same edge (-ve clk2x)
always @(negedge clk2x or negedge reset_n) begin
if (reset_n == 1'b0) begin
dqsout_reg
dqsout
<= 1'b0;
<= {DSIZE/16{1'b0}};
<= wren_dx;
<= dqsout_reg;
end
18
end
// Generation of dqout
// Latch the system data on +ve clk
always @(negedge clk or negedge reset_n) begin
if (reset_n == 1'b0) begin
datain_nx <= {DSIZE{1'b0}};
dmsel_nx <= {DSIZE/8{1'b0}};
end else begin
datain_nx <= sys_datain[DSIZE-1:0];
dmsel_nx <= sys_dmsel[DSIZE/8-1:0];
end
end
// dqout_reg has two clocks (of clk2x) from sys_datain and datain_nx.
// Similarly for dqm_out.
// This is essential to meet the desired frequency.
always @(posedge clk2x or negedge reset_n) begin
if (reset_n == 1'b0) begin
wren_d2x
<= 1'b0;
select_lower_half
dqout_reg
dqm_outreg
dqout
dqm_out
<= 1'b0;
<= wren;
19
select_lower_half
dqout_reg
<= select_lower_half ? datain_nx[DSIZE-1:DSIZE/2] :
sys_datain[DSIZE/2-1:0];
dqm_outreg
<= select_lower_half ? dmsel_nx[DSIZE/8-1:DSIZE/16]:
sys_dmsel[DSIZE/16-1:0];
dqout
dqm_out
<= dqout_reg;
<= dqm_outreg;
end
end
// Generation of sys_rdyn. When sys_rdyn goes low
// data transfer takes place. Applies to read and write
always @(posedge clk or negedge reset_n) begin
if (reset_n == 1'b0) begin
sys_rdyn
<= 1'b1;
write_rdy_d1
<= 1'b0;
write_rdy_d2
<= 1'b0;
write_rdy_d3
<= 1'b0;
read_rdy
read_rdy_d
<= 1'b0;
<= 1'b0;
<= write_rdy;
write_rdy_d2
<= write_rdy_d1;
write_rdy_d3
<= write_rdy_d2;
20
read_rdy
read_rdy_d
if (NUM_CLK_WRITE == 1)
sys_rdyn
if (NUM_CLK_WRITE == 2)
sys_rdyn
if (NUM_CLK_WRITE == 4)
sys_rdyn
end
end
// Generation of sys_dataout_en
always @(negedge clk or negedge reset_n) begin
if (reset_n == 1'b0) begin
sys_dataout_en <= {DSIZE{1'b0}};
end else begin
sys_dataout_en <= read_rdy_d ? {DSIZE {1'b0}} : {DSIZE {1'b1}};
end
end
default: begin
write_rdy = 1'b0;
end
endcase
end
endmodule
TOP MODULE
sys_dmsel;
// System address
// System data mask select during DDR write
output [DDR_A_WIDTH-1:0]ddr_add;
// DDR address
output [DDR_BA_WIDTH-1:0]ddr_ba;
outputddr_casnddr_cke,ddr_csn,ddr_rasn,ddr_wen,sys_init_done,sys_rdyn,ddr_clk,
ddr_clkn;
output [DSIZE/16-1:0] ddr_dqm;
inout [DSIZE/2-1:0]
ddr_dq;
inout [DSIZE/16-1:0]
ddr_dqs;
inout [DSIZE-1:0]
sysd;
reg [DSIZE/2-1:0]
ddr_dq_i;
reg [DSIZE/16-1:0]
ddr_dqs_i;
reg [DSIZE-1:0]
sysd_i;
wire [RA_MSB:CA_LSB]
wire [3:0]
cstate;
wire [3:0]
istate;
wire
addr;
wren;
wire [DSIZE-1:0]
sys_datain;
wire [DSIZE/2-1:0]
dqout;
wire [DSIZE/2-1:0]
dqout_en;
wire [DSIZE/16-1:0]
dqsout;
wire [DSIZE/2-1:0]
dqin;
wire [DSIZE/16-1:0]
dqsout_en;
wire [DSIZE-1:0]
sys_dataout;
wire [DSIZE-1:0]
sys_dataout_en;
wire
pll_mclk_sp;
integeri,j,m;
ddr_ctrl u1_ddr_ctrl (
/*AUTOINST*/
// Outputs
.sys_init_done
(sys_init_done),
.istate
(istate[3:0]),
.cstate
(cstate[3:0]),
.wren
(wren),
23
.addr
(addr[RA_MSB:CA_LSB]),
// Inputs
.clk
.reset_n
(pll_mclk),
(reset_n),
.sys_r_wn
(sys_r_wn),
.sys_adsn
(sys_adsn),
.sys_dly_200us
.sys_add
(sys_dly_200us),
(sys_add[RA_MSB:CA_LSB]));
ddr_data u1_ddr_data (
/*AUTOINST*/
// Outputs
.dqout_en
.dqout
.dqsout_en
.dqsout
.sys_rdyn
.sys_dataout
(dqout_en[DSIZE/2-1:0]),
(dqout[DSIZE/2-1:0]),
(dqsout_en[DSIZE/16-1:0]),
(dqsout[DSIZE/16-1:0]),
(sys_rdyn),
(sys_dataout[DSIZE-1:0]),
.sys_dataout_en (sys_dataout_en[DSIZE-1:0]),
.dqm_out
(ddr_dqm[DSIZE/16-1:0]),
// Inputs
.clk
(pll_mclk),
.clk2x
(pll_nclk),
.reset_n
(reset_n),
.cstate
(cstate[3:0]),
.wren
(wren),
24
.sys_datain
(sys_datain[DSIZE-1:0]),
.sys_dmsel
(sys_dmsel[DSIZE/8-1:0]),
.dqin
(dqin[DSIZE/2-1:0]));
ddr_sig u1_ddr_sig (
/*AUTOINST*/
// Outputs
.ddr_cke
(ddr_cke),
.ddr_csn
(ddr_csn),
.ddr_rasn
(ddr_rasn),
.ddr_casn
(ddr_casn),
.ddr_wen
(ddr_wen),
.ddr_ba
(ddr_ba[DDR_BA_WIDTH-1:0]),
.ddr_add
(ddr_add[DDR_A_WIDTH-1:0]),
// Inputs
.clk
(pll_mclk),
.reset_n
(reset_n),
.addr
(addr[RA_MSB:CA_LSB]),
.istate
(istate[3:0]),
.cstate
(cstate[3:0]));
assignddr_clk = pll_mclk;
assignddr_clkn = !pll_mclk;
assignddr_clk = pll_mclk_sp;
assignddr_clkn = !pll_mclk_sp;
ddr_pll_orca u1_ddr_pll_orca(
25
.clk
(clk),
.mclk (pll_mclk),
.nclk (pll_nclk),
.lock (lock)
);
ddr_pll_orca_sp u2_ddr_pll_orca(
.clk
(clk),
.mclk (pll_mclk_sp),
.nclk (),
.lock ()
);
// DDR interface (READ & WRITE
// Read data
assign dqin[DSIZE/2-1:0]
= ddr_dq;
// Write data
always @ (dqout_en or dqout) begin
for (i=0; i<(DSIZE/2); i=i+1)
// For ORCA
ddr_dq_i[i]
// FOr XPGA
// ddr_dq_i[i]
end
assign #(0.9) ddr_dq = ddr_dq_i;
always @ (dqsout_en or dqsout) begin
26
//For XPGA
//ddr_dqs_i[j]
end
assign #(0.9) ddr_dqs = ddr_dqs_i;
// System side interface
// Write (system write)
assign sys_datain[DSIZE-1:0]
= sysd;
// System Read
always @ (sys_dataout_en or sys_dataout) begin
for (m=0; m<DSIZE; m=m+1)
// For ORCA
sysd_i[m]
// For XPGA
// sysd_i[m]
end
assign #(0.9) sysd = sysd_i;
endmodule
27
28