diff --git a/litex/soc/cores/cpu/vexriscv/core.py b/litex/soc/cores/cpu/vexriscv/core.py index 6b9b7743a..b5f87ec38 100644 --- a/litex/soc/cores/cpu/vexriscv/core.py +++ b/litex/soc/cores/cpu/vexriscv/core.py @@ -19,16 +19,11 @@ class VexRiscv(Module, AutoCSR): variants = ("std", "std_debug", "lite", "lite_debug", "min", "min_debug") assert variant in variants, "Unsupported variant %s" % variant self.reset = Signal() - self.ibus = i = wishbone.Interface() - self.dbus = d = wishbone.Interface() - i_err = Signal() - d_err = Signal() + self.ibus = ibus = wishbone.Interface() + self.dbus = dbus = wishbone.Interface() self.interrupt = Signal(32) - # Output reset signal -- set to 1 when CPU reset is asserted - self.debug_reset = Signal() - verilog_variants = { "std": "VexRiscv.v", "std_debug": "VexRiscv_Debug.v", @@ -37,134 +32,136 @@ class VexRiscv(Module, AutoCSR): "min": "VexRiscv_Lite.v", "min_debug": "VexRiscv_LiteDebug.v", } - - cpu_reset = ResetSignal() - cpu_args = {} cpu_filename = verilog_variants[variant] - if "debug" in variant: - cpu_reset = Signal() - cpu_args = {} - - self.i_cmd_valid = Signal() - self.i_cmd_payload_wr = Signal() - self.i_cmd_payload_address = Signal(8) - self.i_cmd_payload_data = Signal(32) - self.o_cmd_ready = Signal() - self.o_rsp_data = Signal(32) - self.o_resetOut = Signal() - - reset_debug_logic = Signal() - - self.transfer_complete = Signal() - self.transfer_in_progress = Signal() - self.transfer_wait_for_ack = Signal() - - self.debug_bus = wishbone.Interface() - - self.sync += [ - self.debug_bus.dat_r.eq(self.o_rsp_data), - cpu_reset.eq(reset_debug_logic | ResetSignal()), - ] - - self.sync += [ - # CYC is held high for the duration of the transfer. - # STB is kept high when the transfer finishes (write) - # or the master is waiting for data (read), and stays - # there until ACK, ERR, or RTY are asserted. - If((self.debug_bus.stb & self.debug_bus.cyc) - & (~self.transfer_in_progress) - & (~self.transfer_complete) - & (~self.transfer_wait_for_ack), - self.i_cmd_payload_data.eq(self.debug_bus.dat_w), - self.i_cmd_payload_address.eq((self.debug_bus.adr[0:6] << 2) | 0), - self.i_cmd_payload_wr.eq(self.debug_bus.we), - self.i_cmd_valid.eq(1), - self.transfer_in_progress.eq(1), - self.transfer_complete.eq(0), - self.debug_bus.ack.eq(0) - ).Elif(self.transfer_in_progress, - If(self.o_cmd_ready, - self.i_cmd_valid.eq(0), - self.i_cmd_payload_wr.eq(0), - self.transfer_complete.eq(1), - self.transfer_in_progress.eq(0) - ) - ).Elif(self.transfer_complete, - self.transfer_complete.eq(0), - self.debug_bus.ack.eq(1), - self.transfer_wait_for_ack.eq(1) - ).Elif(self.transfer_wait_for_ack & ~(self.debug_bus.stb & self.debug_bus.cyc), - self.transfer_wait_for_ack.eq(0), - self.debug_bus.ack.eq(0) - ), - # Force a Wishbone error if transferring during a reset sequence. - # Because o_resetOut is multiple cycles and i.stb/d.stb should - # deassert one cycle after i_err/i_ack/d_err/d_ack are asserted, - # this will give i_err and o_err enough time to be reset to 0 - # once the reset cycle finishes. - If(self.o_resetOut, - If(i.cyc & i.stb, i_err.eq(1)).Else(i_err.eq(0)), - If(d.cyc & d.stb, d_err.eq(1)).Else(d_err.eq(0)), - reset_debug_logic.eq(1)) - .Else( - reset_debug_logic.eq(0) - ) - ] - - cpu_args.update({ - "i_debugReset": ResetSignal(), - "i_debug_bus_cmd_valid": self.i_cmd_valid, - "i_debug_bus_cmd_payload_wr": self.i_cmd_payload_wr, - "i_debug_bus_cmd_payload_address": self.i_cmd_payload_address, - "i_debug_bus_cmd_payload_data": self.i_cmd_payload_data, - "o_debug_bus_cmd_ready": self.o_cmd_ready, - "o_debug_bus_rsp_data": self.o_rsp_data, - "o_debug_resetOut": self.o_resetOut - }) - - self.comb += [ - i.err.eq(i_err), - d.err.eq(d_err), - ] - self.specials += Instance("VexRiscv", - **cpu_args, - + self.cpu_params = dict( i_clk=ClockSignal(), - i_reset=cpu_reset | self.reset, + i_reset=ResetSignal() | self.reset, i_externalResetVector=cpu_reset_address, i_externalInterruptArray=self.interrupt, i_timerInterrupt=0, - o_iBusWishbone_ADR=i.adr, - o_iBusWishbone_DAT_MOSI=i.dat_w, - o_iBusWishbone_SEL=i.sel, - o_iBusWishbone_CYC=i.cyc, - o_iBusWishbone_STB=i.stb, - o_iBusWishbone_WE=i.we, - o_iBusWishbone_CTI=i.cti, - o_iBusWishbone_BTE=i.bte, - i_iBusWishbone_DAT_MISO=i.dat_r, - i_iBusWishbone_ACK=i.ack, - i_iBusWishbone_ERR=i_err, + o_iBusWishbone_ADR=ibus.adr, + o_iBusWishbone_DAT_MOSI=ibus.dat_w, + o_iBusWishbone_SEL=ibus.sel, + o_iBusWishbone_CYC=ibus.cyc, + o_iBusWishbone_STB=ibus.stb, + o_iBusWishbone_WE=ibus.we, + o_iBusWishbone_CTI=ibus.cti, + o_iBusWishbone_BTE=ibus.bte, + i_iBusWishbone_DAT_MISO=ibus.dat_r, + i_iBusWishbone_ACK=ibus.ack, + i_iBusWishbone_ERR=ibus.err, - o_dBusWishbone_ADR=d.adr, - o_dBusWishbone_DAT_MOSI=d.dat_w, - o_dBusWishbone_SEL=d.sel, - o_dBusWishbone_CYC=d.cyc, - o_dBusWishbone_STB=d.stb, - o_dBusWishbone_WE=d.we, - o_dBusWishbone_CTI=d.cti, - o_dBusWishbone_BTE=d.bte, - i_dBusWishbone_DAT_MISO=d.dat_r, - i_dBusWishbone_ACK=d.ack, - i_dBusWishbone_ERR=d_err) + o_dBusWishbone_ADR=dbus.adr, + o_dBusWishbone_DAT_MOSI=dbus.dat_w, + o_dBusWishbone_SEL=dbus.sel, + o_dBusWishbone_CYC=dbus.cyc, + o_dBusWishbone_STB=dbus.stb, + o_dBusWishbone_WE=dbus.we, + o_dBusWishbone_CTI=dbus.cti, + o_dBusWishbone_BTE=dbus.bte, + i_dBusWishbone_DAT_MISO=dbus.dat_r, + i_dBusWishbone_ACK=dbus.ack, + i_dBusWishbone_ERR=dbus.err) + + if "debug" in variant: + self.add_debug() # add verilog sources self.add_sources(platform, cpu_filename) + def add_debug(self): + debug_reset = Signal() + + ibus_err = Signal() + dbus_err = Signal() + + self.i_cmd_valid = Signal() + self.i_cmd_payload_wr = Signal() + self.i_cmd_payload_address = Signal(8) + self.i_cmd_payload_data = Signal(32) + self.o_cmd_ready = Signal() + self.o_rsp_data = Signal(32) + self.o_resetOut = Signal() + + reset_debug_logic = Signal() + + self.transfer_complete = Signal() + self.transfer_in_progress = Signal() + self.transfer_wait_for_ack = Signal() + + self.debug_bus = wishbone.Interface() + + self.sync += [ + self.debug_bus.dat_r.eq(self.o_rsp_data), + debug_reset.eq(reset_debug_logic | ResetSignal()), + ] + + self.sync += [ + # CYC is held high for the duration of the transfer. + # STB is kept high when the transfer finishes (write) + # or the master is waiting for data (read), and stays + # there until ACK, ERR, or RTY are asserted. + If((self.debug_bus.stb & self.debug_bus.cyc) + & (~self.transfer_in_progress) + & (~self.transfer_complete) + & (~self.transfer_wait_for_ack), + self.i_cmd_payload_data.eq(self.debug_bus.dat_w), + self.i_cmd_payload_address.eq((self.debug_bus.adr[0:6] << 2) | 0), + self.i_cmd_payload_wr.eq(self.debug_bus.we), + self.i_cmd_valid.eq(1), + self.transfer_in_progress.eq(1), + self.transfer_complete.eq(0), + self.debug_bus.ack.eq(0) + ).Elif(self.transfer_in_progress, + If(self.o_cmd_ready, + self.i_cmd_valid.eq(0), + self.i_cmd_payload_wr.eq(0), + self.transfer_complete.eq(1), + self.transfer_in_progress.eq(0) + ) + ).Elif(self.transfer_complete, + self.transfer_complete.eq(0), + self.debug_bus.ack.eq(1), + self.transfer_wait_for_ack.eq(1) + ).Elif(self.transfer_wait_for_ack & ~(self.debug_bus.stb & self.debug_bus.cyc), + self.transfer_wait_for_ack.eq(0), + self.debug_bus.ack.eq(0) + ), + # Force a Wishbone error if transferring during a reset sequence. + # Because o_resetOut is multiple cycles and i.stb/d.stb should + # deassert one cycle after i_err/i_ack/d_err/d_ack are asserted, + # this will give i_err and o_err enough time to be reset to 0 + # once the reset cycle finishes. + If(self.o_resetOut, + If(self.ibus.cyc & self.ibus.stb, ibus_err.eq(1)).Else(ibus_err.eq(0)), + If(self.dbus.cyc & self.dbus.stb, dbus_err.eq(1)).Else(dbus_err.eq(0)), + reset_debug_logic.eq(1)) + .Else( + reset_debug_logic.eq(0) + ) + ] + + self.cpu_params.update( + i_reset=ResetSignal() | self.reset | debug_reset, + i_iBusWishbone_ERR=self.ibus.err | ibus_err, + i_dBusWishbone_ERR=self.dbus.err | dbus_err, + i_debugReset=ResetSignal(), + i_debug_bus_cmd_valid=self.i_cmd_valid, + i_debug_bus_cmd_payload_wr=self.i_cmd_payload_wr, + i_debug_bus_cmd_payload_address=self.i_cmd_payload_address, + i_debug_bus_cmd_payload_data=self.i_cmd_payload_data, + o_debug_bus_cmd_ready=self.o_cmd_ready, + o_debug_bus_rsp_data=self.o_rsp_data, + o_debug_resetOut=self.o_resetOut + ) + @staticmethod def add_sources(platform, cpu_filename): vdir = os.path.join(os.path.abspath(os.path.dirname(__file__)), "verilog") platform.add_source(os.path.join(vdir, cpu_filename)) + + def do_finalize(self): + self.specials += Instance("VexRiscv", **self.cpu_params)