1 # This file is Copyright (c) 2018 Dolu1990 <charles.papon.90@gmail.com>
2 # This file is Copyright (c) 2018-2019 Florent Kermarrec <florent@enjoy-digital.fr>
3 # This file is Copyright (c) 2018-2019 Sean Cross <sean@xobs.io>
4 # This file is Copyright (c) 2019 Tim 'mithro' Ansell <me@mith.ro>
5 # This file is Copyright (c) 2019 David Shah <dave@ds0.me>
6 # This file is Copyright (c) 2019 Antmicro <www.antmicro.com>
7 # This file is Copyright (c) 2019 Kurt Kiefer <kekiefer@gmail.com>
15 from litex
import get_data_mod
16 from litex
.soc
.interconnect
import wishbone
17 from litex
.soc
.interconnect
.csr
import *
18 from litex
.soc
.cores
.cpu
import CPU
, CPU_GCC_TRIPLE_RISCV32
22 "minimal": "VexRiscv_Min",
23 "minimal+debug": "VexRiscv_MinDebug",
24 "lite": "VexRiscv_Lite",
25 "lite+debug": "VexRiscv_LiteDebug",
26 "standard": "VexRiscv",
27 "standard+debug": "VexRiscv_Debug",
28 "imac": "VexRiscv_IMAC",
29 "imac+debug": "VexRiscv_IMACDebug",
30 "full": "VexRiscv_Full",
31 "full+debug": "VexRiscv_FullDebug",
32 "linux": "VexRiscv_Linux",
33 "linux+debug": "VexRiscv_LinuxDebug",
34 "linux+no-dsp": "VexRiscv_LinuxNoDspFmax",
40 # |/------- Hardware Multiply + Divide
42 # |||/---- Compressed ISA
43 # ||||/--- Single-Precision Floating-Point
44 # |||||/-- Double-Precision Floating-Point
46 "minimal": "-march=rv32i -mabi=ilp32",
47 "minimal+debug": "-march=rv32i -mabi=ilp32",
48 "lite": "-march=rv32i -mabi=ilp32",
49 "lite+debug": "-march=rv32i -mabi=ilp32",
50 "standard": "-march=rv32im -mabi=ilp32",
51 "standard+debug": "-march=rv32im -mabi=ilp32",
52 "imac": "-march=rv32imac -mabi=ilp32",
53 "imac+debug": "-march=rv32imac -mabi=ilp32",
54 "full": "-march=rv32im -mabi=ilp32",
55 "full+debug": "-march=rv32im -mabi=ilp32",
56 "linux": "-march=rv32ima -mabi=ilp32",
57 "linux+debug": "-march=rv32ima -mabi=ilp32",
58 "linux+no-dsp": "-march=rv32ima -mabi=ilp32",
62 class VexRiscvTimer(Module
, AutoCSR
):
65 self
._time
= CSRStatus(64)
66 self
._time
_cmp
= CSRStorage(64, reset
=2**64-1)
67 self
.interrupt
= Signal()
72 self
.sync
+= time
.eq(time
+ 1)
73 self
.sync
+= If(self
._latch
.re
, self
._time
.status
.eq(time
))
75 time_cmp
= Signal(64, reset
=2**64-1)
76 self
.sync
+= If(self
._latch
.re
, time_cmp
.eq(self
._time
_cmp
.storage
))
78 self
.comb
+= self
.interrupt
.eq(time
>= time_cmp
)
81 class VexRiscv(CPU
, AutoCSR
):
83 human_name
= "VexRiscv"
84 variants
= CPU_VARIANTS
87 gcc_triple
= CPU_GCC_TRIPLE_RISCV32
88 linker_output_format
= "elf32-littleriscv"
90 io_regions
= {0x80000000: 0x80000000} # origin, length
93 def mem_map_linux(self
):
97 "main_ram": 0x40000000,
103 flags
= GCC_FLAGS
[self
.variant
]
104 flags
+= " -D__vexriscv__"
107 def __init__(self
, platform
, variant
="standard"):
108 self
.platform
= platform
109 self
.variant
= variant
110 self
.external_variant
= None
111 self
.reset
= Signal()
112 self
.interrupt
= Signal(32)
113 self
.ibus
= ibus
= wishbone
.Interface()
114 self
.dbus
= dbus
= wishbone
.Interface()
115 self
.periph_buses
= [ibus
, dbus
]
116 self
.memory_buses
= []
120 self
.cpu_params
= dict(
121 i_clk
= ClockSignal(),
122 i_reset
= ResetSignal() | self
.reset
,
124 i_externalInterruptArray
= self
.interrupt
,
125 i_timerInterrupt
= 0,
126 i_softwareInterrupt
= 0,
128 o_iBusWishbone_ADR
= ibus
.adr
,
129 o_iBusWishbone_DAT_MOSI
= ibus
.dat_w
,
130 o_iBusWishbone_SEL
= ibus
.sel
,
131 o_iBusWishbone_CYC
= ibus
.cyc
,
132 o_iBusWishbone_STB
= ibus
.stb
,
133 o_iBusWishbone_WE
= ibus
.we
,
134 o_iBusWishbone_CTI
= ibus
.cti
,
135 o_iBusWishbone_BTE
= ibus
.bte
,
136 i_iBusWishbone_DAT_MISO
= ibus
.dat_r
,
137 i_iBusWishbone_ACK
= ibus
.ack
,
138 i_iBusWishbone_ERR
= ibus
.err
,
140 o_dBusWishbone_ADR
= dbus
.adr
,
141 o_dBusWishbone_DAT_MOSI
= dbus
.dat_w
,
142 o_dBusWishbone_SEL
= dbus
.sel
,
143 o_dBusWishbone_CYC
= dbus
.cyc
,
144 o_dBusWishbone_STB
= dbus
.stb
,
145 o_dBusWishbone_WE
= dbus
.we
,
146 o_dBusWishbone_CTI
= dbus
.cti
,
147 o_dBusWishbone_BTE
= dbus
.bte
,
148 i_dBusWishbone_DAT_MISO
= dbus
.dat_r
,
149 i_dBusWishbone_ACK
= dbus
.ack
,
150 i_dBusWishbone_ERR
= dbus
.err
153 if "linux" in variant
:
155 self
.mem_map
= self
.mem_map_linux
157 if "debug" in variant
:
161 debug_reset
= Signal()
166 self
.i_cmd_valid
= Signal()
167 self
.i_cmd_payload_wr
= Signal()
168 self
.i_cmd_payload_address
= Signal(8)
169 self
.i_cmd_payload_data
= Signal(32)
170 self
.o_cmd_ready
= Signal()
171 self
.o_rsp_data
= Signal(32)
172 self
.o_resetOut
= Signal()
174 reset_debug_logic
= Signal()
176 self
.transfer_complete
= Signal()
177 self
.transfer_in_progress
= Signal()
178 self
.transfer_wait_for_ack
= Signal()
180 self
.debug_bus
= wishbone
.Interface()
183 self
.debug_bus
.dat_r
.eq(self
.o_rsp_data
),
184 debug_reset
.eq(reset_debug_logic |
ResetSignal()),
188 # CYC is held high for the duration of the transfer.
189 # STB is kept high when the transfer finishes (write)
190 # or the master is waiting for data (read), and stays
191 # there until ACK, ERR, or RTY are asserted.
192 If((self
.debug_bus
.stb
& self
.debug_bus
.cyc
)
193 & (~self
.transfer_in_progress
)
194 & (~self
.transfer_complete
)
195 & (~self
.transfer_wait_for_ack
),
196 self
.i_cmd_payload_data
.eq(self
.debug_bus
.dat_w
),
197 self
.i_cmd_payload_address
.eq((self
.debug_bus
.adr
[0:6] << 2) |
0),
198 self
.i_cmd_payload_wr
.eq(self
.debug_bus
.we
),
199 self
.i_cmd_valid
.eq(1),
200 self
.transfer_in_progress
.eq(1),
201 self
.transfer_complete
.eq(0),
202 self
.debug_bus
.ack
.eq(0)
203 ).Elif(self
.transfer_in_progress
,
205 self
.i_cmd_valid
.eq(0),
206 self
.i_cmd_payload_wr
.eq(0),
207 self
.transfer_complete
.eq(1),
208 self
.transfer_in_progress
.eq(0)
210 ).Elif(self
.transfer_complete
,
211 self
.transfer_complete
.eq(0),
212 self
.debug_bus
.ack
.eq(1),
213 self
.transfer_wait_for_ack
.eq(1)
214 ).Elif(self
.transfer_wait_for_ack
& ~
(self
.debug_bus
.stb
& self
.debug_bus
.cyc
),
215 self
.transfer_wait_for_ack
.eq(0),
216 self
.debug_bus
.ack
.eq(0)
218 # Force a Wishbone error if transferring during a reset sequence.
219 # Because o_resetOut is multiple cycles and i.stb/d.stb should
220 # deassert one cycle after i_err/i_ack/d_err/d_ack are asserted,
221 # this will give i_err and o_err enough time to be reset to 0
222 # once the reset cycle finishes.
224 If(self
.ibus
.cyc
& self
.ibus
.stb
, ibus_err
.eq(1)).Else(ibus_err
.eq(0)),
225 If(self
.dbus
.cyc
& self
.dbus
.stb
, dbus_err
.eq(1)).Else(dbus_err
.eq(0)),
226 reset_debug_logic
.eq(1))
228 reset_debug_logic
.eq(0)
232 self
.cpu_params
.update(
233 i_reset
=ResetSignal() | self
.reset | debug_reset
,
234 i_iBusWishbone_ERR
=self
.ibus
.err | ibus_err
,
235 i_dBusWishbone_ERR
=self
.dbus
.err | dbus_err
,
236 i_debugReset
= ResetSignal(),
237 i_debug_bus_cmd_valid
= self
.i_cmd_valid
,
238 i_debug_bus_cmd_payload_wr
= self
.i_cmd_payload_wr
,
239 i_debug_bus_cmd_payload_address
= self
.i_cmd_payload_address
,
240 i_debug_bus_cmd_payload_data
= self
.i_cmd_payload_data
,
241 o_debug_bus_cmd_ready
= self
.o_cmd_ready
,
242 o_debug_bus_rsp_data
= self
.o_rsp_data
,
243 o_debug_resetOut
= self
.o_resetOut
246 def set_reset_address(self
, reset_address
):
247 assert not hasattr(self
, "reset_address")
248 self
.reset_address
= reset_address
249 self
.cpu_params
.update(i_externalResetVector
=Signal(32, reset
=reset_address
))
252 self
.submodules
.timer
= VexRiscvTimer()
253 self
.cpu_params
.update(i_timerInterrupt
=self
.timer
.interrupt
)
256 def add_sources(platform
, variant
="standard"):
257 cpu_filename
= CPU_VARIANTS
[variant
] + ".v"
258 vdir
= get_data_mod("cpu", "vexriscv").data_location
259 platform
.add_source(os
.path
.join(vdir
, cpu_filename
))
261 def use_external_variant(self
, variant_filename
):
262 self
.external_variant
= True
263 self
.platform
.add_source(variant_filename
)
265 def do_finalize(self
):
266 assert hasattr(self
, "reset_address")
267 if not self
.external_variant
:
268 self
.add_sources(self
.platform
, self
.variant
)
269 self
.specials
+= Instance("VexRiscv", **self
.cpu_params
)