def test_cpu(sync_sim): m = nm.Module() reg = 2 cpu_inst = m.submodules.cpu = cpu.CPU(debug_reg=reg) link_reg = 5 program = [ encoding.IType.encode(1, reg, encoding.IntRegImmFunct.ADDI, reg, encoding.Opcode.OP_IMM), # jump back to the previous instruction for infinite loop encoding.JType.encode(0x1ffffc, link_reg) ] imem = nm.Memory(width=32, depth=1024, init=program) imem_rp = m.submodules.imem_rp = imem.read_port(domain="sync") m.d.comb += [ imem_rp.addr.eq(cpu_inst.imem_addr[2:]), cpu_inst.imem_data.eq(imem_rp.data), ] def testbench(): for _ in range(20): yield sync_sim(m, testbench)
def elaborate(self, platform): m = nm.Module() tx_div = nm.Signal(range(self.divider)) tx_reg = nm.Signal(self.n + 2, reset=1) tx_cnt = nm.Signal(range(self.n + 3)) m.d.comb += self.tx_o.eq(tx_reg[0]) with m.If(tx_cnt == 0): # Idle with m.If(self.valid): m.d.sync += [ tx_reg.eq(nm.Cat(0, self.data, 1)), tx_cnt.eq(self.n + 2), tx_div.eq(self.divider - 1), ] with m.Else(): # Transmitting with m.If(tx_div != 0): # Wait for clock divider m.d.sync += tx_div.eq(tx_div - 1) with m.Else(): # Update output state m.d.sync += [ tx_reg.eq(nm.Cat(tx_reg[1:], 1)), tx_cnt.eq(tx_cnt - 1), tx_div.eq(self.divider - 1), ] return m
def elaborate(self, platform): m = nm.Module() clk_freq = platform.default_clk_frequency speed = int(clk_freq // (1 << 4)) frame_counter = nm.Signal(range(speed), reset=speed - 1) stepctr = nm.Signal(4) step = nm.Signal(3) matrix = m.submodules.matrix = LEDMatrix(4, 8, clk_freq) with m.If(stepctr >= 8): m.d.comb += step.eq(7 - stepctr[0:3]) with m.Else(): m.d.comb += step.eq(stepctr) m.d.comb += [ matrix.columns[0].eq(1 << step), matrix.columns[1].eq(1 << step | 2 << step), matrix.columns[2].eq(~0 ^ 4 << step), matrix.columns[3].eq(~0 ^ (1 << step | 8 << step)), ] with m.If(frame_counter == 0): m.d.sync += [ stepctr.eq(stepctr + 1), frame_counter.eq(frame_counter.reset) ] with m.Else(): m.d.sync += [frame_counter.eq(frame_counter - 1)] return m
def elaborate(self, platform): m = nm.Module() # Use OSCG so we can still clock with PHYs in reset # (otherwise, the PHYs stop running the XO). m.domains.sync = cd_osc = nm.ClockDomain("sync") m.submodules.oscg = nm.Instance("OSCG", p_DIV=12, o_OSC=cd_osc.clk) # Hold PHYs in reset m.d.comb += platform.request("eth_common").rst.eq(1) # Hold SDRAM in WE to prevent it driving DQ and leave clock low. sdram = platform.request("sdram") m.d.comb += sdram.we.eq(1), sdram.clk.eq(0) # Flash LED led = platform.request("led") ctr = nm.Signal(22) m.d.sync += ctr.eq(ctr + 1) m.d.comb += led.o.eq(ctr[-1]) # UART on unknown outputs v = nm.Signal() p = nm.Signal() m.d.sync += p.eq(ctr[-4]), v.eq(p != ctr[-4]) for idx, pin in enumerate(platform.outputs): print(f"{idx:02X} {pin}") uart = UART(idx) m.submodules += uart pin = platform.request(pin) m.d.comb += pin.o.eq(uart.tx_o), uart.valid.eq(v) return m
def elaborate(self, _): m = nm.Module() registers = nm.Memory( width=self.register_width, depth=self.num_registers) rp1 = m.submodules.rp1 = registers.read_port(domain="comb") rp2 = m.submodules.rp2 = registers.read_port(domain="comb") debug_rp = m.submodules.debug_rp = registers.read_port(domain="comb") wp = m.submodules.wp = registers.write_port(domain="sync") # The first register, x0, has a special function: Reading it always # returns 0 and writes to it are ignored. # https://github.com/riscv/riscv-asm-manual/blob/master/riscv-asm.md m.d.comb += wp.en.eq( nm.Mux(self.write_select == 0, 0, self.write_enable)) m.d.comb += [ rp1.addr.eq(self.read_select_1), rp2.addr.eq(self.read_select_2), wp.addr.eq(self.write_select), debug_rp.addr.eq(self.debug_reg), self.read_data_1.eq(rp1.data), self.read_data_2.eq(rp2.data), wp.data.eq(self.write_data), self.debug_out.eq(debug_rp.data), ] return m
def elaborate(self, _): m = nm.Module() with m.Switch(self.op): with m.Case(ALUOp.ADD): m.d.comb += self.o.eq(self.a + self.b) with m.Case(ALUOp.SUB): m.d.comb += self.o.eq(self.a - self.b) return m
def test_jtype_same_offset_out_as_in(comb_sim, offset): m = nm.Module() jal = nm.Const(encoding.JType.encode(offset, 5), shape=32) extended_offset = int(f"{offset:021b}"[0] * 11 + f"{offset:021b}", 2) assert (extended_offset & 0x1ffffe) == offset def testbench(): assert (yield encoding.JType(jal).immediate()) == extended_offset comb_sim(m, testbench)
def elaborate(self, platform): m = nm.Module() cd_sync = nm.ClockDomain("sync") m.domains += cd_sync clk100 = platform.request("clk100") cd_fast = nm.ClockDomain("fast") m.domains += cd_fast m.d.comb += cd_fast.clk.eq(clk100.i) m.submodules.pll = nm.Instance("SB_PLL40_CORE", p_FEEDBACK_PATH="SIMPLE", p_DIVR=3, p_DIVF=40, p_DIVQ=6, p_FILTER_RANGE=2, i_RESETB=1, i_BYPASS=0, i_REFERENCECLK=clk100.i, o_PLLOUTCORE=cd_sync.clk) reg = 2 cpu_inst = m.submodules.cpu = cpu.CPU(debug_reg=reg) link_reg = 5 program = [ encoding.IType.encode(1, reg, encoding.IntRegImmFunct.ADDI, reg, encoding.Opcode.OP_IMM), # jump back to the previous instruction for infinite loop encoding.JType.encode(0x1ffffc, link_reg) ] imem = nm.Memory(width=32, depth=256, init=program) imem_rp = m.submodules.imem_rp = imem.read_port() m.d.comb += [ imem_rp.addr.eq(cpu_inst.imem_addr), cpu_inst.imem_data.eq(imem_rp.data), ] dmem = nm.Memory(width=32, depth=256) dmem_rp = m.submodules.dmem_rp = dmem.read_port(transparent=False, domain="fast") dmem_wp = m.submodules.dmem_wp = dmem.write_port(domain="fast") m.d.comb += [ dmem_rp.addr.eq(cpu_inst.dmem_r_addr), cpu_inst.dmem_r_data.eq(dmem_rp.data), dmem_wp.addr.eq(cpu_inst.dmem_w_addr), dmem_wp.data.eq(cpu_inst.dmem_w_data), ] colours = ["b", "g", "o", "r"] leds = nm.Cat(platform.request(f"led_{c}") for c in colours) m.d.sync += leds.eq(cpu_inst.debug_out[13:17]) return m
def test_itype_same_immediate_out_as_in(comb_sim, imm): m = nm.Module() addi = nm.Const(encoding.IType.encode(imm, 1, encoding.IntRegImmFunct.ADDI, 2, encoding.Opcode.OP_IMM), shape=32) extended_imm = int(f"{imm:012b}"[0] * 20 + f"{imm:012b}", 2) assert (extended_imm & 0x7ff) == imm def testbench(): assert (yield encoding.IType(addi).immediate()) == extended_imm comb_sim(m, testbench)
def elaborate(self, _): m = nm.Module() m.d.comb += self.pc_inc.eq(self.pc + INSTR_BYTES) m.d.sync += self.pc.eq(self.pc_next) with m.If(self.load): m.d.comb += self.pc_next.eq(self.input_address) with m.Else(): m.d.comb += self.pc_next.eq(self.pc_inc) return m
def elaborate(self, _): m = nm.Module() m.d.comb += self.dmem_r_addr.eq(self.byte_address[2:]) with m.Switch(self.address_mode): with m.Case(AddressMode.BYTE): m.d.comb += self.load_value.eq( self.dmem_r_data.word_select(self.byte_address[0:2], 8)) with m.Case(AddressMode.HALF): m.d.comb += self.load_value.eq( self.dmem_r_data.word_select(self.byte_address[1], 16)) with m.Case(AddressMode.WORD): m.d.comb += self.load_value.eq(self.dmem_r_data) return m
def elaborate(self, _): m = nm.Module() alu_inst = m.submodules.alu = alu.ALU(32) dmem = m.submodules.dmem = data_memory.DataMemory() idec = m.submodules.idec = instruction_decoder.InstructionDecoder() pc = m.submodules.pc = program_counter.ProgramCounter() rf = m.submodules.rf = register_file.RegisterFile( debug_reg=self.debug_reg) m.d.comb += [ rf.read_select_1.eq(idec.rf_read_select_1), rf.read_select_2.eq(idec.rf_read_select_2), rf.write_enable.eq(idec.rf_write_enable), rf.write_select.eq(idec.rf_write_select), alu_inst.a.eq(idec.alu_imm), alu_inst.op.eq(idec.alu_op), self.dmem_r_addr.eq(dmem.dmem_r_addr), dmem.byte_address.eq(alu_inst.o), dmem.signed.eq(idec.dmem_signed), dmem.address_mode.eq(idec.dmem_address_mode), dmem.dmem_r_data.eq(self.dmem_r_data), pc.load.eq(idec.pc_load), pc.input_address.eq(alu_inst.o), self.imem_addr.eq(pc.pc_next), idec.instr.eq(self.imem_data), self.debug_out.eq(rf.debug_out), ] with m.Switch(idec.rd_mux_op): with m.Case(instruction_decoder.RdValue.PC_INC): m.d.comb += rf.write_data.eq(pc.pc_inc) with m.Case(instruction_decoder.RdValue.ALU_OUTPUT): m.d.comb += rf.write_data.eq(alu_inst.o) with m.Case(instruction_decoder.RdValue.LOAD): m.d.comb += rf.write_data.eq(dmem.load_value) with m.Switch(idec.alu_mux_op): with m.Case(instruction_decoder.ALUInput.READ_DATA_1): m.d.comb += alu_inst.b.eq(rf.read_data_1) with m.Case(instruction_decoder.ALUInput.PC): m.d.comb += alu_inst.b.eq(pc.pc) return m
def elaborate(self, platform): m = nm.Module() matrix = platform.request("led_matrix", 0) cols = matrix.columns rows = matrix.rows row_idx = nm.Signal(range(len(rows))) m.d.comb += [ cols.eq(self.columns[row_idx]), rows.eq(1 << row_idx), ] with m.If(self.row_counter == 0): m.d.sync += [ self.row_counter.eq(self.row_counter.reset), row_idx.eq(row_idx + 1), ] with m.Else(): m.d.sync += [self.row_counter.eq(self.row_counter - 1)] return m
def elaborate(self, _): m = nm.Module() opcode = encoding.opcode(self.instr) m.d.comb += self.rf_write_select.eq(encoding.rd(self.instr)) m.d.comb += self.rf_read_select_1.eq(encoding.rs1(self.instr)) m.d.comb += self.rf_read_select_2.eq(encoding.rs2(self.instr)) with m.Switch(opcode): with m.Case(encoding.Opcode.OP_IMM): m.d.comb += self.rf_write_enable.eq(1) itype = encoding.IType(self.instr) with m.Switch(itype.funct()): with m.Case(encoding.IntRegImmFunct.ADDI): m.d.comb += [ self.pc_load.eq(0), self.alu_op.eq(alu.ALUOp.ADD), self.alu_imm.eq(itype.immediate()), self.rd_mux_op.eq(RdValue.ALU_OUTPUT), self.alu_mux_op.eq(ALUInput.READ_DATA_1), ] with m.Case(encoding.Opcode.JAL): m.d.comb += self.rf_write_enable.eq(1) jtype = encoding.JType(self.instr) m.d.comb += [ self.pc_load.eq(1), self.alu_op.eq(alu.ALUOp.ADD), self.alu_imm.eq(jtype.immediate()), self.rd_mux_op.eq(RdValue.PC_INC), self.alu_mux_op.eq(ALUInput.PC) ] return m
def elaborate(self, _): m = nm.Module() shamt_width = 5 with m.Switch(self.op): with m.Case(ALUOp.ADD): m.d.comb += self.o.eq(self.a + self.b) with m.Case(ALUOp.SUB): m.d.comb += self.o.eq(self.a - self.b) with m.Case(ALUOp.AND): m.d.comb += self.o.eq(self.a & self.b) with m.Case(ALUOp.OR): m.d.comb += self.o.eq(self.a | self.b) with m.Case(ALUOp.XOR): m.d.comb += self.o.eq(self.a ^ self.b) with m.Case(ALUOp.SLL): m.d.comb += self.o.eq(self.b << self.a[:shamt_width]) with m.Case(ALUOp.SRL): m.d.comb += self.o.eq(self.b >> self.a[:shamt_width]) with m.Case(ALUOp.SRA): m.d.comb += self.o.eq( self.b.as_signed() >> self.a[:shamt_width]) return m
def elaborate(self, platform): m = nm.Module() m.d.comb += self.output.eq(~self.input) return m
def elaborate(self, _): m = nm.Module() opcode = encoding.opcode(self.instr) m.d.comb += self.rf_write_select.eq(encoding.rd(self.instr)) m.d.comb += self.rf_read_select_1.eq(encoding.rs1(self.instr)) m.d.comb += self.rf_read_select_2.eq(encoding.rs2(self.instr)) with m.Switch(opcode): with m.Case(encoding.Opcode.OP_IMM): m.d.comb += self.rf_write_enable.eq(1) itype = encoding.IType(self.instr) with m.Switch(itype.funct()): m.d.comb += [ self.pc_load.eq(0), self.rd_mux_op.eq(RdValue.ALU_OUTPUT), self.alu_mux_op.eq(ALUInput.READ_DATA_1), ] with m.Case(encoding.IntRegImmFunct.ADDI): m.d.comb += [ self.alu_op.eq(alu.ALUOp.ADD), self.alu_imm.eq(itype.immediate()), ] with m.Case(encoding.IntRegImmFunct.XORI): m.d.comb += [ self.alu_op.eq(alu.ALUOp.XOR), self.alu_imm.eq(itype.immediate()), ] with m.Case(encoding.IntRegImmFunct.ORI): m.d.comb += [ self.alu_op.eq(alu.ALUOp.OR), self.alu_imm.eq(itype.immediate()), ] with m.Case(encoding.IntRegImmFunct.ORI): m.d.comb += [ self.alu_op.eq(alu.ALUOp.OR), self.alu_imm.eq(itype.immediate()), ] with m.Case(encoding.IntRegImmFunct.ANDI): m.d.comb += [ self.alu_op.eq(alu.ALUOp.AND), self.alu_imm.eq(itype.immediate()), ] with m.Case(encoding.IntRegImmFunct.SLLI): m.d.comb += [ self.alu_op.eq(alu.ALUOp.SLL), self.alu_imm.eq(itype.shift_amount()), ] with m.Case(encoding.IntRegImmFunct.SRLI_OR_SRAI): m.d.comb += self.alu_imm.eq(itype.shift_amount()) with m.Switch(itype.right_shift_type()): with m.Case(encoding.RightShiftType.SRLI): m.d.comb += self.alu_op.eq(alu.ALUOp.SRL) with m.Case(encoding.RightShiftType.SRAI): m.d.comb += self.alu_op.eq(alu.ALUOp.SRA) with m.Case(encoding.Opcode.JAL): m.d.comb += self.rf_write_enable.eq(1) jtype = encoding.JType(self.instr) m.d.comb += [ self.pc_load.eq(1), self.alu_op.eq(alu.ALUOp.ADD), self.alu_imm.eq(jtype.immediate()), self.rd_mux_op.eq(RdValue.PC_INC), self.alu_mux_op.eq(ALUInput.PC), ] with m.Case(encoding.Opcode.LOAD): m.d.comb += [ self.rf_write_enable.eq(1), self.pc_load.eq(0), self.alu_op.eq(alu.ALUOp.ADD), self.alu_imm.eq(itype.immediate()), self.rd_mux_op.eq(RdValue.LOAD), self.alu_mux_op.eq(ALUInput.READ_DATA_1), ] itype = encoding.IType(self.instr) funct = itype.funct() with m.If(funct == encoding.LoadFunct.LW): m.d.comb += self.dmem_address_mode.eq( data_memory.AddressMode.WORD) with m.Elif((funct == encoding.LoadFunct.LH) | (funct == encoding.LoadFunct.LHU)): m.d.comb += self.dmem_address_mode.eq( data_memory.AddressMode.HALF) with m.Elif((funct == encoding.LoadFunct.LB) | (funct == encoding.LoadFunct.LBU)): m.d.comb += self.dmem_address_mode.eq( data_memory.AddressMode.BYTE) m.d.comb += self.dmem_signed.eq(funct[2] == 0) return m