6775427fd300d4e2113122ba3c9e5354332458fc
1 # Copyright (C) 2022 Raptor Engineering, LLC <support@raptorengineering.com>
3 # Based partly on code from LibreSoC
5 # Modifications for the Libre-SOC Project funded by NLnet and NGI POINTER
6 # under EU Grants 871528 and 957073, under the LGPLv3+ License
8 # this is a wrapper around the Verilog Wishbone Components wb_async_reg module
10 from nmigen
import (Elaboratable
, Cat
, Module
, Signal
, ClockSignal
, Instance
,
13 from nmigen_soc
.wishbone
.bus
import Interface
14 from nmigen_soc
.memory
import MemoryMap
15 from nmigen
.utils
import log2_int
16 from nmigen
.cli
import rtlil
, verilog
17 from nmutil
.byterev
import byte_reverse
20 __all__
= ["WBAsyncBridge"]
23 class WBAsyncBridge(Elaboratable
):
24 """Verilog Wishbone Components wb_async_reg module, nmigen wrapper.
25 remember to call WBAsyncBridge.add_verilog_source
28 def __init__(self
, master_bus
=None, slave_bus
=None, master_features
=None,
29 slave_features
=None, name
=None,
30 address_width
=30, data_width
=32, granularity
=8,
31 master_clock_domain
=None, slave_clock_domain
=None):
33 # convention: give the name in the format "name_number"
34 self
.idx
= int(name
.split("_")[-1])
37 name
= "wbasyncbridge_0"
38 self
.address_width
= address_width
39 self
.data_width
= data_width
40 self
.granularity
= granularity
41 self
.dsize
= log2_int(self
.data_width
//self
.granularity
)
43 # set up the clock domains
44 if master_clock_domain
is None:
45 self
.wb_mclk
= ClockSignal()
46 self
.wb_mrst
= ResetSignal()
48 self
.wb_mclk
= ClockSignal(master_clock_domain
)
49 self
.wb_mrst
= ResetSignal(master_clock_domain
)
50 if slave_clock_domain
is None:
51 self
.wb_sclk
= ClockSignal()
52 self
.wb_srst
= ResetSignal()
54 self
.wb_sclk
= ClockSignal(slave_clock_domain
)
55 self
.wb_srst
= ResetSignal(slave_clock_domain
)
57 # set up the wishbone busses
58 if master_features
is None:
59 master_features
= frozenset()
60 if slave_features
is None:
61 slave_features
= frozenset()
62 if master_bus
is None:
63 master_bus
= Interface(addr_width
=self
.address_width
,
64 data_width
=self
.data_width
,
65 features
=master_features
,
66 granularity
=self
.granularity
,
67 name
=name
+"_wb_%d_master" % self
.idx
)
69 slave_bus
= Interface(addr_width
=self
.address_width
,
70 data_width
=self
.data_width
,
71 features
=slave_features
,
72 granularity
=self
.granularity
,
73 name
=name
+"_wb_%d_slave" % self
.idx
)
74 self
.master_bus
= master_bus
75 assert len(self
.master_bus
.dat_r
) == data_width
, \
76 "bus width must be %d" % data_width
77 self
.slave_bus
= slave_bus
78 assert len(self
.slave_bus
.dat_r
) == data_width
, \
79 "bus width must be %d" % data_width
82 def add_verilog_source(cls
, verilog_src_dir
, platform
):
83 # add each of the verilog sources, needed for when doing platform.build
84 for fname
in ['wb_async_reg.v']:
85 # prepend the src directory to each filename, add its contents
86 fullname
= os
.path
.join(verilog_src_dir
, fname
)
87 with
open(fullname
) as f
:
88 platform
.add_file(fullname
, f
)
90 def elaborate(self
, platform
):
93 master_bus
, slave_bus
= self
.master_bus
, self
.slave_bus
98 # create definition of external verilog bridge code here, so that
99 # nmigen understands I/O directions (defined by i_ and o_ prefixes)
101 wb_async_bridge
= Instance("wb_async_reg",
103 p_ADDR_WIDTH
=self
.address_width
,
104 p_DATA_WIDTH
=self
.data_width
,
105 p_SELECT_WIDTH
=self
.granularity
,
108 i_wbm_clk
=self
.wb_mclk
,
109 i_wbm_rst
=self
.wb_mrst
,
110 i_wbs_clk
=self
.wb_sclk
,
111 i_wbs_rst
=self
.wb_srst
,
113 # Master Wishbone bus signals
114 i_wbm_adr_i
=self
.master_bus
.adr
,
115 i_wbm_dat_i
=self
.master_bus
.dat_w
,
116 o_wbm_dat_o
=self
.master_bus
.dat_r
,
117 i_wbm_we_i
=self
.master_bus
.we
,
118 i_wbm_sel_i
=self
.master_bus
.sel
,
119 i_wbm_stb_i
=self
.master_bus
.stb
,
120 i_wbm_cyc_i
=self
.master_bus
.cyc
,
121 o_wbm_ack_o
=self
.master_bus
.ack
,
122 #o_wbm_err=self.master_bus.err,
123 #o_wbm_rty_i=self.master_bus.rty,
125 # Slave Wishbone bus signals
126 o_wbs_adr_o
=self
.slave_bus
.adr
,
127 i_wbs_dat_i
=self
.slave_bus
.dat_r
,
128 o_wbs_dat_o
=self
.slave_bus
.dat_w
,
129 o_wbs_we_o
=self
.slave_bus
.we
,
130 o_wbs_sel_o
=self
.slave_bus
.sel
,
131 o_wbs_stb_o
=self
.slave_bus
.stb
,
132 o_wbs_cyc_o
=self
.slave_bus
.cyc
,
133 i_wbs_ack_i
=slave_ack
,
134 i_wbs_err_i
=slave_err
,
135 i_wbs_rty_i
=slave_rty
138 # Wire unused signals to 0
139 comb
+= slave_err
.eq(0)
140 comb
+= slave_rty
.eq(0)
142 m
.submodules
['wb_async_bridge_%d' % self
.idx
] = wb_async_bridge
147 return [self
.master_bus
.adr
, self
.master_bus
.dat_w
,
148 self
.master_bus
.dat_r
,
149 self
.master_bus
.we
, self
.master_bus
.sel
,
151 self
.master_bus
.cyc
, self
.master_bus
.ack
,
154 self
.slave_bus
.adr
, self
.slave_bus
.dat_w
,
155 self
.slave_bus
.dat_r
,
156 self
.slave_bus
.we
, self
.slave_bus
.sel
,
158 self
.slave_bus
.cyc
, self
.slave_bus
.ack
,
163 def create_ilang(dut
, ports
, test_name
):
164 vl
= rtlil
.convert(dut
, name
=test_name
, ports
=ports
)
165 with
open("%s.il" % test_name
, "w") as f
:
168 def create_verilog(dut
, ports
, test_name
):
169 vl
= verilog
.convert(dut
, name
=test_name
, ports
=ports
)
170 with
open("%s.v" % test_name
, "w") as f
:
174 if __name__
== "__main__":
175 wbasyncbridge
= WBAsyncBridge(name
="wbasyncbridge_0", address_width
=30, data_width
=32, granularity
=8)
176 create_ilang(wbasyncbridge
, wbasyncbridge
.ports(), "wbasyncbridge_0")