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 external_core_top.v verilog module
9 # which allows for faster development iteration (oh and microwatt or
10 # other core to be dropped into a peripheral fabric)
12 from nmigen
import (Elaboratable
, Cat
, Module
, Signal
, ClockSignal
, Instance
,
14 from nmigen
.cli
import rtlil
, verilog
16 from soc
.debug
.dmi
import DMIInterface
17 from nmigen_soc
.wishbone
.bus
import Interface
20 __all__
= ["ExternalCore"]
23 class ExternalCore(Elaboratable
):
24 """External Core verilog wrapper for microwatt and libre-soc
25 (actually, anything prepared to map to the Signals defined below)
26 remember to call ExternalCore.add_verilog_source
29 def __init__(self
, ibus
=None, dbus
=None, features
=None, name
=None):
31 # set up the icache wishbone bus
33 features
= frozenset(("stall",))
35 ibus
= Interface(addr_width
=32,
41 dbus
= Interface(addr_width
=32,
46 self
.dmi
= DMIInterface(name
="dmi")
50 assert len(self
.ibus
.dat_r
) == 64, "bus width must be 64"
51 assert len(self
.dbus
.dat_r
) == 64, "bus width must be 64"
53 # IRQ for data buffer receive/xmit
56 # debug monitoring signals
58 self
.nia_req
= Signal()
60 self
.ldst_addr
= Signal(64)
61 self
.ldst_req
= Signal()
63 # alternative reset and termination indicator
64 self
.alt_reset
= Signal()
65 self
.terminated_o
= Signal()
68 def add_verilog_source(cls
, verilog_src_dir
, platform
):
69 # add each of the verilog sources, needed for when doing platform.build
70 for fname
in ['external_core_top.v',
72 # prepend the src directory to each filename, add its contents
73 fullname
= os
.path
.join(verilog_src_dir
, fname
)
74 with
open(fullname
) as f
:
75 platform
.add_file(fullname
, f
)
77 def elaborate(self
, platform
):
81 # create definition of external core here, so that
82 # nmigen understands I/O directions (defined by i_ and o_ prefixes)
83 ibus
, dbus
, dmi
= self
.ibus
, self
.dbus
, self
.dmi
87 m
.d
.comb
+= ibus
.adr
.eq(ibus_adr
)
88 m
.d
.comb
+= dbus
.adr
.eq(dbus_adr
)
92 'i_clk': ClockSignal(),
93 'i_rst': ResetSignal(),
95 'i_dmi_addr': dmi
.addr_i
,
96 'i_dmi_req': dmi
.req_i
,
99 'o_dmi_dout': dmi
.dout
,
100 'o_dmi_ack': dmi
.ack_o
,
101 # debug/monitor signals
103 'o_nia_req': self
.nia_req
,
105 'o_ldst_addr': self
.ldst_addr
,
106 'o_ldst_req': self
.ldst_req
,
107 'i_alt_reset': self
.alt_reset
,
108 'o_terminated_out': self
.terminated_o
,
109 # wishbone instruction bus
110 'o_wishbone_insn_out.adr': ibus_adr
,
111 'o_wishbone_insn_out.dat': ibus
.dat_w
,
112 'o_wishbone_insn_out.sel': ibus
.sel
,
113 'o_wishbone_insn_out.cyc': ibus
.cyc
,
114 'o_wishbone_insn_out.stb': ibus
.stb
,
115 'o_wishbone_insn_out.we': ibus
.we
,
116 'i_wishbone_insn_in.dat': ibus
.dat_r
,
117 'i_wishbone_insn_in.ack': ibus
.ack
,
118 'i_wishbone_insn_in.stall': ibus
.stall
,
120 'o_wishbone_data_out.adr': dbus_adr
,
121 'o_wishbone_data_out.dat': dbus
.dat_w
,
122 'o_wishbone_data_out.sel': dbus
.sel
,
123 'o_wishbone_data_out.cyc': dbus
.cyc
,
124 'o_wishbone_data_out.stb': dbus
.stb
,
125 'o_wishbone_data_out.we': dbus
.we
,
126 'i_wishbone_data_in.dat': dbus
.dat_r
,
127 'i_wishbone_data_in.ack': dbus
.ack
,
128 'i_wishbone_data_in.stall': dbus
.stall
,
129 # external interrupt request
130 'i_ext_irq': self
.irq
,
132 core
= Instance("external_core_top", **kwargs
)
133 m
.submodules
['core_top'] = core
138 def create_ilang(dut
, ports
, test_name
):
139 vl
= rtlil
.convert(dut
, name
=test_name
, ports
=ports
)
140 with
open("%s.il" % test_name
, "w") as f
:
143 def create_verilog(dut
, ports
, test_name
):
144 vl
= verilog
.convert(dut
, name
=test_name
, ports
=ports
)
145 with
open("%s.v" % test_name
, "w") as f
:
149 if __name__
== "__main__":
150 core
= ExternalCore(name
="core")
152 core
.ibus
.cyc
, core
.ibus
.stb
, core
.ibus
.ack
,
153 core
.ibus
.dat_r
, core
.ibus
.dat_w
, core
.ibus
.adr
,
154 core
.ibus
.we
, core
.ibus
.sel
, core
.ibus
.stall
,
155 core
.dbus
.cyc
, core
.dbus
.stb
, core
.dbus
.ack
,
156 core
.dbus
.dat_r
, core
.dbus
.dat_w
, core
.dbus
.adr
,
157 core
.dbus
.we
, core
.dbus
.sel
,
158 core
.irq
, core
.alt_reset
, core
.terminated_o
,
159 core
.msr
, core
.nia
, core
.nia_req
,
160 core
.ldst_addr
, core
.ldst_req
,
161 core
.dmi
.addr_i
, core
.dmi
.req_i
, core
.dmi
.we_i
,
162 core
.dmi
.din
, core
.dmi
.dout
, core
.dmi
.ack_o
,