import migen in litex/gen
[litex.git] / litex / soc / misoc / cores / sdram_phy / gensdrphy.py
1 #
2 # 1:1 frequency-ratio Generic SDR PHY
3 #
4 # The GENSDRPHY is validated on CycloneIV (Altera) but since it does
5 # not use vendor-dependent code, it can also be used on other architectures.
6 #
7 # The PHY needs 2 Clock domains:
8 # - sys_clk : The System Clock domain
9 # - sys_clk_ps : The System Clock domain with its phase shifted
10 # (-3ns on C4@100MHz)
11 #
12 # Assert dfi_wrdata_en and present the data
13 # on dfi_wrdata_mask/dfi_wrdata in the same
14 # cycle as the write command.
15 #
16 # Assert dfi_rddata_en in the same cycle as the read
17 # command. The data will come back on dfi_rddata
18 # 4 cycles later, along with the assertion of
19 # dfi_rddata_valid.
20 #
21 # This PHY only supports CAS Latency 2.
22 #
23
24 from migen import *
25 from migen.genlib.record import *
26 from migen.fhdl.specials import Tristate
27
28 from misoc.interconnect.dfi import *
29 from misoc.cores import sdram_settings
30
31
32 class GENSDRPHY(Module):
33 def __init__(self, pads):
34 addressbits = len(pads.a)
35 bankbits = len(pads.ba)
36 databits = len(pads.dq)
37
38 self.settings = sdram_settings.PhySettings(
39 memtype="SDR",
40 dfi_databits=databits,
41 nphases=1,
42 rdphase=0,
43 wrphase=0,
44 rdcmdphase=0,
45 wrcmdphase=0,
46 cl=2,
47 read_latency=4,
48 write_latency=0
49 )
50
51 self.dfi = Interface(addressbits, bankbits, databits)
52
53 ###
54
55 #
56 # Command/address
57 #
58 self.sync += [
59 pads.a.eq(self.dfi.p0.address),
60 pads.ba.eq(self.dfi.p0.bank),
61 pads.cke.eq(self.dfi.p0.cke),
62 pads.cas_n.eq(self.dfi.p0.cas_n),
63 pads.ras_n.eq(self.dfi.p0.ras_n),
64 pads.we_n.eq(self.dfi.p0.we_n)
65 ]
66 if hasattr(pads, "cs_n"):
67 self.sync += pads.cs_n.eq(self.dfi.p0.cs_n)
68
69 #
70 # DQ/DQS/DM data
71 #
72 sd_dq_out = Signal(databits)
73 drive_dq = Signal()
74 self.sync += sd_dq_out.eq(self.dfi.p0.wrdata)
75 self.specials += Tristate(pads.dq, sd_dq_out, drive_dq)
76 self.sync += \
77 If(self.dfi.p0.wrdata_en,
78 pads.dm.eq(self.dfi.p0.wrdata_mask)
79 ).Else(
80 pads.dm.eq(0)
81 )
82 sd_dq_in_ps = Signal(databits)
83 self.sync.sys_ps += sd_dq_in_ps.eq(pads.dq)
84 self.sync += self.dfi.p0.rddata.eq(sd_dq_in_ps)
85
86 #
87 # DQ/DM control
88 #
89 d_dfi_wrdata_en = Signal()
90 self.sync += d_dfi_wrdata_en.eq(self.dfi.p0.wrdata_en)
91 self.comb += drive_dq.eq(d_dfi_wrdata_en)
92
93 rddata_sr = Signal(4)
94 self.comb += self.dfi.p0.rddata_valid.eq(rddata_sr[3])
95 self.sync += rddata_sr.eq(Cat(self.dfi.p0.rddata_en, rddata_sr[:3]))