b90913d1ce704fa69aa65839c986bdea330295fa
3 # SPDX-License-Identifier: LGPLv3+
4 # Copyright (C) 2022 Luke Kenneth Casson Leighton <lkcl@lkcl.net>
5 # Sponsored by NLnet and NGI POINTER under EU Grants 871528 and 957073
6 # Part of the Libre-SOC Project.
8 # this is a wrapper around the opencores verilog core16550 module
10 from nmigen
import (Elaboratable
, Cat
, Module
, Signal
, ClockSignal
, Instance
,
12 from nmigen
.cli
import rtlil
, verilog
14 from soc
.debug
.dmi
import DMIInterface
15 from nmigen_soc
.wishbone
.bus
import Interface
18 __all__
= ["ExternalCore"]
21 class ExternalCore(Elaboratable
):
22 """External Core verilog wrapper for microwatt and libre-soc
23 (actually, anything prepared to map to the Signals defined below)
24 remember to call ExternalCore.add_verilog_source
27 def __init__(self
, ibus
=None, dbus
=None, features
=None, name
=None):
29 # set up the icache wishbone bus
31 features
= frozenset(("stall",))
33 ibus
= Interface(addr_width
=32,
39 dbus
= Interface(addr_width
=32,
44 self
.dmi
= DMIInterface(name
="dmi")
48 assert len(self
.ibus
.dat_r
) == 64, "bus width must be 64"
49 assert len(self
.dbus
.dat_r
) == 64, "bus width must be 64"
51 # IRQ for data buffer receive/xmit
54 # debug monitoring signals
56 self
.nia_req
= Signal()
58 self
.ldst_addr
= Signal(64)
59 self
.ldst_req
= Signal()
61 # alternative reset and termination indicator
62 self
.alt_reset
= Signal()
63 self
.terminated_o
= Signal()
66 def add_verilog_source(cls
, verilog_src_dir
, platform
):
67 # add each of the verilog sources, needed for when doing platform.build
68 for fname
in ['external_core_top.v',
70 # prepend the src directory to each filename, add its contents
71 fullname
= os
.path
.join(verilog_src_dir
, fname
)
72 with
open(fullname
) as f
:
73 platform
.add_file(fullname
, f
)
75 def elaborate(self
, platform
):
79 # create definition of external core here, so that
80 # nmigen understands I/O directions (defined by i_ and o_ prefixes)
81 ibus
, dbus
, dmi
= self
.ibus
, self
.dbus
, self
.dmi
83 # sigh, microwatt wishbone address is borked, it contains the 3 LSBs
86 m
.d
.comb
+= ibus
.adr
.eq(ibus_adr
[3:])
87 m
.d
.comb
+= dbus
.adr
.eq(dbus_adr
[3:])
91 'i_clk': ClockSignal(),
92 'i_rst': ResetSignal(),
94 'i_dmi_addr': dmi
.addr_i
,
95 'i_dmi_req': dmi
.req_i
,
98 'o_dmi_dout': dmi
.dout
,
99 'o_dmi_ack': dmi
.ack_o
,
100 # debug/monitor signals
102 'o_nia_req': self
.nia_req
,
104 'o_ldst_addr': self
.ldst_addr
,
105 'o_ldst_req': self
.ldst_req
,
106 'i_alt_reset': self
.alt_reset
,
107 'o_terminated_out': self
.terminated_o
,
108 # wishbone instruction bus
109 'o_wishbone_insn_out.adr': ibus_adr
,
110 'o_wishbone_insn_out.dat': ibus
.dat_w
,
111 'o_wishbone_insn_out.sel': ibus
.sel
,
112 'o_wishbone_insn_out.cyc': ibus
.cyc
,
113 'o_wishbone_insn_out.stb': ibus
.stb
,
114 'o_wishbone_insn_out.we': ibus
.we
,
115 'i_wishbone_insn_in.dat': ibus
.dat_r
,
116 'i_wishbone_insn_in.ack': ibus
.ack
,
117 'i_wishbone_insn_in.stall': ibus
.stall
,
119 'o_wishbone_data_out.adr': dbus_adr
,
120 'o_wishbone_data_out.dat': dbus
.dat_w
,
121 'o_wishbone_data_out.sel': dbus
.sel
,
122 'o_wishbone_data_out.cyc': dbus
.cyc
,
123 'o_wishbone_data_out.stb': dbus
.stb
,
124 'o_wishbone_data_out.we': dbus
.we
,
125 'i_wishbone_data_in.dat': dbus
.dat_r
,
126 'i_wishbone_data_in.ack': dbus
.ack
,
127 'i_wishbone_data_in.stall': dbus
.stall
,
128 # external interrupt request
129 'i_ext_irq': self
.irq
,
131 core
= Instance("external_core_top", **kwargs
)
132 m
.submodules
['core_top'] = core
137 def create_ilang(dut
, ports
, test_name
):
138 vl
= rtlil
.convert(dut
, name
=test_name
, ports
=ports
)
139 with
open("%s.il" % test_name
, "w") as f
:
142 def create_verilog(dut
, ports
, test_name
):
143 vl
= verilog
.convert(dut
, name
=test_name
, ports
=ports
)
144 with
open("%s.v" % test_name
, "w") as f
:
148 if __name__
== "__main__":
149 core
= ExternalCore(name
="core")
151 core
.ibus
.cyc
, core
.ibus
.stb
, core
.ibus
.ack
,
152 core
.ibus
.dat_r
, core
.ibus
.dat_w
, core
.ibus
.adr
,
153 core
.ibus
.we
, core
.ibus
.sel
, core
.ibus
.stall
,
154 core
.dbus
.cyc
, core
.dbus
.stb
, core
.dbus
.ack
,
155 core
.dbus
.dat_r
, core
.dbus
.dat_w
, core
.dbus
.adr
,
156 core
.dbus
.we
, core
.dbus
.sel
,
157 core
.irq
, core
.alt_reset
, core
.terminated_o
,
158 core
.msr
, core
.nia
, core
.nia_req
,
159 core
.ldst_addr
, core
.ldst_req
,
160 core
.dmi
.addr_i
, core
.dmi
.req_i
, core
.dmi
.we_i
,
161 core
.dmi
.din
, core
.dmi
.dout
, core
.dmi
.ack_o
,