1 # This file is Copyright (c) 2015 Sebastien Bourdeauducq <sb@m-labs.hk>
2 # Copyright (c) 2020 LambdaConcept <contact@lambdaconcept.com>
5 from nmigen
.hdl
.rec
import *
7 def phase_cmd_description(addressbits
, bankbits
, nranks
):
9 ("address", addressbits
, DIR_FANOUT
),
10 ("bank", bankbits
, DIR_FANOUT
),
11 ("cas_n", 1, DIR_FANOUT
),
12 ("cs_n", nranks
, DIR_FANOUT
),
13 ("ras_n", 1, DIR_FANOUT
),
14 ("we_n", 1, DIR_FANOUT
),
15 ("cke", nranks
, DIR_FANOUT
),
16 ("odt", nranks
, DIR_FANOUT
),
17 ("reset_n", 1, DIR_FANOUT
),
18 ("act_n", 1, DIR_FANOUT
)
22 def phase_wrdata_description(databits
):
24 ("wrdata", databits
, DIR_FANOUT
),
25 ("wrdata_en", 1, DIR_FANOUT
),
26 ("wrdata_mask", databits
//8, DIR_FANOUT
)
30 def phase_rddata_description(databits
):
32 ("rddata_en", 1, DIR_FANOUT
),
33 ("rddata", databits
, DIR_FANIN
),
34 ("rddata_valid", 1, DIR_FANIN
)
38 def phase_description(addressbits
, bankbits
, nranks
, databits
):
39 r
= phase_cmd_description(addressbits
, bankbits
, nranks
)
40 r
+= phase_wrdata_description(databits
)
41 r
+= phase_rddata_description(databits
)
45 class Interface(Record
):
46 def __init__(self
, addressbits
, bankbits
, nranks
, databits
, nphases
=1):
47 layout
= [("p"+str(i
), phase_description(addressbits
, bankbits
, nranks
, databits
)) for i
in range(nphases
)]
48 Record
.__init
__(self
, layout
)
49 self
.phases
= [getattr(self
, "p"+str(i
)) for i
in range(nphases
)]
52 p
.cs_n
.reset
= (2**nranks
-1)
57 # Returns pairs (DFI-mandated signal name, Migen signal object)
58 def get_standard_names(self
, m2s
=True, s2m
=True):
60 add_suffix
= len(self
.phases
) > 1
61 for n
, phase
in enumerate(self
.phases
):
62 for field
, size
, direction
in phase
.layout
:
63 if (m2s
and direction
== DIR_FANOUT
) or (s2m
and direction
== DIR_FANIN
):
65 if direction
== DIR_FANOUT
:
66 suffix
= "_p" + str(n
)
68 suffix
= "_w" + str(n
)
71 r
.append(("dfi_" + field
+ suffix
, getattr(phase
, field
)))
75 class Interconnect(Elaboratable
):
76 def __init__(self
, master
, slave
):
80 def elaborate(self
, platform
):
82 m
.d
.comb
+= self
._master
.connect(self
._slave
)
86 class DDR4DFIMux(Elaboratable
):
87 def __init__(self
, dfi_i
, dfi_o
):
91 def elaborate(self
, platform
):
97 for i
in range(len(dfi_i
.phases
)):
100 m
.d
.comb
+= p_i
.connect(p_o
)
101 with m
.If(~p_i
.ras_n
& p_i
.cas_n
& p_i
.we_n
):
104 p_o
.we_n
.eq(p_i
.address
[14]),
105 p_o
.cas_n
.eq(p_i
.address
[15]),
106 p_o
.ras_n
.eq(p_i
.address
[16]),
109 m
.d
.comb
+= p_o
.act_n
.eq(1)