Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
E
eddr3
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Commits
Issue Boards
Open sidebar
Elphel
eddr3
Commits
2aa6f1d2
Commit
2aa6f1d2
authored
Apr 29, 2014
by
Andrey Filippov
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
More code
parent
ea560b4a
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
275 additions
and
61 deletions
+275
-61
byte_lane.v
phy/byte_lane.v
+3
-3
cmd_addr.v
phy/cmd_addr.v
+259
-0
cmda_single.v
phy/cmda_single.v
+13
-58
No files found.
phy/byte_lane.v
View file @
2aa6f1d2
...
...
@@ -2,7 +2,7 @@
* Module: byte_lane
* Date:2014-04-26
* Author: Andrey Filippov
* Description: DDR3 byte lane, in
g
luding DQS I/O, 8xDQ I/O and DM output
* Description: DDR3 byte lane, in
c
luding DQS I/O, 8xDQ I/O and DM output
*
* Copyright (c) 2014 Elphel, Inc.
* byte_lane.v is free software; you can redistribute it and/or modify
...
...
@@ -44,7 +44,7 @@ module byte_lane #(
input
[
3
:
0
]
tin_dq
,
// tristate for data out (sent out earlier than data!) and dm
input
[
3
:
0
]
din_dqs
,
// parallel data to be sent out over DQS
input
[
3
:
0
]
tin_dqs
,
// tristate for DQS out (sent out earlier than data!)
output
[
31
:
0
]
dout
,
// parallel data received from DDR3 memory, 4 bits per D
G
I/O
output
[
31
:
0
]
dout
,
// parallel data received from DDR3 memory, 4 bits per D
Q
I/O
input
[
7
:
0
]
dly_data
,
// delay value (3 LSB - fine delay)
input
[
4
:
0
]
dly_addr
,
// select which delay to program
input
ld_delay
,
// load delay data to selected iodelayl (clk_iv synchronous)
...
...
@@ -91,7 +91,7 @@ end
generate
genvar
i
;
for
(
i
=
0
;
i
<
7
;
i
=
i
+
1
)
begin
:
dq_block
for
(
i
=
0
;
i
<
8
;
i
=
i
+
1
)
begin
:
dq_block
dq_single
#(
.
IODELAY_GRP
(
IODELAY_GRP
)
,
.
IBUF_LOW_PWR
(
IBUF_LOW_PWR
)
,
...
...
phy/cmd_addr.v
0 → 100644
View file @
2aa6f1d2
/*******************************************************************************
* Module: cmd_addr
* Date:2014-04-26
* Author: Andrey Filippov
* Description: DDR3 command/address signals
*
* Copyright (c) 2014 Elphel, Inc.
* cmd_addr.v is free software; 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.
*
* cmd_addr.v is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY 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. If not, see <http://www.gnu.org/licenses/> .
*******************************************************************************/
`timescale
1
ns
/
1
ps
module
cmd_addr
#(
parameter
IODELAY_GRP
=
"IODELAY_MEMORY"
,
parameter
IOSTANDARD
=
"SSTL15"
,
parameter
SLEW
=
"SLOW"
,
parameter
real
REFCLK_FREQUENCY
=
300.0
,
parameter
HIGH_PERFORMANCE_MODE
=
"FALSE"
,
parameter
ADDRESS_NUMBER
=
15
)(
output
[
ADDRESS_NUMBER
-
1
:
0
]
ddr3_a
,
// output address ports (14:0) for 4Gb device
output
[
2
:
0
]
ddr3_ba
,
// output bank address ports
output
ddr3_we
,
// output WE port
output
ddr3_ras
,
// output RAS port
output
ddr3_cas
,
// output CAS port
output
ddr3_cke
,
// output Clock Enable port
output
ddr3_odt
,
// output ODT port
input
clk
,
// free-running system clock, same frequency as iclk (shared for R/W)
input
clk_div
,
// free-running half clk frequency, front aligned to clk (shared for R/W)
input
rst
,
// reset delays/serdes
input
[
2
*
ADDRESS_NUMBER
-
1
:
0
]
in_a
,
// input address, 2 bits per signal (first, second) (29:0) for 4Gb device
input
[
5
:
0
]
in_ba
,
// input bank address, 2 bits per signal (first, second)
input
[
1
:
0
]
in_we
,
// input WE, 2 bits (first, second)
input
[
1
:
0
]
in_ras
,
// input RAS, 2 bits (first, second)
input
[
1
:
0
]
in_cas
,
// input CAS, 2 bits (first, second)
input
[
1
:
0
]
in_cke
,
// input CKE, 2 bits (first, second)
input
[
1
:
0
]
in_odt
,
// input ODT, 2 bits (first, second)
input
[
1
:
0
]
in_tri
,
// tristate command/address outputs - same timing, but no odelay
input
[
7
:
0
]
dly_data
,
// delay value (3 LSB - fine delay)
input
[
4
:
0
]
dly_addr
,
// select which delay to program
input
ld_delay
,
// load delay data to selected iodelayl (clk_iv synchronous)
input
set
// clk_div synchronous set all delays from previously loaded values
)
;
reg
[
2
*
ADDRESS_NUMBER
-
1
:
0
]
in_a_r
=
0
;
reg
[
5
:
0
]
in_ba_r
=
0
;
reg
[
1
:
0
]
in_we_r
=
2'h3
,
in_ras_r
=
2'h3
,
in_cas_r
=
2'h3
,
in_cke_r
=
2'h3
,
in_odt_r
=
2'h0
;
reg
[
1
:
0
]
in_tri_r
=
2'h0
;
// or tri-state on reset?
reg
[
7
:
0
]
dly_data_r
=
0
;
reg
set_r
=
0
;
reg
[
7
:
0
]
ld_dly_cmd
=
8'b0
;
reg
[
ADDRESS_NUMBER
-
1
:
0
]
ld_dly_addr
=
0
;
wire
[
ADDRESS_NUMBER
-
1
:
0
]
decode_addr
;
wire
[
7
:
0
]
decode_sel
={
(
dly_addr
[
2
:
0
]
==
7
)
?
1'b1
:
1'b0
,
(
dly_addr
[
2
:
0
]
==
6
)
?
1'b1
:
1'b0
,
(
dly_addr
[
2
:
0
]
==
5
)
?
1'b1
:
1'b0
,
(
dly_addr
[
2
:
0
]
==
4
)
?
1'b1
:
1'b0
,
(
dly_addr
[
2
:
0
]
==
3
)
?
1'b1
:
1'b0
,
(
dly_addr
[
2
:
0
]
==
2
)
?
1'b1
:
1'b0
,
(
dly_addr
[
2
:
0
]
==
1
)
?
1'b1
:
1'b0
,
(
dly_addr
[
2
:
0
]
==
0
)
?
1'b1
:
1'b0
};
always
@
(
posedge
clk_div
or
posedge
rst
)
begin
if
(
rst
)
begin
in_a_r
<=
0
;
in_ba_r
<=
6'b0
;
in_we_r
<=
2'h3
;
in_ras_r
<=
2'h3
;
in_cas_r
<=
2'h3
;
in_cke_r
<=
2'h3
;
in_odt_r
<=
2'h0
;
in_tri_r
<=
2'h0
;
// or tri-state on reset?
dly_data_r
<=
8'b0
;
set_r
<=
1'b0
;
ld_dly_cmd
<=
8'b0
;
ld_dly_addr
<=
0
;
end
else
begin
in_a_r
<=
in_a
;
in_ba_r
<=
in_ba
;
in_we_r
<=
in_we
;
in_ras_r
<=
in_ras
;
in_cas_r
<=
in_cas
;
in_cke_r
<=
in_cke
;
in_odt_r
<=
in_odt
;
in_tri_r
<=
in_tri
;
dly_data_r
<=
dly_data
;
set_r
<=
set
;
ld_dly_cmd
<=
{
8
{
dly_addr
[
4
]
&
dly_addr
[
3
]
&
ld_delay
}}
&
decode_sel
[
7
:
0
]
;
ld_dly_addr
<=
{
(
ADDRESS_NUMBER
-
1
)
{
ld_delay
}}
&
decode_addr
;
end
end
// All addresses
generate
genvar
i
;
for
(
i
=
0
;
i
<
ADDRESS_NUMBER
;
i
=
i
+
1
)
begin
:
addr_block
assign
decode_addr
[
i
]
=
(
ld_dly_addr
[
4
:
0
]
==
i
)
?
1'b1
:
1'b0
;
cmda_single
#(
.
IODELAY_GRP
(
IODELAY_GRP
)
,
.
IOSTANDARD
(
IOSTANDARD
)
,
.
SLEW
(
SLEW
)
,
.
REFCLK_FREQUENCY
(
REFCLK_FREQUENCY
)
,
.
HIGH_PERFORMANCE_MODE
(
HIGH_PERFORMANCE_MODE
)
)
cmda_addr_i
(
.
dq
(
ddr3_a
)
,
// I/O pad (appears on the output 1/2 clk_div earlier, than DDR data)
.
clk
(
clk
)
,
// free-running system clock, same frequency as iclk (shared for R/W)
.
clk_div
(
clk_div
)
,
// free-running half clk frequency, front aligned to clk (shared for R/W)
.
rst
(
rst
)
,
.
dly_data
(
dly_data_r
[
7
:
0
])
,
// delay value (3 LSB - fine delay)
.
din
(
in_a_r
[
2
*
i
+
1
:
2
*
i
])
,
// parallel data to be sent out
.
tin
(
in_tri_r
[
1
:
0
])
,
// tristate for data out (sent out earlier than data!)
.
set_delay
(
set_r
)
,
// clk_div synchronous load odelay value from dly_data
.
ld_delay
(
ld_dly_addr
[
i
])
// clk_div synchronous set odealy value from loaded
)
;
end
endgenerate
// Bank addresses
// ba0
cmda_single
#(
.
IODELAY_GRP
(
IODELAY_GRP
)
,
.
IOSTANDARD
(
IOSTANDARD
)
,
.
SLEW
(
SLEW
)
,
.
REFCLK_FREQUENCY
(
REFCLK_FREQUENCY
)
,
.
HIGH_PERFORMANCE_MODE
(
HIGH_PERFORMANCE_MODE
)
)
cmda_ba0_i
(
.
dq
(
ddr3_ba
[
0
])
,
.
clk
(
clk
)
,
.
clk_div
(
clk_div
)
,
.
rst
(
rst
)
,
.
dly_data
(
dly_data_r
[
7
:
0
])
,
.
din
(
in_ba_r
[
1
:
0
])
,
.
tin
(
in_tri_r
[
1
:
0
])
,
.
set_delay
(
set_r
)
,
.
ld_delay
(
ld_dly_cmd
[
0
]))
;
// ba1
cmda_single
#(
.
IODELAY_GRP
(
IODELAY_GRP
)
,
.
IOSTANDARD
(
IOSTANDARD
)
,
.
SLEW
(
SLEW
)
,
.
REFCLK_FREQUENCY
(
REFCLK_FREQUENCY
)
,
.
HIGH_PERFORMANCE_MODE
(
HIGH_PERFORMANCE_MODE
)
)
cmda_ba1_i
(
.
dq
(
ddr3_ba
[
1
])
,
.
clk
(
clk
)
,
.
clk_div
(
clk_div
)
,
.
rst
(
rst
)
,
.
dly_data
(
dly_data_r
[
7
:
0
])
,
.
din
(
in_ba_r
[
3
:
2
])
,
.
tin
(
in_tri_r
[
1
:
0
])
,
.
set_delay
(
set_r
)
,
.
ld_delay
(
ld_dly_cmd
[
1
]))
;
// ba2
cmda_single
#(
.
IODELAY_GRP
(
IODELAY_GRP
)
,
.
IOSTANDARD
(
IOSTANDARD
)
,
.
SLEW
(
SLEW
)
,
.
REFCLK_FREQUENCY
(
REFCLK_FREQUENCY
)
,
.
HIGH_PERFORMANCE_MODE
(
HIGH_PERFORMANCE_MODE
)
)
cmda_ba2_i
(
.
dq
(
ddr3_ba
[
2
])
,
.
clk
(
clk
)
,
.
clk_div
(
clk_div
)
,
.
rst
(
rst
)
,
.
dly_data
(
dly_data_r
[
7
:
0
])
,
.
din
(
in_ba_r
[
5
:
4
])
,
.
tin
(
in_tri_r
[
1
:
0
])
,
.
set_delay
(
set_r
)
,
.
ld_delay
(
ld_dly_cmd
[
2
]))
;
// we
cmda_single
#(
.
IODELAY_GRP
(
IODELAY_GRP
)
,
.
IOSTANDARD
(
IOSTANDARD
)
,
.
SLEW
(
SLEW
)
,
.
REFCLK_FREQUENCY
(
REFCLK_FREQUENCY
)
,
.
HIGH_PERFORMANCE_MODE
(
HIGH_PERFORMANCE_MODE
)
)
cmda_we_i
(
.
dq
(
ddr3_we
)
,
.
clk
(
clk
)
,
.
clk_div
(
clk_div
)
,
.
rst
(
rst
)
,
.
dly_data
(
dly_data_r
[
7
:
0
])
,
.
din
(
in_we_r
[
1
:
0
])
,
.
tin
(
in_tri_r
[
1
:
0
])
,
.
set_delay
(
set_r
)
,
.
ld_delay
(
ld_dly_cmd
[
3
]))
;
// ras
cmda_single
#(
.
IODELAY_GRP
(
IODELAY_GRP
)
,
.
IOSTANDARD
(
IOSTANDARD
)
,
.
SLEW
(
SLEW
)
,
.
REFCLK_FREQUENCY
(
REFCLK_FREQUENCY
)
,
.
HIGH_PERFORMANCE_MODE
(
HIGH_PERFORMANCE_MODE
)
)
cmda_ras_i
(
.
dq
(
ddr3_ras
)
,
.
clk
(
clk
)
,
.
clk_div
(
clk_div
)
,
.
rst
(
rst
)
,
.
dly_data
(
dly_data_r
[
7
:
0
])
,
.
din
(
in_ras_r
[
1
:
0
])
,
.
tin
(
in_tri_r
[
1
:
0
])
,
.
set_delay
(
set_r
)
,
.
ld_delay
(
ld_dly_cmd
[
4
]))
;
// cas
cmda_single
#(
.
IODELAY_GRP
(
IODELAY_GRP
)
,
.
IOSTANDARD
(
IOSTANDARD
)
,
.
SLEW
(
SLEW
)
,
.
REFCLK_FREQUENCY
(
REFCLK_FREQUENCY
)
,
.
HIGH_PERFORMANCE_MODE
(
HIGH_PERFORMANCE_MODE
)
)
cmda_cas_i
(
.
dq
(
ddr3_cas
)
,
.
clk
(
clk
)
,
.
clk_div
(
clk_div
)
,
.
rst
(
rst
)
,
.
dly_data
(
dly_data_r
[
7
:
0
])
,
.
din
(
in_cas_r
[
1
:
0
])
,
.
tin
(
in_tri_r
[
1
:
0
])
,
.
set_delay
(
set_r
)
,
.
ld_delay
(
ld_dly_cmd
[
5
]))
;
// cke
cmda_single
#(
.
IODELAY_GRP
(
IODELAY_GRP
)
,
.
IOSTANDARD
(
IOSTANDARD
)
,
.
SLEW
(
SLEW
)
,
.
REFCLK_FREQUENCY
(
REFCLK_FREQUENCY
)
,
.
HIGH_PERFORMANCE_MODE
(
HIGH_PERFORMANCE_MODE
)
)
cmda_cke_i
(
.
dq
(
ddr3_cke
)
,
.
clk
(
clk
)
,
.
clk_div
(
clk_div
)
,
.
rst
(
rst
)
,
.
dly_data
(
dly_data_r
[
7
:
0
])
,
.
din
(
in_cke_r
[
1
:
0
])
,
.
tin
(
in_tri_r
[
1
:
0
])
,
.
set_delay
(
set_r
)
,
.
ld_delay
(
ld_dly_cmd
[
6
]))
;
// odt
cmda_single
#(
.
IODELAY_GRP
(
IODELAY_GRP
)
,
.
IOSTANDARD
(
IOSTANDARD
)
,
.
SLEW
(
SLEW
)
,
.
REFCLK_FREQUENCY
(
REFCLK_FREQUENCY
)
,
.
HIGH_PERFORMANCE_MODE
(
HIGH_PERFORMANCE_MODE
)
)
cmda_odt_i
(
.
dq
(
ddr3_odt
)
,
.
clk
(
clk
)
,
.
clk_div
(
clk_div
)
,
.
rst
(
rst
)
,
.
dly_data
(
dly_data_r
[
7
:
0
])
,
.
din
(
in_odt_r
[
1
:
0
])
,
.
tin
(
in_tri_r
[
1
:
0
])
,
.
set_delay
(
set_r
)
,
.
ld_delay
(
ld_dly_cmd
[
7
]))
;
endmodule
phy/cmda_single.v
View file @
2aa6f1d2
...
...
@@ -22,36 +22,24 @@
module
cmda_single
#(
parameter
IODELAY_GRP
=
"IODELAY_MEMORY"
,
parameter
IBUF_LOW_PWR
=
"TRUE"
,
parameter
IOSTANDARD
=
"SSTL15"
,
parameter
SLEW
=
"SLOW"
,
parameter
real
REFCLK_FREQUENCY
=
300.0
,
parameter
HIGH_PERFORMANCE_MODE
=
"FALSE"
)(
inout
dq
,
// I/O pad
input
iclk
,
// source-synchronous clock (BUFR from DQS)
output
dq
,
// I/O pad (appears on the output 1/2 clk_div earlier, than DDR data)
input
clk
,
// free-running system clock, same frequency as iclk (shared for R/W)
input
clk_div
,
// free-running half clk frequency, front aligned to clk (shared for R/W)
input
inv_clk_div
,
// invert clk_div for R channel (clk_div is shared between R and W)
input
rst
,
input
dci_disable
,
// disable DCI termination during writes and idle
input
[
7
:
0
]
dly_data
,
// delay value (3 LSB - fine delay)
input
[
3
:
0
]
din
,
// parallel data to be sent out
input
[
3
:
0
]
tin
,
// tristate for data out (sent out earlier than data!)
output
[
3
:
0
]
dout
,
// parallel data received from DDR3 memory
input
set_odelay
,
// clk_div synchronous load odelay value from dly_data
input
ld_odelay
,
// clk_div synchronous set odealy value from loaded
input
set_idelay
,
// clk_div synchronous load idelay value from dly_data
input
ld_idelay
// clk_div synchronous set idealy value from loaded
input
[
1
:
0
]
din
,
// parallel data to be sent out
input
[
1
:
0
]
tin
,
// tristate for data out (sent out earlier than data!)
input
set_delay
,
// clk_div synchronous load odelay value from dly_data
input
ld_delay
// clk_div synchronous set odealy value from loaded
)
;
wire
d_ser
;
wire
dq_tri
;
wire
dq_data_dly
;
wire
dq_dly
;
// keep IOBUF_DCIEN.O to user as output only (UDM/LDM), so the rest of tyhe read channel will be optimized out, but I/O will stay the same
(
*
keep
=
"true"
*
)
wire
dq_di
;
oserdes_mem
#(
.
MODE_DDR
(
"FALSE"
)
...
...
@@ -59,8 +47,8 @@ oserdes_mem#(
.
clk
(
clk
)
,
// serial output clock
.
clk_div
(
clk_div
)
,
// oclk divided by 2, front aligned
.
rst
(
rst
)
,
// reset
.
din
(
din
[
3
:
0
])
,
// parallel data in
.
tin
(
tin
[
3
:
0
])
,
// parallel tri-state in
.
din
(
din
[
1
:
0
])
,
// parallel data in
.
tin
(
tin
[
1
:
0
])
,
// parallel tri-state in
.
dout_dly
(
d_ser
)
,
// data out to be connected to odelay input
.
dout_iob
()
,
// data out to be connected directly to the output buffer
.
tout_dly
()
,
// tristate out to be connected to odelay input
...
...
@@ -74,53 +62,20 @@ odelay_fine_pipe # (
)
dqs_out_dly_i
(
.
clk
(
clk_div
)
,
.
rst
(
rst
)
,
.
set
(
set_
o
delay
)
,
.
ld
(
ld_
o
delay
)
,
.
set
(
set_delay
)
,
.
ld
(
ld_delay
)
,
.
delay
(
dly_data
[
7
:
0
])
,
.
data_in
(
d_ser
)
,
.
data_out
(
dq_data_dly
)
)
;
IOBUF_DCIEN
#(
.
IBUF_LOW_PWR
(
IBUF_LOW_PWR
)
,
//
OBUFT
#(
.
IOSTANDARD
(
IOSTANDARD
)
,
.
SLEW
(
SLEW
)
,
.
USE_IBUFDISABLE
(
"FALSE"
)
.
SLEW
(
SLEW
)
)
iobufs_dqs_i
(
.
O
(
dq_di
)
,
.
IO
(
dq
)
,
.
DCITERMDISABLE
(
dci_disable
)
,
.
IBUFDISABLE
(
1'b0
)
,
.
I
(
dq_data_dly
)
,
//dqs_data),
.
O
(
dq
)
,
.
I
(
dq_data_dly
)
,
.
T
(
dq_tri
))
;
idelay_fine_pipe
#
(
.
IODELAY_GRP
(
IODELAY_GRP
)
,
.
DELAY_VALUE
(
0
)
,
.
REFCLK_FREQUENCY
(
REFCLK_FREQUENCY
)
,
.
HIGH_PERFORMANCE_MODE
(
HIGH_PERFORMANCE_MODE
)
)
dqs_in_dly_i
(
.
clk
(
clk_div
)
,
.
rst
(
rst
)
,
.
set
(
set_idelay
)
,
.
ld
(
ld_idelay
)
,
.
delay
(
dly_data
[
7
:
0
])
,
.
data_in
(
dq_di
)
,
.
data_out
(
dq_dly
)
)
;
iserdes_mem
#(
.
DYN_CLKDIV_INV_EN
(
"FALSE"
)
)
iserdes_mem_i
(
.
iclk
(
iclk
)
,
// source-synchronous clock
.
oclk
(
clk
)
,
// system clock, phase should allow iclk-to-oclk jitter with setup/hold margin
.
oclk_div
(
clk_div
)
,
// oclk divided by 2, front aligned
.
inv_clk_div
(
inv_clk_div
)
,
// invert oclk_div (this clock is shared between iserdes and oserdes. Works only in MEMORY_DDR3 mode?
.
rst
(
rst
)
,
// reset
.
d_direct
(
1'b0
)
,
// direct input from IOB, normally not used, controlled by IOBDELAY parameter (set to "NONE")
.
ddly
(
dq_dly
)
,
// serial input from idelay
.
dout
(
dout
[
3
:
0
])
// parallel data out
)
;
endmodule
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment