def setUp(self): # Ensure IS_SIM_RUN set global _IS_SIM_RUN _IS_SIM_RUN = True # Create DUT and add to simulator self.m = Module() self.dut = self.create_dut() self.m.submodules['dut'] = self.dut self.m.submodules['dummy'] = _DummySyncModule() self.sim = Simulator(self.m)
def __init__(self, platform): m = Module() led1 = platform.request("ld1", 0) led2 = platform.request("ld2", 0) switch = platform.request("v16", 0) m.d.comb += led1.o.eq(1) m.d.comb += led2.o.eq(~switch) return m
def elaborate(platform): m = Module() m.submodules.alu = alu = ALU(16) # wire top level ports m.d.comb += [ alu.op.eq(op), alu.a.eq(a), alu.b.eq(b), o.eq(alu.o)] return m
def elaborate(self, _: Platform) -> Module: """Implements the logic for the Counter module.""" m = Module() with m.If(self.count == 9): m.d.sync += self.count.eq(1) with m.Else(): m.d.sync += self.count.eq(self.count+1) return m
def elaborate(self, platform): m = Module() m.submodules += self.ila # Grab a reference to our debug-SPI bus. board_spi = synchronize(m, platform.request("debug_spi")) # Clock divider / counter. m.d.sync += self.counter.eq(self.counter + 1) # Another example signal, for variety. m.d.sync += self.toggle.eq(~self.toggle) # Create an SPI bus for our ILA. ila_spi = SPIBus() m.d.comb += [ self.ila.spi.connect(ila_spi), # For sharing, we'll connect the _inverse_ of the primary # chip select to our ILA bus. This will allow us to send # ILA data when CS is un-asserted, and register data when # CS is asserted. ila_spi.cs.eq(~board_spi.cs) ] # Create a set of registers... spi_registers = SPIRegisterInterface() m.submodules.spi_registers = spi_registers # ... and an SPI bus for them. reg_spi = SPIBus() m.d.comb += [ spi_registers.spi.connect(reg_spi), reg_spi.cs.eq(board_spi.cs) ] # Multiplex our ILA and register SPI busses. m.submodules.mux = SPIMultiplexer([ila_spi, reg_spi]) m.d.comb += m.submodules.mux.shared_lines.connect(board_spi) # Add a simple ID register to demonstrate our registers. spi_registers.add_read_only_register(REGISTER_ID, read=0xDEADBEEF) # Create a simple SFR that will trigger an ILA capture when written, # and which will display our sample status read. spi_registers.add_sfr(REGISTER_ILA, read=self.ila.complete, write_strobe=self.ila.trigger) # Attach the LEDs and User I/O to the MSBs of our counter. leds = [platform.request("led", i, dir="o") for i in range(0, 6)] m.d.comb += Cat(leds).eq(self.counter[-7:-1]) # Return our elaborated module. return m
def formal(cls) -> Tuple[Module, List[Signal]]: """Formal verification for the active low 74182 chip.""" m = Module() m.submodules.clu = clu = IC_74182_active_low() # Verify the truth tables in the datasheet with m.If(clu.np.matches("0000")): m.d.comb += Assert(clu.group_np == 0) with m.Else(): m.d.comb += Assert(clu.group_np == 1) with m.If(clu.ng.matches("0---") & clu.np.matches("----")): m.d.comb += Assert(clu.group_ng == 0) with m.Elif(clu.ng.matches("-0--") & clu.np.matches("0---")): m.d.comb += Assert(clu.group_ng == 0) with m.Elif(clu.ng.matches("--0-") & clu.np.matches("00--")): m.d.comb += Assert(clu.group_ng == 0) with m.Elif(clu.ng.matches("---0") & clu.np.matches("000-")): m.d.comb += Assert(clu.group_ng == 0) with m.Else(): m.d.comb += Assert(clu.group_ng == 1) with m.If(clu.ng[0] == 0): m.d.comb += Assert(clu.carryout_x == 1) with m.Elif((clu.np[0] == 0) & (clu.carryin == 1)): m.d.comb += Assert(clu.carryout_x == 1) with m.Else(): m.d.comb += Assert(clu.carryout_x == 0) with m.If(clu.ng.matches("--0-") & clu.np.matches("----")): m.d.comb += Assert(clu.carryout_y == 1) with m.Elif(clu.ng.matches("---0") & clu.np.matches("--0-")): m.d.comb += Assert(clu.carryout_y == 1) with m.Elif( clu.ng.matches("----") & clu.np.matches("--00") & (clu.carryin == 1)): m.d.comb += Assert(clu.carryout_y == 1) with m.Else(): m.d.comb += Assert(clu.carryout_y == 0) with m.If(clu.ng.matches("-0--") & clu.np.matches("----")): m.d.comb += Assert(clu.carryout_z == 1) with m.Elif(clu.ng.matches("--0-") & clu.np.matches("-0--")): m.d.comb += Assert(clu.carryout_z == 1) with m.Elif(clu.ng.matches("---0") & clu.np.matches("-00-")): m.d.comb += Assert(clu.carryout_z == 1) with m.Elif( clu.ng.matches("----") & clu.np.matches("-000") & (clu.carryin == 1)): m.d.comb += Assert(clu.carryout_z == 1) with m.Else(): m.d.comb += Assert(clu.carryout_z == 0) return m, clu.ports()
def elaborate(self, platform): m = Module() a = Signal(signed(33)) b = Signal(signed(33)) result_ll = Signal(32) result_lh = Signal(33) result_hl = Signal(33) result_hh = Signal(33) result_3 = Signal(64) result_4 = Signal(64) active = Signal(5) is_signed = Signal() a_is_signed = Signal() b_is_signed = Signal() low = Signal() m.d.sync += [ is_signed.eq(a_is_signed ^ b_is_signed), active.eq(Cat(self.valid & (active == 0), active)), low.eq(self.op == Funct3.MUL) ] # fist state m.d.comb += [ a_is_signed.eq(( (self.op == Funct3.MULH) | (self.op == Funct3.MULHSU)) & self.dat1[-1]), b_is_signed.eq((self.op == Funct3.MULH) & self.dat2[-1]) ] m.d.sync += [ a.eq(Mux(a_is_signed, -Cat(self.dat1, 1), self.dat1)), b.eq(Mux(b_is_signed, -Cat(self.dat2, 1), self.dat2)), ] # second state m.d.sync += [ result_ll.eq(a[0:16] * b[0:16]), result_lh.eq(a[0:16] * b[16:33]), result_hl.eq(a[16:33] * b[0:16]), result_hh.eq(a[16:33] * b[16:33]) ] # third state m.d.sync += [ result_3.eq( Cat(result_ll, result_hh) + Cat(Repl(0, 16), (result_lh + result_hl))) ] # fourth state m.d.sync += [ result_4.eq(Mux(is_signed, -result_3, result_3)), self.result.eq(Mux(low, result_4[:32], result_4[32:64])) ] m.d.comb += self.ready.eq(active[-1]) return m
def elaborate(self, platform): m = Module() # Register input data on the data_valid signal data_reg = Signal(8) with m.FSM() as fsm: m.d.comb += [ self.ready.eq(fsm.ongoing("IDLE") | fsm.ongoing("NIBBLE4")), self.txen.eq(~fsm.ongoing("IDLE")), ] with m.State("IDLE"): m.d.comb += [ self.txd0.eq(0), self.txd1.eq(0), ] m.d.sync += data_reg.eq(self.data) with m.If(self.data_valid): m.next = "NIBBLE1" with m.State("NIBBLE1"): m.d.comb += [ self.txd0.eq(data_reg[0]), self.txd1.eq(data_reg[1]), ] m.next = "NIBBLE2" with m.State("NIBBLE2"): m.d.comb += [ self.txd0.eq(data_reg[2]), self.txd1.eq(data_reg[3]), ] m.next = "NIBBLE3" with m.State("NIBBLE3"): m.d.comb += [ self.txd0.eq(data_reg[4]), self.txd1.eq(data_reg[5]), ] m.next = "NIBBLE4" with m.State("NIBBLE4"): m.d.comb += [ self.txd0.eq(data_reg[6]), self.txd1.eq(data_reg[7]), ] m.d.sync += data_reg.eq(self.data) with m.If(self.data_valid): m.next = "NIBBLE1" with m.Else(): m.next = "IDLE" return m
def elaborate(self, platform): """ """ m = Module() dbuf = Signal(self._width) m.d[self._posedge_domain] += [self.dao.eq(dbuf), self.dbo.eq(self.di)] m.d[self._negedge_domain] += dbuf.eq(self.di) return m
def elaborate(self, platform): m = Module() x = Signal() tap = LFSR.TAPS[self.k] m.d.comb += x.eq(self.state[self.k - 1] ^ self.state[tap - 1]) with m.If(self.reset): m.d.sync += self.state.eq(1) with m.Else(): m.d.sync += Cat(self.state).eq(Cat(x, self.state)) return m
def elaborate(self, p: Platform) -> Module: m = Module() comb = m.d.comb iclk = m.d.i comb += self.rs1_out.eq(self.r[self.rs1_in]) comb += self.rs2_out.eq(self.r[self.rs2_in]) with m.If(self.rd != 0): iclk += self.r[self.rd].eq(self.rd_value) return m
def test_synth_realcase(): m = Module() m.submodules.axi2axil = axi2axil = Axi2AxiLite(32, 16, 5) m.submodules.xbar = xbar = AxiLiteXBar(32, 16) slaves = [DemoAxi(32, 16) for _ in range(5)] for i, s in enumerate(slaves): m.submodules['slave_' + str(i)] = s xbar.add_slave(s.axilite, 0x1000 * i, 0x1000) xbar.add_master(axi2axil.axilite) ports = list(axi2axil.axi.fields.values()) synth(m, ports)
def elaborate(self, _: Platform) -> Module: """Implements the logic for the ToPennies module.""" m = Module() m.d.comb += self.pennies_out.eq(self.pennies + 5 * self.nickels + 10 * self.dimes + 25 * self.quarters + 100 * self.dollars) return m
def elaborate(self, platform: Platform) -> Module: m = Module() def step(m: Module, last: Statement, index: int) -> Statement: parity = Signal(name=f"parity_{index}") m.d.comb += parity.eq(last ^ self.a[index]) return parity all_xored = self.elaborate_range(m, self.input_width, 0, step) m.d.comb += self.parity.eq(~all_xored) return m
def elaborate(self, _: Platform) -> Module: """Implements the logic of the trap sequencer ROM.""" m = Module() # Defaults m.d.comb += [ self.set_instr_complete.eq(0), self.save_trap_csrs.eq(0), self.csr_to_x.eq(0), self._next_instr_phase.eq(0), self.alu_op_to_z.eq(AluOp.NONE), self._mcause_to_csr_num.eq(0), self.enter_trap.eq(0), self.exit_trap.eq(0), self.clear_pend_mti.eq(0), self.clear_pend_mei.eq(0), self.x_mux_select.eq(SeqMuxSelect.X), self.y_mux_select.eq(SeqMuxSelect.Y), self.z_mux_select.eq(SeqMuxSelect.Z), self.pc_mux_select.eq(SeqMuxSelect.PC), self.memaddr_mux_select.eq(SeqMuxSelect.MEMADDR), self._const.eq(0), ] m.d.comb += [ self.load_trap.eq(0), self.next_trap.eq(0), self.load_exception.eq(0), self.next_exception.eq(0), self.next_fatal.eq(0), ] # 4 cases here: # # 1. It's a trap! # 2. It's not a trap, but PC is misaligned. # 3. It's not a trap, PC is aligned, but it's a bad instruction. # 4. None of the above (allow control by sequencer ROM). with m.If(self.trap): self.handle_trap(m) # True when pc[0:2] != 0 and ~trap. with m.Elif(self.instr_misalign): self.set_exception(m, ConstSelect.EXC_INSTR_ADDR_MISALIGN, mtval=SeqMuxSelect.PC) with m.Elif(self.bad_instr): self.set_exception(m, ConstSelect.EXC_ILLEGAL_INSTR, mtval=SeqMuxSelect.INSTR) return m
def elaborate(self, platform): m = Module() m.submodules.soc = self.soc # Connect up our UART. uart_io = platform.request("uart", 0) m.d.comb += [ uart_io.tx.eq(self.uart_pins.tx), self.uart_pins.rx.eq(uart_io.rx) ] return m
def formal(cls) -> Tuple[Module, List[Signal]]: """Formal verification for the ALU.""" m = Module() m.submodules.alu = alu = AluCard() with m.Switch(alu.alu_op): with m.Case(AluOp.ADD): m.d.comb += Assert(alu.data_z == (alu.data_x + alu.data_y)[:32]) with m.Case(AluOp.SUB): m.d.comb += [ Assert(alu.data_z == (alu.data_x - alu.data_y)[:32]), Assert(alu.alu_eq == (alu.data_x == alu.data_y)), Assert(alu.alu_ltu == (alu.data_x < alu.data_y)), Assert(alu.alu_lt == ( alu.data_x.as_signed() < alu.data_y.as_signed())), ] with m.Case(AluOp.AND): m.d.comb += Assert(alu.data_z == (alu.data_x & alu.data_y)) with m.Case(AluOp.AND_NOT): m.d.comb += Assert(alu.data_z == (alu.data_x & ~alu.data_y)) with m.Case(AluOp.OR): m.d.comb += Assert(alu.data_z == (alu.data_x | alu.data_y)) with m.Case(AluOp.XOR): m.d.comb += Assert(alu.data_z == (alu.data_x ^ alu.data_y)) with m.Case(AluOp.SLTU): with m.If(alu.data_x < alu.data_y): m.d.comb += Assert(alu.data_z == 1) with m.Else(): m.d.comb += Assert(alu.data_z == 0) with m.Case(AluOp.SLT): with m.If(alu.data_x.as_signed() < alu.data_y.as_signed()): m.d.comb += Assert(alu.data_z == 1) with m.Else(): m.d.comb += Assert(alu.data_z == 0) with m.Case(AluOp.X): m.d.comb += Assert(alu.data_z == alu.data_x) with m.Case(AluOp.Y): m.d.comb += Assert(alu.data_z == alu.data_y) with m.Default(): m.d.comb += Assert(alu.data_z == 0) return m, [alu.alu_op, alu.data_x, alu.data_y, alu.data_z]
def elaborate(self, platform): m = Module() # # Our module has three core parts: # - an encoder, which converts from our one-hot signal to a mux select line # - a multiplexer, which handles multiplexing e.g. payload signals # - a set of OR'ing logic, which joints together our simple or'd signals # Create our encoder... m.submodules.encoder = encoder = Encoder(len(self._inputs)) for index, interface in enumerate(self._inputs): # ... and tie its inputs to each of our 'valid' signals. valid_signal = getattr(interface, self._valid_field) m.d.comb += encoder.i[index].eq(valid_signal) # Create our multiplexer, and drive each of our output signals from it. with m.Switch(encoder.o): for index, interface in enumerate(self._inputs): # If an interface is selected... with m.Case(index): for identifier in self._mux_signals: # ... connect all of its muxed signals through to the output. output_signal = self._get_signal( self.output, identifier) input_signal = self._get_signal(interface, identifier) m.d.comb += output_signal.eq(input_signal) # Create the OR'ing logic for each of or or_signals. for identifier in self._or_signals: # Figure out the signals we want to work with... output_signal = self._get_signal(self.output, identifier) input_signals = (self._get_signal(i, identifier) for i in self._inputs) # ... and OR them together. or_reduced = functools.reduce(operator.__or__, input_signals, 0) m.d.comb += output_signal.eq(or_reduced) # Finally, pass each of our pass-back signals from the output interface # back to each of our input interfaces. for identifier in self._pass_signals: output_signal = self._get_signal(self.output, identifier) for interface in self._inputs: input_signal = self._get_signal(interface, identifier) m.d.comb += input_signal.eq(output_signal) return m
def test_h100_sync(): from nmigen.sim import Simulator, Delay bus = HighSpeedTransmitBus() m = Module() m.submodules.sync = sync = H100Sync() m.submodules.dut = dut = HighSpeedTransmit(bus=bus, sync=sync) frame_data_0 = [ord(c) for c in '0_TESTING_T1_DATA_STUFF\xff'] frame_data_1 = [ord(c) for c in '1_TESTING_T1_DATA_STUFF\x00'] frame_data_2 = [ord(c) for c in '2_TESTING_T1_DATA_STUFF\xff'] frame_data_3 = [ord(c) for c in '3_TESTING_T1_DATA_STUFF\x00'] def process_test(): yield Delay(100e-9) yield sync.enable.eq(1) yield dut.enable.eq(1) yield dut.data[0].eq(0xaa) yield dut.data[1].eq(0x55) yield dut.data[2].eq(0xff) yield dut.data[3].eq(0x00) for _ in range(2500): slot_t1 = yield sync.slot_t1 yield yield dut.data[0].eq(frame_data_0[slot_t1]) yield dut.data[1].eq(frame_data_1[slot_t1]) yield dut.data[2].eq(frame_data_2[slot_t1]) yield dut.data[3].eq(frame_data_3[slot_t1]) sim = Simulator(m) sim.add_clock(1.0 / 16.384e6) # sim.add_sync_process(process_inclk) sim.add_sync_process(process_test) traces = [ # sync.inclk, # sync.outclk, dut.enable, bus.ser.o, bus.ser.oe, bus.msync.o, bus.msync.oe, bus.sync.o, bus.sync.oe, ] with sim.write_vcd("test_h100_sync.vcd", "test_h100_sync.gtkw", traces=traces): sim.run()
def elaborate(self, platform): m = Module() m.d.comb += [ # Assume(self.left_in.i_valid == self.right_in.i_valid), self.stereo_out.o_valid.eq(self.left_in.i_valid), self.stereo_out.o_data.left.eq(self.left_in.i_data), self.stereo_out.o_data.right.eq(self.right_in.i_data), self.left_in.o_ready.eq(self.stereo_out.i_ready), self.right_in.o_ready.eq(self.stereo_out.i_ready), ] m.d.sync += [] return m
def elaborate(self, platform): m = Module() if self.own_register_window: m.submodules.reg_window = self.register_window # Add the registers that represent each of our signals. self.populate_ulpi_registers(m) # Generate logic to handle changes on each of our registers. first_element = True for address, signals in self._register_signals.items(): conditional = m.If if first_element else m.Elif first_element = False # If we're requesting a write on the given register, pass that to our # register window. with conditional(signals['write_requested']): # Keep track of when we'll be okay to start a write: # it's when there's a write request, we're not complete. # and the bus is idle. We'll use this below. request_write = \ signals['write_requested'] & \ ~self.register_window.done & \ self.bus_idle m.d.comb += [ # Control signals. signals['write_done'].eq(self.register_window.done), # Register window signals. self.register_window.address.eq(address), self.register_window.write_data.eq(signals['write_value']), self.register_window.write_request.eq(request_write), # Status signals self.busy.eq(request_write | self.register_window.busy) ] # If no register accesses are active, provide default signal values. with m.Else(): m.d.comb += [ self.register_window.write_request.eq(0), self.busy.eq(self.register_window.busy) ] # Ensure our register window is never performing a read. m.d.comb += self.register_window.read_request.eq(0) return m
def elaborate(self, platform: Platform) -> Module: m = Module() for ip_name in self._ips.keys(): args = getattr(self, ip_name) try: inst = Instance(ip_name, **args) setattr(m.submodules, ip_name, inst) except TypeError: error(f"couldn't create instance of {ip_name} " f"using args: {args}") return m
def formal(cls) -> Tuple[Module, List[Signal]]: """Formal verification for my module.""" m = Module() m.submodules.my_class = my_class = cls() # Make sure that the output is always the same as the input m.d.comb += Assert(my_class.my_input == my_class.my_output) # Cover the case where the output is 1. m.d.comb += Cover(my_class.my_output == 1) return m, [my_class.my_input]
def elaborate(self, platform): m = Module() m.submodules.bridge = self._bridge # Grab our LEDS... leds = Cat(platform.request("led", i) for i in range(6)) # ... and update them on each register write. with m.If(self._output.w_stb): m.d.sync += leds.eq(self._output.w_data) return m
def test_nested_record(self): m = Module() record = Record([ ('sig_in', 1, DIR_FANIN), ('sig_out', 1, DIR_FANOUT), ('nested', [ ('subsig_in', 1, DIR_FANIN), ('subsig_out', 1, DIR_FANOUT), ]) ]) synchronize(m, record)
def elaborate(self, platform): timer = Signal(23) m = Module() m.d.sync += timer.eq(timer + 1) if platform is not None: led = platform.request("led", 0) m.d.comb += led.o.eq(timer[-1]) return m
def elaborate(self, platform): m = Module() with m.If(self.data_in.received()): m.d.sync += [ self.data.eq(self.data_in.i_data), self.data_in.o_ready.eq(self.data[1]), ] with m.Else(): m.d.sync += [ self.data_in.o_ready.eq(True) ] return m
def elaborate(self, platform): m = Module() # Create our domains; but don't do anything else for them, for now. m.domains.usb = ClockDomain() m.domains.fast = ClockDomain() # Handle USB PHY resets. m.submodules.usb_reset = controller = PHYResetController() m.d.comb += [ResetSignal("usb").eq(controller.phy_reset)] return m
def setup(validator: Optional[Base]): result = CliSetup( Module(), Core(validator), ClockDomain("ph1"), ClockSignal("ph1"), ) result.m.submodules.core = result.core result.m.domains.ph1 = result.ph1 result.ph1.rst = result.core.Rst return result
def elaborate(self, platform): m = Module() N = self.M + 2 assert _is_power_of_2(N) # kernel_RAM = Memory(width=COEFF_WIDTH, depth=N, init=kernel) m.submodules.kr_port = kr_port = kernel_RAM.read_port() sample_RAM = Memory(width=self.sample_depth, depth=N, init=[0] * N) m.submodules.sw_port = sw_port = sample_RAM.write_port() m.submodules.sr_port = sr_port = sample_RAM.read_port() roto_sample_spec = PipeSpec( ( ('coeff', COEFF_SHAPE), ('sample', signed(sample_depth)), ), flags=START_STOP, ) class RotorFIFO(Elaboratable): def elaborate(self): m = Module() # when samples_in and fifo not full: insert sample. # when samples_readable and out pipe not full: # out pipe send {} # o_data.coeff = kernel[c_index], # o_data.sample = sample[...], # o_start=c_index == 1, # o_stop=c_index == ~0, # } # when c_index == ~0: # c_index = 1 # sr_index = start_index + R # start_index += R # else: # c_index += 1 # sr_index += 1 return m m.submodules.rfifo = RotorFifo() m.submodules.pipe = SimplePipeline.assemble( roto_sample_spec, LogicModule(lambda m, i, o: o.eq(i.coeff * i.sample)), PipeSpec(signed(COEFF_WIDTH + sample_depth)), LogicAndHandshakeModule( lambda m, i, o: { 'sync': acc.eq(Mux(i_start, i_data, acc + i_data)), 'comb': o.o_data.eq(acc[shift:]), }), PipeSpec(signed(sample_depth)), flags=START_STOP, ) return m