Skip to content

Commit d301191

Browse files
Merge pull request #390 from enjoy-digital/fix-gen-axi-user-enable
gen: gate AXI user ports until ready
2 parents 54b33f8 + be6e2de commit d301191

2 files changed

Lines changed: 140 additions & 41 deletions

File tree

litedram/gen.py

Lines changed: 43 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,48 @@ def get_axi_user_port_ios(_id, aw, dw, iw):
278278
),
279279
]
280280

281+
def connect_axi_user_port(axi_port, axi_port_io, user_enable):
282+
return [
283+
# AW Channel.
284+
axi_port.aw.valid.eq(axi_port_io.awvalid & user_enable),
285+
axi_port_io.awready.eq(axi_port.aw.ready & user_enable),
286+
axi_port.aw.addr.eq(axi_port_io.awaddr),
287+
axi_port.aw.burst.eq(axi_port_io.awburst),
288+
axi_port.aw.len.eq(axi_port_io.awlen),
289+
axi_port.aw.size.eq(axi_port_io.awsize),
290+
axi_port.aw.id.eq(axi_port_io.awid),
291+
292+
# W Channel.
293+
axi_port.w.valid.eq(axi_port_io.wvalid & user_enable),
294+
axi_port_io.wready.eq(axi_port.w.ready & user_enable),
295+
axi_port.w.last.eq(axi_port_io.wlast),
296+
axi_port.w.strb.eq(axi_port_io.wstrb),
297+
axi_port.w.data.eq(axi_port_io.wdata),
298+
299+
# B Channel.
300+
axi_port_io.bvalid.eq(axi_port.b.valid & user_enable),
301+
axi_port.b.ready.eq(axi_port_io.bready & user_enable),
302+
axi_port_io.bresp.eq(axi_port.b.resp),
303+
axi_port_io.bid.eq(axi_port.b.id),
304+
305+
# AR Channel.
306+
axi_port.ar.valid.eq(axi_port_io.arvalid & user_enable),
307+
axi_port_io.arready.eq(axi_port.ar.ready & user_enable),
308+
axi_port.ar.addr.eq(axi_port_io.araddr),
309+
axi_port.ar.burst.eq(axi_port_io.arburst),
310+
axi_port.ar.len.eq(axi_port_io.arlen),
311+
axi_port.ar.size.eq(axi_port_io.arsize),
312+
axi_port.ar.id.eq(axi_port_io.arid),
313+
314+
# R Channel.
315+
axi_port_io.rvalid.eq(axi_port.r.valid & user_enable),
316+
axi_port.r.ready.eq(axi_port_io.rready & user_enable),
317+
axi_port_io.rlast.eq(axi_port.r.last),
318+
axi_port_io.rresp.eq(axi_port.r.resp),
319+
axi_port_io.rdata.eq(axi_port.r.data),
320+
axi_port_io.rid.eq(axi_port.r.id),
321+
]
322+
281323
def get_fifo_user_port_ios(_id, dw):
282324
return [
283325
("user_fifo_{}".format(_id), 0,
@@ -794,46 +836,7 @@ def __init__(self, platform, core_config, **kwargs):
794836
axi_port.data_width,
795837
port["id_width"]))
796838
_axi_port_io = platform.request("user_port_{}".format(name))
797-
self.comb += [
798-
# AW Channel.
799-
axi_port.aw.valid.eq(_axi_port_io.awvalid & user_enable),
800-
_axi_port_io.awready.eq(axi_port.aw.ready & user_enable),
801-
axi_port.aw.addr.eq(_axi_port_io.awaddr),
802-
axi_port.aw.burst.eq(_axi_port_io.awburst),
803-
axi_port.aw.len.eq(_axi_port_io.awlen),
804-
axi_port.aw.size.eq(_axi_port_io.awsize),
805-
axi_port.aw.id.eq(_axi_port_io.awid),
806-
807-
# W Channel.
808-
axi_port.w.valid.eq(_axi_port_io.wvalid),
809-
_axi_port_io.wready.eq(axi_port.w.ready),
810-
axi_port.w.last.eq(_axi_port_io.wlast),
811-
axi_port.w.strb.eq(_axi_port_io.wstrb),
812-
axi_port.w.data.eq(_axi_port_io.wdata),
813-
814-
# B Channel.
815-
_axi_port_io.bvalid.eq(axi_port.b.valid),
816-
axi_port.b.ready.eq(_axi_port_io.bready),
817-
_axi_port_io.bresp.eq(axi_port.b.resp),
818-
_axi_port_io.bid.eq(axi_port.b.id),
819-
820-
# AR Channel.
821-
axi_port.ar.valid.eq(_axi_port_io.arvalid & user_enable),
822-
_axi_port_io.arready.eq(axi_port.ar.ready & user_enable),
823-
axi_port.ar.addr.eq(_axi_port_io.araddr),
824-
axi_port.ar.burst.eq(_axi_port_io.arburst),
825-
axi_port.ar.len.eq(_axi_port_io.arlen),
826-
axi_port.ar.size.eq(_axi_port_io.arsize),
827-
axi_port.ar.id.eq(_axi_port_io.arid),
828-
829-
# R Channel.
830-
_axi_port_io.rvalid.eq(axi_port.r.valid),
831-
axi_port.r.ready.eq(_axi_port_io.rready),
832-
_axi_port_io.rlast.eq(axi_port.r.last),
833-
_axi_port_io.rresp.eq(axi_port.r.resp),
834-
_axi_port_io.rdata.eq(axi_port.r.data),
835-
_axi_port_io.rid.eq(axi_port.r.id),
836-
]
839+
self.comb += connect_axi_user_port(axi_port, _axi_port_io, user_enable)
837840
# FIFO ---------------------------------------------------------------------------------
838841
elif port["type"] == "fifo":
839842
data_width = port.get("data_width", self.sdram.crossbar.controller.data_width)

