def __init__(self, size=32, bus=None, debug_bus=None): self.irq = Signal() if bus is None: self.bus = wb.Interface(data_width=32, adr_width=32) else: self.bus = bus if debug_bus is None: self.debug_bus = wb.Interface(data_width=32, adr_width=32) else: self.debug_bus = debug_bus # TODO ignore high bits instead of clipping actual value mem = Array(Signal(32, reset_less=True) for _ in range(size)) # Main bus (read-only port) self.sync += [ self.bus.ack.eq(0), self.bus.err.eq(0), self.bus.dat_r.eq(mem[(self.bus.adr >> 2)]), If(self.bus.stb & self.bus.cyc & ~self.bus.ack, self.bus.ack.eq(1)) ] # Debug bus (read/write port) self.sync += [ self.debug_bus.ack.eq(0), self.debug_bus.err.eq(0), self.debug_bus.dat_r.eq(mem[(self.debug_bus.adr >> 2)]), If( self.debug_bus.stb & self.debug_bus.cyc & ~self.debug_bus.ack, self.debug_bus.ack.eq(1), If( self.debug_bus.we & self.debug_bus.sel[0], mem[(self.debug_bus.adr >> 2)][0:8].eq( self.debug_bus.dat_w[0:8])), If( self.debug_bus.we & self.debug_bus.sel[1], mem[(self.debug_bus.adr >> 2)][8:16].eq( self.debug_bus.dat_w[8:16])), If( self.debug_bus.we & self.debug_bus.sel[2], mem[(self.debug_bus.adr >> 2)][16:24].eq( self.debug_bus.dat_w[16:24])), If( self.debug_bus.we & self.debug_bus.sel[3], mem[(self.debug_bus.adr >> 2)][24:32].eq( self.debug_bus.dat_w[24:32])), ) ]
def __init__(self, data, bus=None, nullterm=True, endianness="little"): if bus is None: bus = wb.Interface(data_width=32, adr_width=32) self.bus = bus num_bytes = bus.data_width // 8 data = list(data) for i in range(len(data)): if isinstance(data[i], str): data[i] = ord(data[i]) data[i] = int(data[i]) if nullterm: data = data + [0] # Add padding data = data + [0] * ((num_bytes - (len(data) % num_bytes)) % num_bytes) assert len(data) % num_bytes == 0 # Group into words data = [data[i:i + num_bytes] for i in range(0, len(data), num_bytes)] assert all([len(x) == num_bytes for x in data]) # Pack words data = [pack_list(x, endianness=endianness) for x in data] self.sync += [ self.bus.ack.eq(self.bus.cyc & self.bus.stb & ~self.bus.ack), self.bus.dat_r.eq(Array(data)[self.bus.adr >> 2]) ]
def __init__(self, pads, fifo_depth=4, bus=None): self.uart_tx = pads.tx self.uart_rx = pads.rx if bus is None: self.bus = wb.Interface(data_width=32, adr_width=32) else: self.bus = bus addr_spacing = self.bus.dat_r.nbits // 8 self.specials += Instance("wbuart", o_o_tx=self.uart_tx, i_i_rx=self.uart_rx, i_i_wb_cyc=self.bus.cyc, i_i_wb_stb=self.bus.stb, i_i_wb_we=self.bus.we & self.bus.sel[0], i_i_wb_addr=self.bus.adr, i_i_wb_data=self.bus.dat_w, o_o_wb_ack=self.bus.ack, o_o_wb_err=self.bus.err, o_o_wb_data=self.bus.dat_r, i_i_clk=ClockSignal(), i_i_rst=ResetSignal(), p_FIFO_DEPTH=fifo_depth, p_ADDR_STATUS=0 * addr_spacing, p_ADDR_CONFIG=1 * addr_spacing, p_ADDR_WRITE=2 * addr_spacing, p_ADDR_READ=3 * addr_spacing)
def __init__(self, bus=None, reset_less=False): if bus is None: self.bus = wb.Interface(data_width=32, adr_width=32) else: self.bus = bus if reset_less: ctr = Signal(bits_sign=64, reset_less=True) else: ctr = Signal(bits_sign=64, reset=0) # Reads are not guaranteed to be atomic # Read-procedure: # - Read high word # - Read low word # - Re-read high word # - If high word has changed, re-read low word # Because the low word will only roll over after 4B clock cycles, # it is safe to read in this manner (with the last condition catching any rollovers) self.sync += [ self.bus.ack.eq(0), self.bus.err.eq(0), self.bus.dat_r.eq(0), If(self.bus.stb & self.bus.cyc & ~self.bus.ack, self.bus.ack.eq(1), If((self.bus.adr >> 2) == 0, self.bus.dat_r.eq(ctr[0:32])), If((self.bus.adr >> 2) == 1, self.bus.dat_r.eq(ctr[32:64]))) ] self.sync += ctr.eq(ctr + 1)
def __init__(self): self.instr_bus = wb.Interface(data_width=32, adr_width=32) self.data_bus = wb.Interface(data_width=32, adr_width=32) self.stall_in = Signal() self.stall_out = Signal() self.init_pc = Signal(32) self.pc_out = Signal(32) self.cpu_reset = Signal(reset=0) self.specials += Instance("cpu", o_instr_wb_cyc=self.instr_bus.cyc, o_instr_wb_stb=self.instr_bus.stb, o_instr_wb_we=self.instr_bus.we, o_instr_wb_sel=self.instr_bus.sel, o_instr_wb_addr=self.instr_bus.adr, o_instr_wb_data_wr=self.instr_bus.dat_w, i_instr_wb_ack=self.instr_bus.ack, i_instr_wb_err=self.instr_bus.err, i_instr_wb_data_rd=self.instr_bus.dat_r, o_data_wb_cyc=self.data_bus.cyc, o_data_wb_stb=self.data_bus.stb, o_data_wb_we=self.data_bus.we, o_data_wb_sel=self.data_bus.sel, o_data_wb_addr=self.data_bus.adr, o_data_wb_data_wr=self.data_bus.dat_w, i_data_wb_ack=self.data_bus.ack, i_data_wb_err=self.data_bus.err, i_data_wb_data_rd=self.data_bus.dat_r, i_i_stall_in=self.stall_in, i_i_init_pc=self.init_pc, o_o_stall_out=self.stall_out, o_o_pc_out=self.pc_out, i_i_clk=ClockSignal(), i_i_rst=ResetSignal() | self.cpu_reset, p_USE_BARREL_SHIFTER=True, p_WISHBONE_PIPELINED=0)
def __init__(self, controllers, peripherals, register=False): check_fns, periph_busses = zip(*peripherals) # TODO allow selectively blocking specific points in crossbar cross_points = [[ wb.Interface(data_width=32, adr_width=32) for j in peripherals ] for i in controllers] for row, controller in zip(cross_points, controllers): self.submodules += wb.Decoder(controller, list(zip(check_fns, row)), register=register) for col, bus in zip(zip(*cross_points), periph_busses): self.submodules += wb.Arbiter(col, bus)
def __init__(self, pads, fifo_depth=4, bus=None): # Check if power of 2 fifo_addr_width = int(math.log2(fifo_depth)) if 2**(fifo_addr_width) != fifo_depth: raise ValueError("Invalid FIFO depth, must be a power of 2") if bus is None: self.bus = wb.Interface(data_width=32, adr_width=32) else: self.bus = bus addr_spacing = self.bus.dat_r.nbits // 8 print(addr_spacing) DEFAULT_PRESCALE = 32 # 400kHz @ 50Mhz last_stb = Signal() last_ack = Signal() self.sync += [last_stb.eq(self.bus.stb), last_ack.eq(self.bus.ack)] self.specials += Instance( "i2c_master_wbs_16", i_i2c_scl_i=pads.scl_i, o_i2c_scl_o=pads.scl_o, o_i2c_scl_t=pads.scl_oen, i_i2c_sda_i=pads.sda_i, o_i2c_sda_o=pads.sda_o, o_i2c_sda_t=pads.sda_oen, i_wbs_adr_i=self.bus.adr >> 1, i_wbs_dat_i=self.bus.dat_w, o_wbs_dat_o=self.bus.dat_r, i_wbs_we_i=self.bus.we & (self.bus.sel[1] | self.bus.sel[0]), i_wbs_sel_i=self.bus.sel, # Classic -> Pipelined i_wbs_stb_i=self.bus.stb & (~last_stb | last_ack), o_wbs_ack_o=self.bus.ack, i_wbs_cyc_i=self.bus.cyc, i_clk=ClockSignal(), i_rst=ResetSignal(), p_DEFAULT_PRESCALE=32, # 400kHz @ 50Mhz p_FIXED_PRESCALE=0, p_CMD_FIFO=1, p_CMD_FIFO_ADDR_WIDTH=fifo_addr_width, p_WRITE_FIFO=1, p_WRITE_FIFO_ADDR_WIDTH=fifo_addr_width, p_READ_FIFO=1, p_READ_FIFO_ADDR_WIDTH=fifo_addr_width)
def __init__(self, uart, clk_freq, baud=115200, drop_clks=None, fifo_depth=16): if drop_clks is None: # Default to 1s timeout drop_clks = clk_freq // 1 self.uart_tx = uart.tx self.uart_rx = uart.rx self.bus = wb.Interface(data_width=32, adr_width=32) self.ctr = Signal(16) last_stb = Signal() self.sync += [ last_stb.eq(self.bus.stb), If(self.bus.cyc & self.bus.stb, If(~last_stb, self.ctr.eq(0)).Else(self.ctr.eq(self.ctr + 1))) ] self.sync += [ self.bus.sel.eq(Constant(0b1111)), ] self.specials += Instance("wbdbgbus", o_o_tx=self.uart_tx, i_i_rx=self.uart_rx, o_o_wb_cyc=self.bus.cyc, o_o_wb_stb=self.bus.stb, o_o_wb_we=self.bus.we, o_o_wb_addr=self.bus.adr, o_o_wb_data=self.bus.dat_w, i_i_wb_ack=self.bus.ack, i_i_wb_err=self.bus.err, i_i_wb_stall=0, i_i_wb_data=self.bus.dat_r, i_i_interrupt_1=0, i_i_interrupt_2=0, i_i_interrupt_3=0, i_i_interrupt_4=0, i_i_clk=ClockSignal(), p_CLK_FREQ=clk_freq, p_UART_BAUD=baud, p_DROP_CLKS=drop_clks, p_FIFO_DEPTH=fifo_depth)
def __init__(self, pads, bus=None): if bus is None: self.bus = wb.Interface(data_width=32, adr_width=32) else: self.bus = bus self.comb += [ self.bus.cyc.eq(pads.cyc), self.bus.stb.eq(pads.stb), self.bus.adr.eq(pads.addr), self.bus.dat_w.eq(pads.data_wr), pads.data_rd.eq(self.bus.dat_r), self.bus.sel.eq(pads.sel), self.bus.we.eq(pads.we), pads.ack.eq(self.bus.ack), pads.err.eq(self.bus.err), ]
def __init__(self, platform, debug_controller=None, wishbone_delay_register=True): self.submodules.crg = SimpleCRG(platform.request("sys_clk"), platform.request("sys_rst")) self.controllers = {} self.mem_bus = {} self.periph_bus = {} if debug_controller is None: debug_controller = wb.Interface(data_width=32, adr_width=32) self.debug_controller = debug_controller self.debug_bus = {} self.wishbone_delay_register = wishbone_delay_register
def __init__(self, pads, bus=None): if bus is None: self.bus = wb.Interface(data_width=32, adr_width=32) else: self.bus = bus self.enable = Signal(reset=1) self.comb += [ pads.cyc.eq(self.enable & self.bus.cyc), pads.stb.eq(self.enable & self.bus.stb), pads.addr.eq(self.bus.adr), pads.data_wr.eq(self.bus.dat_w), self.bus.dat_r.eq(pads.data_rd), pads.sel.eq(self.bus.sel), pads.we.eq(self.bus.we), self.bus.ack.eq(self.enable & pads.ack), self.bus.err.eq(self.enable & pads.err) ]
def __init__(self, bus=None, debug_bus=None, enable_code=0xABAB12): if bus is None: self.bus = wb.Interface(data_width=32, adr_width=32) else: self.bus = bus if debug_bus is None: self.debug_bus = wb.Interface(data_width=32, adr_width=32) else: self.debug_bus = debug_bus wb_rd_req = self.bus.cyc & self.bus.stb & ~self.bus.ack & ~self.bus.we wb_wr_req = self.bus.cyc & self.bus.stb & ~self.bus.ack & self.bus.we wb_rd_data = Signal(32) self.comb += self.bus.dat_r.eq(wb_rd_data) enable_entry = Signal(32, reset=0) enabled = enable_entry == Constant(enable_code) # 00 = Cfg/Status {22'b0, err, ack, sel[3:0], 2'b0, rd_req, wr_req} # 04 = Addr # 08 = Write Data # 0C = Read Data # 10 = Enable self.sync += [ self.bus.ack.eq(0), self.bus.err.eq(0), self.debug_bus.ack.eq(0), self.debug_bus.err.eq(0), self.debug_bus.dat_r.eq(0), If(self.debug_bus.stb & self.debug_bus.cyc & ~self.debug_bus.ack, self.debug_bus.ack.eq(1), If((self.debug_bus.adr >> 2) == 0, If(enabled & self.debug_bus.we & self.debug_bus.sel[1], If(self.debug_bus.dat_w[8], self.bus.ack.eq(1)). Elif(self.debug_bus.dat_w[9], self.bus.err.eq(1))), self.debug_bus.dat_r.eq(Cat(wb_wr_req, wb_rd_req, Constant(0, bits_sign=2), self.bus.sel))), If((self.debug_bus.adr >> 2) == 1, self.debug_bus.dat_r.eq(self.bus.adr)), If((self.debug_bus.adr >> 2) == 2, self.debug_bus.dat_r.eq(self.bus.dat_w)), If((self.debug_bus.adr >> 2) == 3, If(self.debug_bus.we & self.debug_bus.sel[0], wb_rd_data[0:8].eq(self.debug_bus.dat_w[0:8])), If(self.debug_bus.we & self.debug_bus.sel[1], wb_rd_data[8:16].eq(self.debug_bus.dat_w[8:16])), If(self.debug_bus.we & self.debug_bus.sel[2], wb_rd_data[16:24].eq(self.debug_bus.dat_w[16:24])), If(self.debug_bus.we & self.debug_bus.sel[3], wb_rd_data[24:32].eq(self.debug_bus.dat_w[24:32])), self.debug_bus.dat_r.eq(wb_rd_data)), If((self.debug_bus.adr >> 2) == 4, If(self.debug_bus.we & self.debug_bus.sel[0], enable_entry[0:8].eq(self.debug_bus.dat_w[0:8])), If(self.debug_bus.we & self.debug_bus.sel[1], enable_entry[8:16].eq(self.debug_bus.dat_w[8:16])), If(self.debug_bus.we & self.debug_bus.sel[2], enable_entry[16:24].eq(self.debug_bus.dat_w[16:24])), If(self.debug_bus.we & self.debug_bus.sel[3], enable_entry[24:32].eq(self.debug_bus.dat_w[24:32])), self.debug_bus.dat_r.eq(enable_entry)), ) ]
def __init__(self, bus=None): self.irq = Signal() if bus is None: self.bus = wb.Interface(data_width=32, adr_width=32) else: self.bus = bus ctr = Signal(bits_sign=32, reset=0) # When enabled, runs for `load` cycles, then repeatedly reloads to `reload` cycles # (Unless reload is zero) running = Signal(reset=0) triggered = Signal(reset=0) reload = Signal(bits_sign=32) load = Signal(bits_sign=32) # Address space: # 00 = ctr # 04 = reload # 08 = load # 0C = enable # 10 = triggered self.sync += [ self.irq.eq(0), If( running, ctr.eq(ctr - 1), If((ctr == 1) | (ctr == 0), triggered.eq(1), self.irq.eq(1), If(reload != 0, ctr.eq(reload)).Else(ctr.eq(0)))).Else( ctr.eq(0), triggered.eq(0)), self.bus.ack.eq(0), self.bus.err.eq(0), self.bus.dat_r.eq(0), If( self.bus.stb & self.bus.cyc & ~self.bus.ack, self.bus.ack.eq(1), If((self.bus.adr >> 2) == 0, self.bus.dat_r.eq(ctr)), If((self.bus.adr >> 2) == 1, If(self.bus.we & self.bus.sel[0], reload[0:8].eq(self.bus.dat_w[0:8])), If(self.bus.we & self.bus.sel[1], reload[8:16].eq(self.bus.dat_w[8:16])), If(self.bus.we & self.bus.sel[2], reload[16:24].eq(self.bus.dat_w[16:24])), If(self.bus.we & self.bus.sel[3], reload[24:32].eq(self.bus.dat_w[24:32])), self.bus.dat_r.eq(reload)), If((self.bus.adr >> 2) == 2, If(self.bus.we & self.bus.sel[0], load[0:8].eq(self.bus.dat_w[0:8])), If(self.bus.we & self.bus.sel[1], load[8:16].eq(self.bus.dat_w[8:16])), If(self.bus.we & self.bus.sel[2], load[16:24].eq(self.bus.dat_w[16:24])), If(self.bus.we & self.bus.sel[3], load[24:32].eq(self.bus.dat_w[24:32])), self.bus.dat_r.eq(load)), If((self.bus.adr >> 2) == 3, If(self.bus.we & self.bus.sel[0], running.eq(self.bus.dat_w[0]), If(self.bus.dat_w[0], ctr.eq(load))), self.bus.dat_r.eq(running)), If((self.bus.adr >> 2) == 4, If(self.bus.we & self.bus.sel[0] & self.bus.dat_w[0] == 0, triggered.eq(0)), self.bus.dat_r.eq(triggered)), ) ]
def generate_bus(self): if len(self.mem_bus) + len(self.periph_bus) < 1: raise ValueError( "Must have at least one peripheral or memory in order to generate bus" ) if len(self.debug_bus) < 1: raise ValueError( "Must have at least one debug peripheral in order to generate bus" ) if len(self.controllers) < 1: raise ValueError( "Must have at least one controller in order to generate bus") cpu_address_map = [ ] # (addr, name) or (addr, name, [(addr, name), ...]) - all addresses are absolute debug_address_map = [] if len(self.periph_bus) != 0: periph_addr_base, periph_addr_top = self.wb_address("periphs")[0:2] periph_address_map = [] peripherals = [] for name, periph in self.periph_bus.items(): controller_bus = wb.Interface(data_width=32, adr_width=32) periph_bus = periph[1] base_addr, top_addr, size, translate_fn, c_type, c_type_top = self.wb_address( name) assert base_addr >= periph_addr_base and base_addr <= periph_addr_top assert top_addr >= periph_addr_base and top_addr <= periph_addr_top if translate_fn is None: translate_fn = create_translate_fn(base_addr - 0, size) check_fn = create_check_fn(base_addr - 0, top_addr - 0) translator = WishboneAddressTranslator(controller_bus, periph_bus, translate_fn) setattr(self.submodules, name + "__translator", translator) peripherals.append((check_fn, controller_bus)) periph_address_map.append((base_addr, name)) cpu_address_map.append( (periph_addr_base, "Peripherals", periph_address_map)) shared = wb.Interface(data_width=32, adr_width=32) periph_bridge = wb.Decoder(shared, peripherals, register=True) self.add_mem(periph_bridge, "periphs", bus=shared) assert len(self.mem_bus) >= 1 controllers = [x[1] for x in self.controllers.values()] mems = [] for name, periph in self.mem_bus.items(): controller_bus = wb.Interface(data_width=32, adr_width=32) periph_bus = periph[1] base_addr, top_addr, size, translate_fn, c_type, c_type_top = self.wb_address( name) if translate_fn is None: if name == "periphs": translate_fn = lambda x: x else: translate_fn = create_translate_fn(base_addr, size) check_fn = create_check_fn(base_addr, top_addr) translator = WishboneAddressTranslator(controller_bus, periph_bus, translate_fn) setattr(self.submodules, name + "__translator", translator) if name not in ["periphs"]: cpu_address_map.append((base_addr, name)) mems.append((check_fn, controller_bus)) self.submodules.crossbar = WishboneCrossbar( controllers, mems, register=self.wishbone_delay_register) debug_address_map = [] debug_peripherals = [] for name, periph in self.debug_bus.items(): controller_bus = wb.Interface(data_width=32, adr_width=32) periph_bus = periph[1] base_addr, top_addr, size, translate_fn = self.debug_address(name) if translate_fn is None: translate_fn = create_translate_fn(base_addr, size) check_fn = create_check_fn(base_addr, top_addr) translator = WishboneAddressTranslator(controller_bus, periph_bus, translate_fn) setattr(self.submodules, name + "__translator", translator) debug_peripherals.append((check_fn, controller_bus)) debug_address_map.append((base_addr, name)) self.submodules.debug_interconnect = wb.Decoder(self.debug_controller, debug_peripherals, register=True) return cpu_address_map, debug_address_map
def __init__(self, platform): debug_bus = wb.Interface(data_width=32, adr_width=32) CLK = int(25e6) super().__init__( platform, debug_controller=debug_bus, wishbone_delay_register=False ) spi0_pads = make_pads_obj({ "mosi": Signal(1), "miso": Signal(1), "clk": Signal(1), }) spi1_pads = make_pads_obj({ "mosi": Signal(1), "miso": Signal(1), "clk": Signal(1), }) uart0_pads = make_pads_obj({ "rx": Signal(1), "tx": Signal(1), }) uart1_pads = make_pads_obj({ "rx": Signal(1), "tx": Signal(1), }) i2c0_pads = make_pads_obj({ "sda_i": Signal(1), "sda_o": Signal(1), "sda_oen": Signal(1), "scl_i": Signal(1), "scl_o": Signal(1), "scl_oen": Signal(1), }) pwm0_pad = Signal(1) pwm1_pad = Signal(1) pwm2_pad = Signal(1) pwm3_pad = Signal(1) pwm4_pad = Signal(1) pwm5_pad = Signal(1) # IO control setup # Input-only = (input_wire, Signal(), Constant(0)) # Output-only = (Signal(), output_wire, Constant(1)) io_in = lambda a, b, c: (a, b, c, Signal(), Constant(0)) io_out = lambda a, b, c: (a, b, Signal(), c, Constant(1)) UART_IO_IND = 1 UART_RX_PORT = 0 UART_TX_PORT = 1 LED_PORT = 13 io_config = [ { "index": 0, "name": "GPIO0 / RX0", "mode": "standard", "sync": True, "options": [ io_in(UART_IO_IND, "uart", uart0_pads.rx), ], }, { "index": 1, "name": "GPIO1 / TX0", "mode": "standard", "sync": True, "options": [ io_out(UART_IO_IND, "uart", uart0_pads.tx), ], }, { "index": 2, "name": "GPIO2 / RX1", "mode": "standard", "sync": True, "options": [ io_in(UART_IO_IND, "uart", uart1_pads.rx), ], }, { "index": 3, "name": "GPIO3 / TX1", "mode": "standard", "sync": True, "options": [ io_out(UART_IO_IND, "uart", uart1_pads.tx), ], }, { "index": 4, "name": "GPIO4 / PWM0", "mode": "standard", "sync": True, "options": [ io_out(1, "pwm", pwm0_pad), ], }, { "index": 5, "name": "GPIO5 / PWM1", "mode": "standard", "sync": True, "options": [ io_out(1, "pwm", pwm1_pad), ], }, { "index": 6, "name": "GPIO6 / PWM2", "mode": "standard", "sync": True, "options": [ io_out(1, "pwm", pwm2_pad), ], }, { "index": 7, "name": "GPIO7 / PWM3", "mode": "standard", "sync": True, "options": [ io_out(1, "pwm", pwm3_pad), ], }, { "index": 8, "name": "GPIO8 / PWM4", "mode": "standard", "sync": True, "options": [ io_out(1, "pwm", pwm4_pad), ], }, { "index": 9, "name": "GPIO9 / PWM5", "mode": "standard", "sync": True, "options": [ io_out(1, "pwm", pwm5_pad), ], }, { "index": 10, "name": "GPIO10", "mode": "standard", "sync": True, "options": [], }, { "index": 11, "name": "GPIO11 / SPI0-MOSI", "mode": "standard", "sync": True, "options": [ io_out(1, "spi", spi0_pads.mosi), ], }, { "index": 12, "name": "GPIO12 / SPI0-MISO", "mode": "standard", "sync": True, "options": [ io_in(1, "spi", spi0_pads.miso), ], }, { "index": 13, "name": "GPIO13 / SPI0-SCK", "mode": "standard", "sync": True, "options": [ io_out(1, "spi", spi0_pads.clk), ], }, { "index": 14, "name": "GPIO14 / SPI1-MOSI", "mode": "standard", "sync": True, "options": [ io_out(1, "spi", spi1_pads.mosi), ], }, { "index": 15, "name": "GPIO15 / SPI1-MISO", "mode": "standard", "sync": True, "options": [ io_in(1, "spi", spi1_pads.miso), ], }, { "index": 16, "name": "GPIO16 / SPI0-SCK", "mode": "standard", "sync": True, "options": [ io_out(1, "spi", spi1_pads.clk), ], }, { "index": 17, "name": "GPIO17", "mode": "standard", "sync": True, "options": [], }, # I2C is open-collector, only output-enable when low { "index": 18, "name": "GPIO18 / I2C0-SDA", "mode": "standard", "sync": True, "options": [ (1, "i2c", i2c0_pads.sda_i, Constant(0), i2c0_pads.sda_o == 0), ], }, { "index": 19, "name": "GPIO19 / I2C0-SCL", "mode": "standard", "sync": True, "options": [ (1, "i2c", i2c0_pads.scl_i, Constant(0), i2c0_pads.scl_o == 0), ], }, ] assert len(io_config) == NUM_IO """I/O controller setup""" io_pins = {"io{}".format(i): platform.request("io{}".format(i)) for i in range(NUM_IO)} self.add_periph(IOControl(io_pins, io_config), "ioctrl") self.add_debug_periph(None, "ioctrl_debug", bus=self.ioctrl.debug_bus) """I/O peripherals""" self.add_periph(spi.SPI(spi0_pads), "spi0") self.add_periph(spi.SPI(spi1_pads), "spi1") self.add_periph(uart.UART(uart0_pads, fifo_depth=8), "uart0") self.add_periph(uart.UART(uart1_pads, fifo_depth=8), "uart1") self.add_periph(i2c.I2C(i2c0_pads, fifo_depth=8), "i2c0") self.add_periph(pwm.PWM(pwm0_pad), "pwm0") self.add_periph(pwm.PWM(pwm1_pad), "pwm1") self.add_periph(pwm.PWM(pwm2_pad), "pwm2") self.add_periph(pwm.PWM(pwm3_pad), "pwm3") self.add_periph(pwm.PWM(pwm4_pad), "pwm4") self.add_periph(pwm.PWM(pwm5_pad), "pwm5") """External memories""" # Disabled in this build - can be added as needed # Cached bus is read-only (designed to be used as an instruction-cache) # Uncached is read-write #self.submodules.ram = RAMSubsystem(platform.request("hyperram"), platform.request("cache_mem")) #self.add_mem(None, "hyperram0", bus=self.ram.bus_cached) #self.add_mem(None, "hyperram1", bus=self.ram.bus_uncached) """Internal memories""" self.add_periph(ROM(bootrom( ioctrl_addr = wb_address_map["ioctrl"][0], uptime_timer_addr = wb_address_map["uptime"][0], uart_addr = wb_address_map["uart0"][0], uart_io_ind = UART_IO_IND, rx_port = UART_RX_PORT, tx_port = UART_TX_PORT, led_port = LED_PORT, imem_base = wb_address_map["imem"][0], dmem_base = wb_address_map["dmem"][0], clk = CLK ), nullterm=False, endianness="little"), "bootrom") self.add_mem(wb.SRAM(IMEM_SIZE, bus=wb.Interface(data_width=32, adr_width=32)), "imem") self.add_mem(wb.SRAM(DMEM_SIZE, bus=wb.Interface(data_width=32, adr_width=32)), "dmem") """Misc non-I/O peripherals""" self.add_periph(ROM(IDENT), "ident") self.add_periph(timer.UptimeTimer(), "uptime") self.add_periph(timer.Timer(), "timer0") self.add_periph(timer.Timer(), "timer1") #self.add_periph(timer.Timer(), "timer2") #self.add_periph(timer.Timer(), "timer3") """Debug-related peripherals""" # Debug region is not necessary in final builds - it is primarily intended for inspecting and debugging CPU internals when the main system bus is congested or blocked #self.add_controller(wishbone_bridge.WishboneBridge(), "wb_bridge") #self.add_debug_periph(None, "wb_bridge_debug", bus=self.wb_bridge.debug_bus) #self.add_debug_periph(debug_probe.DebugProbe(probe_width=64, output_width=64), "debug_probe_debug") #self.add_controller(wishbone_debug_bus.WishboneDebugBus(platform.request("uart_debug_bus"), CLK, baud=115200), "wbdbgbus_debug") """External debug utilities""" self.add_controller(wishbone_debug_bus.WishboneDebugBus(platform.request("uart_main_dbg"), CLK, baud=115200), "wbdbgbus_main") """CPU Instantiation""" self.submodules.cpu = CPUWrapper() self.add_controller(None, "cpu_ibus", bus=self.cpu.instr_bus) self.add_controller(None, "cpu_dbus", bus=self.cpu.data_bus) # Fixed init PC self.comb += self.cpu.init_pc.eq(self.wb_address("bootrom")[0]) # Only needed for debugging the CPU and busses on hardware #self.comb += self.cpu.stall_in.eq(self.debug_probe_debug.stall_out) #self.comb += self.debug_probe_debug.stall_in.eq(self.cpu.stall_out) #self.comb += self.cpu.cpu_reset.eq(self.debug_probe_debug.reset_out) #self.comb += self.debug_probe_debug.probe.eq(self.cpu.pc_out) self.comb += self.cpu.cpu_reset.eq(0) """Generate the bus""" main_mem_map, debug_mem_map = self.generate_bus() with open("build/mem_map.txt", "w+") as f: def println_both(x): print(x) f.write(x+"\n") println_both("Main Memory Map:") print_mem_map(main_mem_map, print_fn = println_both) println_both("") println_both("Debug Memory Map:") print_mem_map(debug_mem_map, print_fn = println_both) print() with open("build/platform.h", "w+") as f: def println_file(x): f.write(x+"\n") println_file("// THIS FILE IS AUTO-GENERATED AND SHOULD NOT BE EDITED BY HAND") println_file("#include <stdint.h>") println_file("") println_file("#ifndef PLATFORM_H") println_file("#define PLATFORM_H 1") println_file("") print_mem_map_defines(wb_address_map, print_fn = println_file) println_file("") print_io_map_defines(io_config, wb_address_map["ioctrl"][0], print_fn = println_file) println_file("#define CLK_FREQ {}".format(CLK)) println_file("#define CLKS_PER_MILLIS {}".format(CLK // 1000)) println_file("") println_file("#endif") with open("build/platform_init.h", "w+") as f: def println_file(x): f.write(x+"\n") println_file("// THIS FILE IS AUTO-GENERATED AND SHOULD NOT BE EDITED BY HAND") println_file("") println_file("#ifndef PLATFORM_INIT_H") println_file("#define PLATFORM_INIT_H 1") println_file("") print_mem_map_defines(wb_address_map, print_fn = println_file, raw_only = True) println_file("#endif") with open("build/platform.ld", "w+") as f: def println_file(x): f.write(x+"\n") println_file("/* THIS FILE IS AUTO-GENERATED AND SHOULD NOT BE EDITED BY HAND */") println_file("") print_mem_map_ld(wb_address_map, print_fn = println_file)
def __init__(self, pads, bus=None): if bus is None: self.bus = wb.Interface(data_width=32, adr_width=32) else: self.bus = bus self.irq = Signal() wb_req = self.bus.cyc & self.bus.stb & ~self.bus.ack data_out_reg = Signal(8) data_out = Signal(8) data_out_valid = Signal() self.sync += If(data_out_valid, data_out_reg.eq(data_out)) data_write = Signal(8) start_write = Signal() ready = Signal() mode = Signal(2) divider = Signal(16, reset=25) # 1Mhz at 50Mhz clk last_out_valid = Signal() # Address 0 = Config / Status = {13'b0, ready[0:0], mode[1:0], divider[15:0]} # Address 4 = Data Write (lowest 8 bits) # Address 8 = Data Read (lowest 8 bits) self.sync += [ self.bus.ack.eq(0), self.bus.err.eq(0), self.irq.eq(0), start_write.eq(0), last_out_valid.eq(data_out_valid), If(data_out_valid & ~last_out_valid, self.irq.eq(1)), If( wb_req, self.bus.ack.eq(1), If((self.bus.adr >> 2) == 0, If(self.bus.we & self.bus.sel[0], divider[0:8].eq(self.bus.dat_w[0:8])), If(self.bus.we & self.bus.sel[1], divider[8:16].eq(self.bus.dat_w[8:16])), If(self.bus.we & self.bus.sel[2], mode.eq(self.bus.dat_w[16:18])), self.bus.dat_r.eq(Cat(divider, mode, ready))), ), If((self.bus.adr >> 2) == 1, If(self.bus.we & self.bus.sel[0], data_write.eq(self.bus.dat_w[0:8]), start_write.eq(1)), self.bus.dat_r.eq(data_write)), If( (self.bus.adr >> 2) == 2, self.bus.dat_r.eq(data_out_reg), ), ] self.specials += Instance("spi_controller", i_i_TX_Byte=data_write, i_i_TX_DV=start_write, o_o_TX_Ready=ready, o_o_RX_Byte=data_out, o_o_RX_DV=data_out_valid, o_o_SPI_Clk=pads.clk, i_i_SPI_MISO=pads.miso, o_o_SPI_MOSI=pads.mosi, i_i_CPHA=mode[0], i_i_CPOL=mode[1], i_i_divider=divider, i_i_Clk=ClockSignal(), i_i_Rst=ResetSignal())
def __init__(self, controllers, peripherals, shared=None, register=False): if shared is None: shared = wb.Interface(data_width=32, adr_width=32) self.submodules.arbiter = wb.Arbiter(controllers, shared) self.submodules.decoder = wb.Decoder(shared, peripherals, register)
def __init__(self, pins, config, bus=None, debug_bus=None): if bus is None: self.bus = wb.Interface(data_width=32, adr_width=32) else: self.bus = bus if debug_bus is None: self.debug_bus = wb.Interface(data_width=32, adr_width=32) else: self.debug_bus = debug_bus self.irq = Signal() self.sync += self.irq.eq(0) io = [] assert 0 < len(config) and len(config) < 256 """ Pad naming: io0, io1, io2, ... Config: [ { index: 0, # must match index of pin in array name: "", # optional mode: "standard/passthrough/passthrough-direct", sync: True/False, options: [ # Only for standard-mode (ind, name, i, o, oe), # ind must not be zero (ind, name, i, o, oe), (ind, name, i, o, oe), ... up to 16 ], passthrough: (i, o, oe) # Only for passthrough-mode } ] state = {4'b0, type[1:0], actual_enable, actual_select[3:0], actual_irqmode[1:0], actual_oe, actual_out, actual_in} Dbg reg: {15'b0, 1'b0, state[15:0]} CPU reg: {state[15:0], 1'b0, enable, select[3:0], irqmode[1:0], 5'b0, gpio_oe, gpio_out, gpio_in} Data: - GPIO in - GPIO out - GPIO oe - enable - select[3:0] - IRQ mode[1:0] - 0 = none, 1 = rising, 2 = falling State: - Actual out - Actual in - Actual oe - Actual enable - Actual select[3:0] - Actual irq mode[1:0] - type[1:0] - 0 = standard, 1 = passthrough, 2 = passthrough-silent """ # Set up I/O for pin_ind, pin in enumerate(config): assert pin["index"] == pin_ind mode = pin["mode"] assert mode in ["standard", "passthrough", "passthrough-direct"] if mode != "standard": assert "options" not in pin or len(pin["options"]) == 0 assert "passthrough" in pin pad = pins["io{}".format(pin_ind)] ind = Constant(pin_ind, bits_sign=8) if pin["sync"]: ff1 = Signal(reset_less=True) ff2 = Signal(reset_less=True) pad_i = Signal(reset_less=True) self.sync += [ ff1.eq(pad.i), ff2.eq(ff1), pad_i.eq(ff2), ] else: pad_i = pad.i pad_o = pad.o pad_oe = pad.oe if mode == "standard": typ = Constant(0, bits_sign=2) elif mode == "passthrough": typ = Constant(1, bits_sign=2) elif mode == "passthrough-direct": typ = Constant(2, bits_sign=2) last = Signal(reset=0) self.sync += last.eq(pad_i) rising = ~pad_oe & pad_i & ~last falling = ~pad_oe & last & ~pad_i gpio_in = Signal(reset=0) gpio_out = Signal(reset=0) gpio_oe = Signal(reset=0) irqmode = Signal(2, reset=0) select = Signal(4, reset=0) enable = Signal(reset=0) if mode == "passthrough-direct": state = Cat(Constant(0, bits_sign=3), irqmode, select, enable, typ, Constant(0, bits_sign=4)) else: state = Cat(pad_i, pad_o, pad_oe, irqmode, select, enable, typ, Constant(0, bits_sign=4)) assert len(state) == 16 dbg_reg = Cat(state, Constant(0, bits_sign=16)) assert len(dbg_reg) == 32 cpu_reg = Cat(gpio_in, gpio_out, gpio_oe, Constant(0, bits_sign=5), irqmode, select, enable, Constant(0, bits_sign=1), state) assert len(cpu_reg) == 32 if mode == "passthrough-direct" or mode == "passthrough": self.comb += [ pin["passthrough"][0].eq(pad_i), pad_o.eq(pin["passthrough"][1]), pad_oe.eq(pin["passthrough"][2]), ] else: # Set up standard I/O multiplexing options = [x for x in pin["options"]] assert not any([x[0] == 0 for x in options]) #options.append((0, "gpio", gpio_in, gpio_out, gpio_oe)) cases = {} cases["default"] = [ pad_o.eq(gpio_out), pad_oe.eq(gpio_oe), ] self.comb += gpio_in.eq(pad_i) for opt_ind, name, i, o, oe in options: self.comb += i.eq(pad_i) cases[opt_ind] = [ pad_o.eq(o), pad_oe.eq(oe), ] self.comb += [ If(~enable, pad_oe.eq(0), pad_o.eq(0)).Else(Case(select, cases)) ] self.sync += [ If(rising & irqmode == 1, self.irq.eq(1)), If(falling & irqmode == 2, self.irq.eq(1)) ] assert pin_ind == len(io) io.append({ "index": pin_ind, "gpio_in": gpio_in, "gpio_out": gpio_out, "gpio_oe": gpio_oe, "enable": enable, "select": select, "irqmode": irqmode, "cpu_reg": cpu_reg, "dbg_reg": dbg_reg, }) # Main bus access # CPU reg: {state[15:0], 1'b0, enable, select[3:0], irqmode[1:0], 5'b0, gpio_oe, gpio_out, gpio_in} self.sync += [ self.bus.ack.eq(0), self.bus.err.eq(0), If( self.bus.stb & self.bus.cyc & ~self.bus.ack, self.bus.ack.eq(1), *[ If((self.bus.adr >> 2) == port["index"], self.bus.dat_r.eq(port["cpu_reg"]), If(self.bus.we & self.bus.sel[0], port["gpio_out"].eq(self.bus.dat_w[1]), port["gpio_oe"].eq(self.bus.dat_w[2])), If(self.bus.we & self.bus.sel[1], port["irqmode"].eq(self.bus.dat_w[8:10]), port["select"].eq(self.bus.dat_w[10:14]), port["enable"].eq(self.bus.dat_w[14]))) for port in io ]) ] # Debug bus access self.sync += [ self.debug_bus.ack.eq(0), self.debug_bus.err.eq(0), If( self.debug_bus.stb & self.debug_bus.cyc & ~self.debug_bus.ack, self.debug_bus.ack.eq(1), *[ If( (self.debug_bus.adr >> 2) == port["index"], self.debug_bus.dat_r.eq(port["dbg_reg"]), ) for port in io ]) ]
def __init__(self, bus=None, debug_bus=None, enable_code=0xABAB12): if bus is None: self.bus = wb.Interface(data_width=32, adr_width=32) else: self.bus = bus if debug_bus is None: self.debug_bus = wb.Interface(data_width=32, adr_width=32) else: self.debug_bus = debug_bus wb_sel = Signal(4, reset=0b1111) wb_addr = Signal(32) wb_wr_data = Signal(32) wb_rd_data = Signal(32) wb_rd_data_valid = Signal() wb_error = Signal() wb_in_progress = Signal() enable_entry = Signal(32, reset=0) enabled = enable_entry == Constant(enable_code) # 00 = Cfg/Status {19'b0, sel_valid, sel[3:0], 2'b0, error, in_progress, rd_valid, halt, rd_req, wr_req} # 04 = Addr # 08 = Write Data # 0C = Read Data # 10 = Enable # Main bus self.comb += [ self.bus.stb.eq(wb_in_progress), self.bus.cyc.eq(wb_in_progress), self.bus.adr.eq(wb_addr), self.bus.dat_w.eq(wb_wr_data), self.bus.sel.eq(wb_sel) ] self.sync += [ If(self.bus.ack, wb_in_progress.eq(0), wb_rd_data.eq(self.bus.dat_r), wb_rd_data_valid.eq(1), wb_error.eq(0)), If(self.bus.err, wb_in_progress.eq(0), wb_rd_data_valid.eq(0), wb_error.eq(1)) ] # Debug bus self.sync += [ self.debug_bus.ack.eq(0), self.debug_bus.err.eq(0), self.debug_bus.dat_r.eq(0), If( self.debug_bus.stb & self.debug_bus.cyc & ~self.debug_bus.ack, self.debug_bus.ack.eq(1), If((self.debug_bus.adr >> 2) == 0, If( self.debug_bus.we & self.debug_bus.sel[0], If(enabled & ~wb_in_progress & self.debug_bus.dat_w[0], wb_in_progress.eq(1), wb_error.eq(0), wb_rd_data.eq(0), wb_rd_data_valid.eq(0), self.bus.we.eq(1)).Elif( enabled & ~wb_in_progress & self.debug_bus.dat_w[1], wb_in_progress.eq(1), wb_error.eq(0), wb_rd_data.eq(0), wb_rd_data_valid.eq(0), self.bus.we.eq(0)).Elif(self.debug_bus.dat_w[2], wb_in_progress.eq(0))), If( self.debug_bus.we & self.debug_bus.sel[1], If(self.debug_bus.dat_w[12] == 1, wb_sel.eq(self.debug_bus.dat_w[8:12]))), self.debug_bus.dat_r.eq( Cat(Constant(0, bits_sign=3), wb_rd_data_valid, wb_in_progress, wb_error, Constant(0, bits_sign=2), wb_sel, Constant(0, bits_sign=1)))), If((self.debug_bus.adr >> 2) == 1, If(self.debug_bus.we & self.debug_bus.sel[0], wb_addr[0:8].eq(self.debug_bus.dat_w[0:8])), If(self.debug_bus.we & self.debug_bus.sel[1], wb_addr[8:16].eq(self.debug_bus.dat_w[8:16])), If(self.debug_bus.we & self.debug_bus.sel[2], wb_addr[16:24].eq(self.debug_bus.dat_w[16:24])), If(self.debug_bus.we & self.debug_bus.sel[3], wb_addr[24:32].eq(self.debug_bus.dat_w[24:32])), self.debug_bus.dat_r.eq(wb_addr)), If((self.debug_bus.adr >> 2) == 2, If(self.debug_bus.we & self.debug_bus.sel[0], wb_wr_data[0:8].eq(self.debug_bus.dat_w[0:8])), If(self.debug_bus.we & self.debug_bus.sel[1], wb_wr_data[8:16].eq(self.debug_bus.dat_w[8:16])), If(self.debug_bus.we & self.debug_bus.sel[2], wb_wr_data[16:24].eq(self.debug_bus.dat_w[16:24])), If(self.debug_bus.we & self.debug_bus.sel[3], wb_wr_data[24:32].eq(self.debug_bus.dat_w[24:32])), self.debug_bus.dat_r.eq(wb_wr_data)), If((self.debug_bus.adr >> 2) == 3, self.debug_bus.dat_r.eq(wb_rd_data)), If((self.debug_bus.adr >> 2) == 4, If(self.debug_bus.we & self.debug_bus.sel[0], enable_entry[0:8].eq(self.debug_bus.dat_w[0:8])), If(self.debug_bus.we & self.debug_bus.sel[1], enable_entry[8:16].eq(self.debug_bus.dat_w[8:16])), If(self.debug_bus.we & self.debug_bus.sel[2], enable_entry[16:24].eq(self.debug_bus.dat_w[16:24])), If(self.debug_bus.we & self.debug_bus.sel[3], enable_entry[24:32].eq(self.debug_bus.dat_w[24:32])), self.debug_bus.dat_r.eq(enable_entry)), ) ]