test/test_gen.py

Lines changed: 97 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,108 @@
66

77
import unittest
88

9+
from migen import *
10+
911
from litex.build.sim import SimPlatform
1012
from litex.build.xilinx import XilinxPlatform
13+
from litex.gen.sim import run_simulation
1114

1215
from litedram import modules as litedram_modules
1316
from litedram import phy as litedram_phys
14-
from litedram.gen import LiteDRAMCore
17+
from litedram.frontend.axi import LiteDRAMAXIPort
18+
from litedram.gen import LiteDRAMCore, connect_axi_user_port
19+
20+
21+
axi_user_port_layout = [
22+
("awvalid", 1),
23+
("awready", 1),
24+
("awaddr", 32),
25+
("awburst", 2),
26+
("awlen", 8),
27+
("awsize", 3),
28+
("awid", 8),
29+
30+
("wvalid", 1),
31+
("wready", 1),
32+
("wlast", 1),
33+
("wstrb", 4),
34+
("wdata", 32),
35+
36+
("bvalid", 1),
37+
("bready", 1),
38+
("bresp", 2),
39+
("bid", 8),
40+
41+
("arvalid", 1),
42+
("arready", 1),
43+
("araddr", 32),
44+
("arburst", 2),
45+
("arlen", 8),
46+
("arsize", 3),
47+
("arid", 8),
48+
49+
("rvalid", 1),
50+
("rready", 1),
51+
("rlast", 1),
52+
("rresp", 2),
53+
("rdata", 32),
54+
("rid", 8),
55+
]
56+
57+
58+
class AXIUserPortDUT(Module):
59+
def __init__(self):
60+
self.user_enable = Signal()
61+
self.axi = LiteDRAMAXIPort(data_width=32, address_width=32, id_width=8)
62+
self.pads = Record(axi_user_port_layout)
63+
64+
self.comb += connect_axi_user_port(self.axi, self.pads, self.user_enable)
65+
66+
67+
class TestGEN(unittest.TestCase):
68+
def test_axi_user_port_block_until_ready(self):
69+
dut = AXIUserPortDUT()
70+
71+
def main_generator():
72+
yield dut.pads.awvalid.eq(1)
73+
yield dut.pads.wvalid.eq(1)
74+
yield dut.pads.bready.eq(1)
75+
yield dut.pads.arvalid.eq(1)
76+
yield dut.pads.rready.eq(1)
77+
78+
yield dut.axi.aw.ready.eq(1)
79+
yield dut.axi.w.ready.eq(1)
80+
yield dut.axi.b.valid.eq(1)
81+
yield dut.axi.ar.ready.eq(1)
82+
yield dut.axi.r.valid.eq(1)
83+
yield
84+
85+
self.assertEqual((yield dut.axi.aw.valid), 0)
86+
self.assertEqual((yield dut.pads.awready), 0)
87+
self.assertEqual((yield dut.axi.w.valid), 0)
88+
self.assertEqual((yield dut.pads.wready), 0)
89+
self.assertEqual((yield dut.pads.bvalid), 0)
90+
self.assertEqual((yield dut.axi.b.ready), 0)
91+
self.assertEqual((yield dut.axi.ar.valid), 0)
92+
self.assertEqual((yield dut.pads.arready), 0)
93+
self.assertEqual((yield dut.pads.rvalid), 0)
94+
self.assertEqual((yield dut.axi.r.ready), 0)
95+
96+
yield dut.user_enable.eq(1)
97+
yield
98+
99+
self.assertEqual((yield dut.axi.aw.valid), 1)
100+
self.assertEqual((yield dut.pads.awready), 1)
101+
self.assertEqual((yield dut.axi.w.valid), 1)
102+
self.assertEqual((yield dut.pads.wready), 1)
103+
self.assertEqual((yield dut.pads.bvalid), 1)
104+
self.assertEqual((yield dut.axi.b.ready), 1)
105+
self.assertEqual((yield dut.axi.ar.valid), 1)
106+
self.assertEqual((yield dut.pads.arready), 1)
107+
self.assertEqual((yield dut.pads.rvalid), 1)
108+
self.assertEqual((yield dut.axi.r.ready), 1)
109+
110+
run_simulation(dut, main_generator())
15111

16112

17113
def core_config():

0 commit comments

Comments
 (0)