def top(din, init_b, cclk, ref_clk, soc_clk_p, soc_clk_n, soc_cs, soc_ras, soc_cas, soc_we, soc_ba, soc_a, soc_dqs, soc_dm, soc_dq, adc_clk_p, adc_clk_n, adc_dat_p, adc_dat_n, adc_ovr_p, adc_ovr_n, shifter_sck, shifter_sdo, bu2506_ld, adf4360_le, adc08d500_cs, lmh6518_cs, dac8532_sync, trig_p, trig_n, ba7406_vd, ba7406_hd, ac_trig, probe_comp, ext_trig_out, i2c_scl, i2c_sda, mcb3_dram_ck, mcb3_dram_ck_n, mcb3_dram_ras_n, mcb3_dram_cas_n, mcb3_dram_we_n, mcb3_dram_ba, mcb3_dram_a, mcb3_dram_odt, mcb3_dram_dqs, mcb3_dram_dqs_n, mcb3_dram_udqs, mcb3_dram_udqs_n, mcb3_dram_dm, mcb3_dram_udm, mcb3_dram_dq, bank2): insts = [] # Clock generator using STARTUP_SPARTAN primitive clk_unbuf = Signal(False) clk_unbuf_inst = startup_spartan6('startup_inst', cfgmclk = clk_unbuf) insts.append(clk_unbuf_inst) clk_buf = Signal(False) clk_inst = bufg('bufg_clk', clk_unbuf, clk_buf) insts.append(clk_inst) system = System(clk_buf, None) mux = WbMux() # Rename and adapt external SPI bus signals slave_spi_bus = SpiInterface() slave_cs = Signal(False) slave_cs_inst = syncro(clk_buf, din, slave_spi_bus.CS) insts.append(slave_cs_inst) slave_sck_inst = syncro(clk_buf, cclk, slave_spi_bus.SCK) insts.append(slave_sck_inst) slave_sdioinst = tristate(init_b, slave_spi_bus.SD_I, slave_spi_bus.SD_O, slave_spi_bus.SD_OE) insts.append(slave_sdioinst) #################################################################### # SoC bus if 0: soc_clk = Signal(False) soc_clk_b = Signal(False) soc_clk_inst = ibufgds_diff_out('ibufgds_diff_out_soc_clk', soc_clk_p, soc_clk_n, soc_clk, soc_clk_b) insts.append(soc_clk_inst) soc_clk._name = 'soc_clk' # Must match name of timing spec in ucf file soc_clk_b._name = 'soc_clk_b' # Must match name of timing spec in ucf file soc_system = System(soc_clk, None) soc_bus = DdrBus(2, 12, 2) soc_connect_inst = ddr_connect( soc_bus, soc_clk, soc_clk_b, None, soc_cs, soc_ras, soc_cas, soc_we, soc_ba, soc_a, soc_dqs, soc_dm, soc_dq) insts.append(soc_connect_inst) if 1: soc_source0 = DdrSource(soc_system, 16, 16) soc_source1 = DdrSource(soc_system, 16, 16) soc_ddr = Ddr(soc_source0, soc_source1) soc_inst = soc_ddr.gen(soc_system, soc_bus) insts.append(soc_inst) if 1: # Trace soc bus control signals soc_capture = Signal(False) soc_ctl = RegFile('soc_ctl', "SOC control", [ RwField(system, 'soc_capture', "Capture samples", soc_capture), ]) mux.add(soc_ctl, 0x231) soc_capture_sync = Signal(False) soc_capture_sync_inst = syncro(soc_clk, soc_capture, soc_capture_sync) insts.append(soc_capture_sync_inst) soc_sdr = ConcatSignal( soc_a, soc_ba, soc_we, soc_cas, soc_ras, soc_cs) soc_sdr_sampler = Sampler(addr_depth = 0x800, sample_clk = soc_clk, sample_data = soc_sdr, sample_enable = soc_capture_sync) mux.add(soc_sdr_sampler, 0x2000) soc_reg = ConcatSignal( soc_bus.A, soc_bus.BA, soc_bus.WE_B, soc_bus.CAS_B, soc_bus.RAS_B, soc_bus.CS_B) soc_reg_sampler = Sampler(addr_depth = 0x800, sample_clk = soc_clk, sample_data = soc_reg, sample_enable = soc_capture_sync) mux.add(soc_reg_sampler, 0x2800) soc_ddr_0 = ConcatSignal(soc_bus.DQ1_OE, soc_bus.DQS1_O, soc_bus.DQS1_OE, soc_bus.DQ0_I, soc_bus.DM0_I, soc_bus.DQS0_I) soc_ddr_1 = ConcatSignal(soc_bus.DQ0_OE, soc_bus.DQS0_O, soc_bus.DQS0_OE, soc_bus.DQ1_I, soc_bus.DM1_I, soc_bus.DQS1_I) soc_ddr_sampler_0 = Sampler(addr_depth = 0x800, sample_clk = soc_clk, sample_data = soc_ddr_0, sample_enable = soc_capture_sync) mux.add(soc_ddr_sampler_0, 0x3000) soc_ddr_sampler_1 = Sampler(addr_depth = 0x800, sample_clk = soc_clk, sample_data = soc_ddr_1, sample_enable = soc_capture_sync) mux.add(soc_ddr_sampler_1, 0x3800) #################################################################### # ADC bus adc_clk_ibuf = Signal(False) adc_clk_ibuf_b = Signal(False) adc_clk_ibuf_inst = ibufgds_diff_out('ibufgds_diff_out_adc_clk', adc_clk_p, adc_clk_n, adc_clk_ibuf, adc_clk_ibuf_b) insts.append(adc_clk_ibuf_inst) if 0: adc_clk = Signal(False) adc_clk_buf_inst = bufg('bufg_adc_clk', adc_clk_ibuf, adc_clk) insts.append(adc_clk_buf_inst) adc_clk_b = Signal(False) adc_clk_b_buf_inst = bufg('bufg_adc_clk_b', adc_clk_ibuf_b, adc_clk_b) insts.append(adc_clk_b_buf_inst) else: adc_clk = adc_clk_ibuf adc_clk_b = adc_clk_ibuf_b adc_clk._name = 'adc_clk' # Must match name of timing spec in ucf file adc_clk_b._name = 'adc_clk_b' # Must match name of timing spec in ucf file if 0: # For some reason myhdl doesn't recognize these signals adc_dat_p._name = 'adc_dat_p' adc_dat_n._name = 'adc_dat_n' if 0: adc_dat_p.read = True adc_dat_n.read = True print "adc_dat_p", type(adc_dat_p), len(adc_dat_p) print "adc_dat_n", type(adc_dat_n), len(adc_dat_n) if 0: adc_dat_array = [ Signal(False) for _ in range(len(adc_dat_p)) ] for i in range(len(adc_dat_p)): adc_dat_inst = ibufds('ibufds_adc_dat%d' % i, adc_dat_p[i], adc_dat_n[i], adc_dat_array[i]) insts.append(adc_dat_inst) print 'adc_dat_array', adc_dat_array adc_dat = ConcatSignal(*adc_dat_array) print len(adc_dat) else: adc_dat = Signal(intbv(0)[len(adc_dat_p):]) if 0: adc_dat._name = 'adc_dat' adc_dat.read = True adc_dat_inst = ibufds_vec('adc_dat_ibufds', adc_dat_p, adc_dat_n, adc_dat) insts.append(adc_dat_inst) adc_dat_0 = Signal(intbv(0)[len(adc_dat):]) adc_dat_1 = Signal(intbv(0)[len(adc_dat):]) adc_dat_ddr_inst = iddr2('adc_dat_iddr2', adc_dat, adc_dat_0, adc_dat_1, c0 = adc_clk, c1 = adc_clk_b, ddr_alignment = 'C0') insts.append(adc_dat_ddr_inst) adc_ovr = Signal(False) adc_ovr_inst = ibufds('ibufds_adc_ovr', adc_ovr_p, adc_ovr_n, adc_ovr) insts.append(adc_ovr_inst) if 1: adc_capture = Signal(False) adc_ctl = RegFile('adc_ctl', "ADC control", [ RwField(system, 'adc_capture', "Capture samples", adc_capture), ]) mux.add(adc_ctl, 0x230) adc_capture_sync = Signal(False) adc_capture_sync_inst = syncro(adc_clk, adc_capture, adc_capture_sync) insts.append(adc_capture_sync_inst) adc_sampler_0 = Sampler(addr_depth = 1024, sample_clk = adc_clk, sample_data = adc_dat_0, sample_enable = adc_capture_sync, skip_cnt = 99) mux.add(adc_sampler_0, 0x4000) adc_sampler_1 = Sampler(addr_depth = 1024, sample_clk = adc_clk, sample_data = adc_dat_1, sample_enable = adc_capture_sync, skip_cnt = 99) mux.add(adc_sampler_1, 0x6000) #################################################################### # Analog frontend if 1: shifter_bus = ShifterBus(6) @always_comb def shifter_comb(): shifter_sck.next = shifter_bus.SCK shifter_sdo.next = shifter_bus.SDO bu2506_ld.next = shifter_bus.CS[0] adf4360_le.next = shifter_bus.CS[1] adc08d500_cs.next = not shifter_bus.CS[2] lmh6518_cs.next[0] = not shifter_bus.CS[3] lmh6518_cs.next[1] = not shifter_bus.CS[4] dac8532_sync.next = not shifter_bus.CS[5] insts.append(shifter_comb) shifter = Shifter(system, shifter_bus, divider = 100) addr = 0x210 for reg in shifter.create_regs(): mux.add(reg, addr) addr += 1 insts.append(shifter.gen()) trig = Signal(intbv(0)[len(trig_p):]) trig_inst = ibufds_vec('ibufds_trig', trig_p, trig_n, trig) insts.append(trig_inst) #################################################################### # Probe compensation output and external trigger output # Just toggle them at 1kHz probe_comb_div = 25000 probe_comp_ctr = Signal(intbv(0, 0, probe_comb_div)) probe_comp_int = Signal(False) @always_seq (system.CLK.posedge, system.RST) def probe_comp_seq(): if probe_comp_ctr == probe_comb_div - 1: probe_comp_int.next = not probe_comp_int probe_comp_ctr.next = 0 else: probe_comp_ctr.next = probe_comp_ctr + 1 insts.append(probe_comp_seq) @always_comb def probe_comp_comb(): probe_comp.next = probe_comp_int ext_trig_out.next = probe_comp_int insts.append(probe_comp_comb) #################################################################### dram_rst_i = Signal(False) dram_clk_p = soc_clk_p dram_clk_n = soc_clk_n dram_calib_done = Signal(False) dram_error = Signal(False) dram_ctl = RegFile('dram_ctl', "DRAM control", [ RwField(system, 'dram_rst_i', "Reset", dram_rst_i), RoField(system, 'dram_calib_done', "Calib flag", dram_calib_done), RoField(system, 'dram_error', "Error flag", dram_error), ]) mux.add(dram_ctl, 0x250) mig_inst = mig( dram_rst_i, dram_clk_p, dram_clk_n, dram_calib_done, dram_error, mcb3_dram_ck, mcb3_dram_ck_n, mcb3_dram_ras_n, mcb3_dram_cas_n, mcb3_dram_we_n, mcb3_dram_ba, mcb3_dram_a, mcb3_dram_odt, mcb3_dram_dqs, mcb3_dram_dqs_n, mcb3_dram_udqs, mcb3_dram_udqs_n, mcb3_dram_dm, mcb3_dram_udm, mcb3_dram_dq) insts.append(mig_inst) #################################################################### # Random stuff if 1: pins = ConcatSignal(cclk, i2c_sda, i2c_scl, ext_trig_out, probe_comp, ac_trig, ba7406_hd, ba7406_vd, trig, ref_clk, bank2) hc = HybridCounter() mux.add(hc, 0, pins) # I have a bug somewhere in my Mux, unless I add this the adc # sample buffer won't show up in the address range. I should fix # it but I haven't managed to figure out what's wrong yet. if 1: ram3 = Ram(addr_depth = 1024, data_width = 32) mux.add(ram3, 0x8000) wb_slave = mux # Create the wishbone bus wb_bus = wb_slave.create_bus() wb_bus.CLK_I = clk_buf wb_bus.RST_I = None # Create the SPI slave spi = SpiSlave() spi.addr_width = 32 spi.data_width = 32 wb_inst = wb_slave.gen(wb_bus) insts.append(wb_inst) slave_spi_inst = spi.gen(slave_spi_bus, wb_bus) insts.append(slave_spi_inst) return insts
def spi_slave_fifo(glbl, spibus, fifobus): """ This is an SPI slave peripheral, when the master starts clocking any data in the TX FIFO (fifobus.write) will be sent (the next byte) and the received byte will be copied to RX FIFO (fifobus.read). The `cso` interface can be used to configure how the SPI slave peripheral behaves. (Arguments == Ports) Arguments: glbl (Global): global clock and reset spibus (SPIBus): the external SPI interface fifobus (FIFOBus): the fifo interface cso (ControlStatus): the control status signals """ fifosize = 8 # Use an async FIFO to transfer from the SPI SCK clock domain and # the internal clock domain. This allows for high-speed SCK. clock, reset = glbl.clock, glbl.reset assert isinstance(spibus, SPIBus) assert isinstance(fifobus, FIFOBus) sck, csn = spibus.sck, spibus.csn # the FIFOs for the receive and transmit (external perspective) readpath = FIFOBus(width=fifobus.width) writepath = FIFOBus(width=fifobus.width) # the FIFO instances tx_fifo_inst = fifo_fast(glbl, writepath, size=fifosize) rx_fifo_inst = fifo_fast(glbl, readpath, size=fifosize) mp_fifo_inst = fifobus.assign_read_write_paths(readpath, writepath) spi_start = Signal(bool(0)) ireg, icap, icaps = Signals(intbv(0)[8:], 3) oreg, ocap = Signals(intbv(0)[8:], 2) bitcnt, b2, b3 = Signals(intbv(0, min=0, max=10), 3) @always(sck.posedge, csn.negedge) def csn_falls(): if sck: spi_start.next = False elif not csn: spi_start.next = True # SCK clock domain, this allows high SCK rates @always(sck.posedge, csn.posedge) def sck_capture_send(): if csn: b2.next = 0 bitcnt.next = 0 else: if bitcnt == 0 or spi_start: spibus.miso.next = ocap[7] oreg.next = (ocap << 1) & 0xFF else: spibus.miso.next = oreg[7] oreg.next = (oreg << 1) & 0xFF ireg.next = concat(ireg[7:0], spibus.mosi) bitcnt.next = bitcnt + 1 if bitcnt == (8 - 1): bitcnt.next = 0 b2.next = 8 icap.next = concat(ireg[7:0], spibus.mosi) else: b2.next = 0 # synchronize the SCK domain to the clock domain syncro(clock, icap, icaps) syncro(clock, b2, b3) gotit = Signal(bool(0)) @always(clock.posedge) def beh_io_capture(): # default no writes readpath.write.next = False writepath.read.next = False if b3 == 0: gotit.next = False elif b3 == 8 and not gotit: readpath.write.next = True readpath.write_data.next = icaps gotit.next = True ocap.next = writepath.read_data if not writepath.empty: writepath.read.next = True return myhdl.instances()
def top(din, init_b, cclk, ref_clk, soc_clk_p, soc_clk_n, soc_cs, soc_ras, soc_cas, soc_we, soc_ba, soc_a, soc_dqs, soc_dm, soc_dq, adc_clk_p, adc_clk_n, adc_dat_p, adc_dat_n, adc_ovr_p, adc_ovr_n, shifter_sck, shifter_sdo, bu2506_ld, adf4360_le, adc08d500_cs, lmh6518_cs, dac8532_sync, trig_p, trig_n, ba7406_vd, ba7406_hd, ac_trig, probe_comp, ext_trig_out, i2c_scl, i2c_sda, fp_rst, fp_clk, fp_din, led_green, led_white, mcb3_dram_ck, mcb3_dram_ck_n, mcb3_dram_ras_n, mcb3_dram_cas_n, mcb3_dram_we_n, mcb3_dram_ba, mcb3_dram_a, mcb3_dram_odt, mcb3_dram_dqs, mcb3_dram_dqs_n, mcb3_dram_udqs, mcb3_dram_udqs_n, mcb3_dram_dm, mcb3_dram_udm, mcb3_dram_dq, bank2): insts = [] # Clock generator using STARTUP_SPARTAN primitive clk_unbuf = Signal(False) clk_unbuf_inst = startup_spartan6('startup_inst', cfgmclk = clk_unbuf) insts.append(clk_unbuf_inst) clk_buf = Signal(False) clk_inst = bufg('bufg_clk', clk_unbuf, clk_buf) insts.append(clk_inst) spi_system = System(clk_buf, None) mux = WbMux() # Rename and adapt external SPI bus signals slave_spi_bus = SpiInterface() slave_cs = Signal(False) slave_cs_inst = syncro(clk_buf, din, slave_spi_bus.CS) insts.append(slave_cs_inst) slave_sck_inst = syncro(clk_buf, cclk, slave_spi_bus.SCK) insts.append(slave_sck_inst) slave_sdioinst = tristate(init_b, slave_spi_bus.SD_I, slave_spi_bus.SD_O, slave_spi_bus.SD_OE) insts.append(slave_sdioinst) #################################################################### # A MUX and some test code for it soc_clk = Signal(False) soc_clk_b = Signal(False) soc_system = System(soc_clk, None) sm = SimpleMux(soc_system) if 1: # A read only area which returns predictable patterns sa = Algo(soc_system, (1<<16), 32) sa_inst = sa.gen() insts.append(sa_inst) sm.add(sa.bus(), 0x10000) #################################################################### # Create a MIG instance # The DDR memory controller uses the SoC clock pins as the input # to its PLL. It also generates soc_clk which is used above soc_clk_ibuf = Signal(False) soc_clk_ibuf_inst = ibufgds('soc_clk_ibuf_inst', soc_clk_p, soc_clk_n, soc_clk_ibuf) insts.append(soc_clk_ibuf_inst) mig = Mig(soc_clk_ibuf) #################################################################### # MIG port 0 mig_port = MigPort(mig, soc_system.CLK) mig.ports[0] = mig_port # MIG port 0 command register # I'm trying to squeeze all the MIG command bits into a 32 bit # register. Since the MIG port is 32 bits wide, the low two # address bits are always going to be zero, so we only have to # keep track of the highest 24 bits of a 32 MByte address. The # highest bit of the instr field is only 1 when used for refresh. # I won't use refresh so I can skip that bit too. mig_cmd_addr = Signal(intbv(0)[24:]) mig_cmd_instr = Signal(intbv(0)[2:]) @always_comb def mig_cmd_comb(): mig_port.cmd_byte_addr.next = mig_cmd_addr << 2 mig_port.cmd_instr.next = mig_cmd_instr insts.append(mig_cmd_comb) mig_cmd = SimpleReg(soc_system, 'mig_cmd', "MIG cmd", [ SimpleRwField('addr', "", mig_cmd_addr), SimpleRwField('bl', "", mig_port.cmd_bl), SimpleRwField('instr', "", mig_cmd_instr), ]) sm.add(mig_cmd.bus(), addr = 0x210) insts.append(mig_cmd.gen()) # Strobe the cmd_en signal after the register has been written mig_cmd_bus = mig_cmd.bus() @always_seq(soc_clk.posedge, soc_system.RST) def mig_cmd_seq(): mig_port.cmd_en.next = mig_cmd_bus.WR insts.append(mig_cmd_seq) mig_status_0_bus, mig_status_0_inst = mig_port.status_reg(soc_system, 0) sm.add(mig_status_0_bus, addr = 0x211) insts.append(mig_status_0_inst) mig_count_0_bus, mig_count_0_inst = mig_port.count_reg(soc_system, 0) sm.add(mig_count_0_bus, addr = 0x212) insts.append(mig_count_0_inst) # MIG port 0 read/write data. This register must be a bit off # from any other regiters that might be read to avoid a read burst # popping off data from the fifo when not expected mig_data_bus = SimpleBus(1, 32) sm.add(mig_data_bus, addr = 0x218) @always_comb def mig_data_comb(): mig_port.rd_en.next = mig_data_bus.RD insts.append(mig_data_comb) @always_seq (soc_system.CLK.posedge, soc_system.RST) def mig_data_seq(): mig_port.wr_en.next = mig_data_bus.WR mig_port.wr_data.next = mig_data_bus.WR_DATA if mig_data_bus.RD: mig_data_bus.RD_DATA.next = mig_port.rd_data else: mig_data_bus.RD_DATA.next = 0 insts.append(mig_data_seq) #################################################################### # Front panel attached to the SoC bus if 1: frontpanel = FrontPanel(soc_system, fp_rst, fp_clk, fp_din) frontpanel_inst = frontpanel.gen() insts.append(frontpanel_inst) # These need to be spaced a bit apart, otherwise burst will make # us read from the data_bus register when we only want to read the # ctl_bus register. sm.add(frontpanel.ctl_bus, addr = 0x100) sm.add(frontpanel.data_bus, addr = 0x104) #################################################################### # LEDs on the front panel if 1: led_green_tmp = Signal(False) led_white_tmp = Signal(False) misc_reg = SimpleReg(soc_system, 'misc', "Miscellaneous", [ SimpleRwField('green', "Green LED", led_green_tmp), SimpleRwField('white', "White LED", led_white_tmp), ]) sm.add(misc_reg.bus(), addr = 0x108) insts.append(misc_reg.gen()) @always_comb def led_inst(): led_green.next = led_green_tmp led_white.next = led_white_tmp insts.append(led_inst) #################################################################### # FIFO reading from MIG if 1: mig_fifo = SyncFifo(None, soc_clk, intbv(0)[32:], 4) insts.append(mig_fifo.gen()) mig_fifo_count_bus, mig_fifo_count_inst = mig_fifo.count_reg( soc_system, 'mig_fifo') sm.add(mig_fifo_count_bus, addr = 0x132) insts.append(mig_fifo_count_inst) mig_rd_port = MigPort(mig, soc_clk) mig.ports[2] = mig_rd_port mig_status_2_bus, mig_status_2_inst = mig_rd_port.status_reg(soc_system, 2) sm.add(mig_status_2_bus, addr = 0x134) insts.append(mig_status_2_inst) mig_count_2_bus, mig_count_2_inst = mig_rd_port.count_reg(soc_system, 2) sm.add(mig_count_2_bus, addr = 0x135) insts.append(mig_count_2_inst) mig_reader_addresser = MigReaderAddresser('mig_reader', soc_system, mig_rd_port) insts.append(mig_reader_addresser.regs_gen()) sm.add(mig_reader_addresser.regs_bus(), addr = 0x130) mig_reader_addresser_inst = mig_reader_addresser.gen(mig_rd_port) insts.append(mig_reader_addresser_inst) mig_reader = MigReader(mig_rd_port, mig_fifo) insts.append(mig_reader.gen()) #################################################################### # Test code for FIFO RAM if 0: wr_fifo = DummyWriteFifo(None, soc_clk, intbv(0)[32:]) insts.append(wr_fifo.gen()) fifo_ram = FifoRam('fifo_ram', soc_system, wr_fifo, mig_fifo, 1024, 32) insts.append(fifo_ram.regs_gen()) sm.add(fifo_ram.regs_bus(), addr = 0x120) insts.append(fifo_ram.gen()) sm.add(fifo_ram.bus(), addr = 0x8000) #################################################################### # Test code for renderer if 1: renderer_clr_port = SimplePort(1) renderer_clr = Signal(False) renderer_clr_addr = Signal(intbv(0)[8:]) renderer_idle = Signal(False) renderer0 = Renderer(system = soc_system, sample_width = 8, accumulator_width = 16) insts.append(renderer0.gen()) renderer1 = Renderer(system = soc_system, sample_width = 8, accumulator_width = 16) insts.append(renderer1.gen()) renderer2 = Renderer(system = soc_system, sample_width = 8, accumulator_width = 16) insts.append(renderer2.gen()) renderer3 = Renderer(system = soc_system, sample_width = 8, accumulator_width = 16) insts.append(renderer3.gen()) renderer_reg = SimpleReg(soc_system, 'renderer', "", [ SimpleField('clear', "", renderer_clr_port), SimpleRoField('idle', "", renderer_idle), ]) sm.add(renderer_reg.bus(), addr = 0x240) insts.append(renderer_reg.gen()) renderer_bus = SimpleBus(addr_depth = 256, data_width = 32) @always_seq(soc_clk.posedge, None) def renderer_seq(): renderer0.STROBE.next = 0 renderer1.STROBE.next = 0 renderer2.STROBE.next = 0 renderer3.STROBE.next = 0 # Can't feed the renderer it is read or written from the host mig_fifo.RD.next = 0 if (not renderer_bus.RD and not renderer_bus.WR and not mig_fifo.RD_EMPTY): renderer0.SAMPLE.next = mig_fifo.RD_DATA[8:0] renderer0.STROBE.next = 1 renderer1.SAMPLE.next = mig_fifo.RD_DATA[16:8] renderer1.STROBE.next = 1 renderer2.SAMPLE.next = mig_fifo.RD_DATA[24:16] renderer2.STROBE.next = 1 renderer3.SAMPLE.next = mig_fifo.RD_DATA[32:24] renderer3.STROBE.next = 1 mig_fifo.RD.next = 1 renderer_idle.next = 0 if mig_fifo.RD_EMPTY and mig_reader_addresser.rd_count == 0: renderer_idle.next = 1 insts.append(renderer_seq) @always_seq(soc_clk.posedge, None) def renderer_clr_seq(): renderer_clr.next = 0 renderer_clr_addr.next = 0 if renderer_clr_port.WR and renderer_clr_port.WR_DATA != 0: renderer_clr.next = 1 renderer_clr_addr.next = 0 elif renderer_clr: if renderer_clr_addr.next != 255: renderer_clr.next = 1 renderer_clr_addr.next = renderer_clr_addr + 1 renderer_clr_port.RD_DATA.next = 0 if renderer_clr_port.RD: renderer_clr_port.RD_DATA.next = renderer_clr insts.append(renderer_clr_seq) renderer0_bus = renderer0.bus() renderer1_bus = renderer1.bus() renderer2_bus = renderer2.bus() renderer3_bus = renderer3.bus() # Combine results from all four renderers @always_comb def renderer_bus_comb(): renderer0_bus.WR.next = 0 renderer1_bus.WR.next = 0 renderer2_bus.WR.next = 0 renderer3_bus.WR.next = 0 renderer0_bus.ADDR.next = 0 renderer1_bus.ADDR.next = 0 renderer2_bus.ADDR.next = 0 renderer3_bus.ADDR.next = 0 renderer0_bus.WR_DATA.next = 0 renderer1_bus.WR_DATA.next = 0 renderer2_bus.WR_DATA.next = 0 renderer3_bus.WR_DATA.next = 0 renderer0_bus.RD.next = 0 renderer1_bus.RD.next = 0 renderer2_bus.RD.next = 0 renderer3_bus.RD.next = 0 if renderer_bus_RD or renderer_bus.WR: renderer0_bus.ADDR.next = renderer_bus.ADDR renderer1_bus.ADDR.next = renderer_bus.ADDR renderer2_bus.ADDR.next = renderer_bus.ADDR renderer3_bus.ADDR.next = renderer_bus.ADDR renderer0_bus.WR.next = renderer_bus.WR renderer1_bus.WR.next = renderer_bus.WR renderer2_bus.WR.next = renderer_bus.WR renderer3_bus.WR.next = renderer_bus.WR renderer0_bus.WR_DATA.next = renderer_bus.WR_DATA renderer1_bus.WR_DATA.next = renderer_bus.WR_DATA renderer2_bus.WR_DATA.next = renderer_bus.WR_DATA renderer3_bus.WR_DATA.next = renderer_bus.WR_DATA renderer0_bus.RD.next = renderer_bus.RD renderer1_bus.RD.next = renderer_bus.RD renderer2_bus.RD.next = renderer_bus.RD renderer3_bus.RD.next = renderer_bus.RD elif renderer_clr: renderer0_bus.ADDR.next = renderer_clr_addr renderer1_bus.ADDR.next = renderer_clr_addr renderer2_bus.ADDR.next = renderer_clr_addr renderer3_bus.ADDR.next = renderer_clr_addr renderer0_bus.WR.next = 1 renderer1_bus.WR.next = 1 renderer2_bus.WR.next = 1 renderer3_bus.WR.next = 1 renderer_bus.RD_DATA.next[16:0] = renderer0_bus.RD_DATA + renderer1_bus.RD_DATA renderer_bus.RD_DATA.next[32:16] = renderer2_bus.RD_DATA + renderer3_bus.RD_DATA insts.append(renderer_bus_comb) sm.add(renderer_bus, addr = 0x400) #################################################################### # ADC bus ADC_INVERT = 0x51a04418 adc_clk = Signal(False) adc_clk_b = Signal(False) adc_clk_ibuf_inst = ibufgds_diff_out('ibufgds_diff_out_adc_clk', adc_clk_p, adc_clk_n, adc_clk, adc_clk_b) insts.append(adc_clk_ibuf_inst) adc_dat = Signal(intbv(0)[len(adc_dat_p):]) adc_dat_ibuf_inst = ibufds_vec('adc_dat_ibufds', adc_dat_p, adc_dat_n, adc_dat) insts.append(adc_dat_ibuf_inst) adc_dat_tmp_0 = Signal(intbv(0)[len(adc_dat):]) adc_dat_tmp_1 = Signal(intbv(0)[len(adc_dat):]) adc_dat_ddr_inst = iddr2('adc_dat_iddr2', adc_dat, adc_dat_tmp_0, adc_dat_tmp_1, c0 = adc_clk, c1 = adc_clk_b, ddr_alignment = 'C0') insts.append(adc_dat_ddr_inst) adc_dat_0 = Signal(intbv(0)[len(adc_dat):]) adc_dat_1 = Signal(intbv(0)[len(adc_dat):]) @always_comb def adc_dat_inv_inst(): adc_dat_0.next = adc_dat_tmp_0 ^ ADC_INVERT adc_dat_1.next = adc_dat_tmp_1 ^ ADC_INVERT insts.append(adc_dat_inv_inst) adc_ovr = Signal(False) adc_ovr_inst = ibufds('ibufds_adc_ovr', adc_ovr_p, adc_ovr_n, adc_ovr) insts.append(adc_ovr_inst) if 1: fifo_overflow_0 = Signal(False) fifo_overflow_1 = Signal(False) adc_capture = Signal(False) adc_ctl = RegFile('adc_ctl', "ADC control", [ RwField(spi_system, 'adc_capture', "Capture samples", adc_capture), RoField(spi_system, 'fifo_overflow_0', "", fifo_overflow_0), RoField(spi_system, 'fifo_overflow_', "", fifo_overflow_1), ]) mux.add(adc_ctl, 0x230) adc_capture_sync = Signal(False) adc_capture_sync_inst = syncro(adc_clk, adc_capture, adc_capture_sync) insts.append(adc_capture_sync_inst) if 0: adc_sampler_0 = Sampler(addr_depth = 1024, sample_clk = adc_clk, sample_data = adc_dat_0, sample_enable = adc_capture_sync, skip_cnt = 99) mux.add(adc_sampler_0, 0x4000) adc_sampler_1 = Sampler(addr_depth = 1024, sample_clk = adc_clk, sample_data = adc_dat_1, sample_enable = adc_capture_sync, skip_cnt = 99) mux.add(adc_sampler_1, 0x6000) mig_sample_synthetic = Signal(False) mig_sample_enable = Signal(False) mig_sample_enable_sync_adc = Signal(False) insts.append(syncro(adc_clk, mig_sample_enable, mig_sample_enable_sync_adc)) mig_sample_overflow_0 = Signal(False) mig_sample_overflow_1 = Signal(False) # Synthetic ADC data to test the FIFO mig_synthetic_data_0 = Signal(intbv(0)[32:]) mig_synthetic_data_1 = Signal(intbv(0)[32:]) @always_seq(adc_clk.posedge, None) def mig_synthetic_inst(): if mig_sample_enable_sync_adc: mig_synthetic_data_0.next = mig_synthetic_data_0 + 2 mig_synthetic_data_1.next = mig_synthetic_data_1 + 2 else: mig_synthetic_data_0.next = 1 mig_synthetic_data_1.next = 0 insts.append(mig_synthetic_inst) mig_data_0 = Signal(intbv(0)[32:]) mig_data_1 = Signal(intbv(0)[32:]) @always_comb def mig_data_inst(): if mig_sample_synthetic: mig_data_0.next = mig_synthetic_data_0 mig_data_1.next = mig_synthetic_data_1 else: mig_data_0.next = adc_dat_0 mig_data_1.next = adc_dat_1 insts.append(mig_data_inst) if 1: adc_mig_port_0 = MigPort(mig, soc_clk) mig.ports[4] = adc_mig_port_0 mig_status_4_bus, mig_status_4_inst = adc_mig_port_0.status_reg(soc_system, 4) sm.add(mig_status_4_bus, addr = 0x220) insts.append(mig_status_4_inst) mig_count_4_bus, mig_count_4_inst = adc_mig_port_0.count_reg(soc_system, 4) sm.add(mig_count_4_bus, addr = 0x221) insts.append(mig_count_4_inst) adc_mig_port_1 = MigPort(mig, soc_clk) mig.ports[5] = adc_mig_port_1 mig_status_5_bus, mig_status_5_inst = adc_mig_port_1.status_reg(soc_system, 5) sm.add(mig_status_5_bus, addr = 0x228) insts.append(mig_status_5_inst) mig_count_5_bus, mig_count_5_inst = adc_mig_port_1.count_reg(soc_system, 5) sm.add(mig_count_5_bus, addr = 0x229) insts.append(mig_count_5_inst) mig_sampler = MigSampler2(sample_clk = adc_clk, sample_data_0 = mig_data_0, sample_data_1 = mig_data_1, sample_enable = mig_sample_enable_sync_adc, mig_port_0 = adc_mig_port_0, mig_port_1 = adc_mig_port_1, overflow_0 = mig_sample_overflow_0, overflow_1 = mig_sample_overflow_1, ) insts.append(mig_sampler.gen()) mig_sampler_reg = SimpleReg(soc_system, 'mig_sampler', "", [ SimpleRwField('enable', "", mig_sample_enable), SimpleRwField('synthetic', "", mig_sample_synthetic), SimpleRoField('overflow_0', "", mig_sample_overflow_0), SimpleRoField('overflow_1', "", mig_sample_overflow_1), ]) sm.add(mig_sampler_reg.bus(), addr = 0x230) insts.append(mig_sampler_reg.gen()) #################################################################### # Analog frontend if 1: shifter_bus = ShifterBus(6) @always_comb def shifter_comb(): shifter_sck.next = shifter_bus.SCK shifter_sdo.next = shifter_bus.SDO bu2506_ld.next = shifter_bus.CS[0] adf4360_le.next = shifter_bus.CS[1] adc08d500_cs.next = not shifter_bus.CS[2] lmh6518_cs.next[0] = not shifter_bus.CS[3] lmh6518_cs.next[1] = not shifter_bus.CS[4] dac8532_sync.next = not shifter_bus.CS[5] insts.append(shifter_comb) shifter = Shifter(spi_system, shifter_bus, divider = 100) addr = 0x210 for reg in shifter.create_regs(): mux.add(reg, addr) addr += 1 insts.append(shifter.gen()) trig = Signal(intbv(0)[len(trig_p):]) trig_inst = ibufds_vec('ibufds_trig', trig_p, trig_n, trig) insts.append(trig_inst) #################################################################### # Probe compensation output and external trigger output # Just toggle them at 1kHz probe_comb_div = 25000 probe_comp_ctr = Signal(intbv(0, 0, probe_comb_div)) probe_comp_int = Signal(False) @always_seq (spi_system.CLK.posedge, spi_system.RST) def probe_comp_seq(): if probe_comp_ctr == probe_comb_div - 1: probe_comp_int.next = not probe_comp_int probe_comp_ctr.next = 0 else: probe_comp_ctr.next = probe_comp_ctr + 1 insts.append(probe_comp_seq) @always_comb def probe_comp_comb(): probe_comp.next = probe_comp_int ext_trig_out.next = probe_comp_int insts.append(probe_comp_comb) #################################################################### # DDR memory using MIG mig_control_bus, mig_control_inst = mig.control_reg(soc_system) sm.add(mig_control_bus, addr = 0x200) insts.append(mig_control_inst) @always_comb def mig_soc_clk_inst(): soc_clk.next = mig.soc_clk soc_clk_b.next = mig.soc_clk_b insts.append(mig_soc_clk_inst) mig.mcbx_dram_addr = mcb3_dram_a mig.mcbx_dram_ba = mcb3_dram_ba mig.mcbx_dram_ras_n = mcb3_dram_ras_n mig.mcbx_dram_cas_n = mcb3_dram_cas_n mig.mcbx_dram_we_n = mcb3_dram_we_n mig.mcbx_dram_clk = mcb3_dram_ck mig.mcbx_dram_clk_n = mcb3_dram_ck_n mig.mcbx_dram_dq = mcb3_dram_dq mig.mcbx_dram_dqs = mcb3_dram_dqs mig.mcbx_dram_dqs_n = mcb3_dram_dqs_n mig.mcbx_dram_udqs = mcb3_dram_udqs mig.mcbx_dram_udqs_n = mcb3_dram_udqs_n mig.mcbx_dram_udm = mcb3_dram_udm mig.mcbx_dram_ldm = mcb3_dram_dm mig_inst = mig.gen() insts.append(mig_inst) #################################################################### # Finalize the SoC MUX sm.addr_depth = 32 * 1024 * 1024 sm_inst = sm.gen() insts.append(sm_inst) #################################################################### # SoC bus soc_bus = DdrBus(2, 12, 2) # Attach the MUX bus to the SoC bus soc_ddr = Ddr() soc_inst = soc_ddr.gen(soc_system, soc_bus, sm.bus()) insts.append(soc_inst) soc_connect_inst = ddr_connect( soc_bus, soc_clk, soc_clk_b, None, soc_cs, soc_ras, soc_cas, soc_we, soc_ba, soc_a, soc_dqs, soc_dm, soc_dq) insts.append(soc_connect_inst) if 1: soc_capture = Signal(False) soc_ctl = RegFile('soc_ctl', "SOC control", [ RwField(spi_system, 'soc_capture', "Capture samples", soc_capture), ]) mux.add(soc_ctl, 0x231) soc_capture_sync = Signal(False) soc_capture_sync_inst = syncro(soc_clk, soc_capture, soc_capture_sync) insts.append(soc_capture_sync_inst) soc_sdr = ConcatSignal( soc_a, soc_ba, soc_we, soc_cas, soc_ras, soc_cs) soc_sdr_sampler = Sampler(addr_depth = 0x800, sample_clk = soc_clk, sample_data = soc_sdr, sample_enable = soc_capture_sync) mux.add(soc_sdr_sampler, 0x2000) soc_reg = ConcatSignal( soc_bus.A, soc_bus.BA, soc_bus.WE_B, soc_bus.CAS_B, soc_bus.RAS_B, soc_bus.CS_B) soc_reg_sampler = Sampler(addr_depth = 0x800, sample_clk = soc_clk, sample_data = soc_reg, sample_enable = soc_capture_sync) mux.add(soc_reg_sampler, 0x2800) soc_ddr_0 = ConcatSignal(soc_bus.DQ1_OE, soc_bus.DQS1_O, soc_bus.DQS1_OE, soc_bus.DQ0_I, soc_bus.DM0_I, soc_bus.DQS0_I) soc_ddr_1 = ConcatSignal(soc_bus.DQ0_OE, soc_bus.DQS0_O, soc_bus.DQS0_OE, soc_bus.DQ1_I, soc_bus.DM1_I, soc_bus.DQS1_I) soc_ddr_sampler_0 = Sampler(addr_depth = 0x800, sample_clk = soc_clk, sample_data = soc_ddr_0, sample_enable = soc_capture_sync) mux.add(soc_ddr_sampler_0, 0x3000) soc_ddr_sampler_1 = Sampler(addr_depth = 0x800, sample_clk = soc_clk, sample_data = soc_ddr_1, sample_enable = soc_capture_sync) mux.add(soc_ddr_sampler_1, 0x3800) #################################################################### # Random stuff if 1: pins = ConcatSignal(cclk, i2c_sda, i2c_scl, ext_trig_out, probe_comp, ac_trig, ba7406_hd, ba7406_vd, trig, ref_clk, bank2) hc = HybridCounter() mux.add(hc, 0, pins) # I have a bug somewhere in my Mux, unless I add this the adc # sample buffer won't show up in the address range. I should fix # it but I haven't managed to figure out what's wrong yet. if 1: ram3 = Ram(addr_depth = 1024, data_width = 32) mux.add(ram3, 0x8000) wb_slave = mux # Create the wishbone bus wb_bus = wb_slave.create_bus() wb_bus.CLK_I = clk_buf wb_bus.RST_I = None # Create the SPI slave spi = SpiSlave() spi.addr_width = 32 spi.data_width = 32 wb_inst = wb_slave.gen(wb_bus) insts.append(wb_inst) slave_spi_inst = spi.gen(slave_spi_bus, wb_bus) insts.append(slave_spi_inst) return insts
def spi_slave_fifo(glbl, spibus, fifobus): """ This is an SPI slave peripheral, when the master starts clocking any data in the TX FIFO (fifobus.write) will be sent (the next byte) and the received byte will be copied to RX FIFO (fifobus.read). The `cso` interface can be used to configure how the SPI slave peripheral behaves. (Arguments == Ports) Arguments: glbl (Global): global clock and reset spibus (SPIBus): the external SPI interface fifobus (FIFOBus): the fifo interface cso (ControlStatus): the control status signals """ fifosize = 8 # Use an async FIFO to transfer from the SPI SCK clock domain and # the internal clock domain. This allows for high-speed SCK. clock, reset = glbl.clock, glbl.reset assert isinstance(spibus, SPIBus) assert isinstance(fifobus, FIFOBus) sck, csn = spibus.sck, spibus.csn # the FIFOs for the receive and transmit (external perspective) readpath = FIFOBus(width=fifobus.width) writepath = FIFOBus(width=fifobus.width) # the FIFO instances tx_fifo_inst = fifo_fast(glbl, writepath, size=fifosize) rx_fifo_inst = fifo_fast(glbl, readpath, size=fifosize) mp_fifo_inst = fifobus.assign_read_write_paths(readpath, writepath) spi_start = Signal(bool(0)) ireg, icap, icaps = Signals(intbv(0)[8:], 3) oreg, ocap = Signals(intbv(0)[8:], 2) bitcnt, b2, b3 = Signals(intbv(0, min=0, max=10), 3) @always(sck.posedge, csn.negedge) def csn_falls(): if sck: spi_start.next = False elif not csn: spi_start.next = True # SCK clock domain, this allows high SCK rates @always(sck.posedge, csn.posedge) def sck_capture_send(): if csn: b2.next = 0 bitcnt.next = 0 else: if bitcnt == 0 or spi_start: spibus.miso.next = ocap[7] oreg.next = (ocap << 1) & 0xFF else: spibus.miso.next = oreg[7] oreg.next = (oreg << 1) & 0xFF ireg.next = concat(ireg[7:0], spibus.mosi) bitcnt.next = bitcnt + 1 if bitcnt == (8-1): bitcnt.next = 0 b2.next = 8 icap.next = concat(ireg[7:0], spibus.mosi) else: b2.next = 0 # synchronize the SCK domain to the clock domain syncro(clock, icap, icaps) syncro(clock, b2, b3) gotit = Signal(bool(0)) @always(clock.posedge) def beh_io_capture(): # default no writes readpath.write.next = False writepath.read.next = False if b3 == 0: gotit.next = False elif b3 == 8 and not gotit: readpath.write.next = True readpath.write_data.next = icaps gotit.next = True ocap.next = writepath.read_data if not writepath.empty: writepath.read.next = True return myhdl.instances()
def gen(self): if self.RST is not None: wr_rst_inst = rst_sync(self.WR_CLK, self.RST, self.WR_RST) rd_rst_inst = rst_sync(self.RD_CLK, self.RST, self.RD_RST) mem = FifoMem(self.WR_CLK, self.RD_CLK, self.depth, len(self.WR_DATA)) mem_inst = mem.gen() gray_init = intbv(0, 0, 2 * self.depth) # Gray encoded write and read pointers wr_gray = Signal(gray_init) rd_gray = Signal(gray_init) ################################################################ # Write side of the FIFO wr_cur = Signal(gray_init) wr_new = Signal(gray_init) # Gray encoded read pointer synchronized to the write clock domain wr_sync_rd_gray = Signal(gray_init) wr_sync_inst = syncro(self.WR_CLK, rd_gray, wr_sync_rd_gray, num_sync_ff = 2) @always_comb def wr_new_comb(): wr_new.next = wr_cur if self.WR: wr_new.next = (wr_cur + 1) & ((1<<len(wr_new))-1) @always_comb def wr_data_comb(): mem.WR.next = 0 mem.WR_ADDR.next = wr_cur & ((1<<len(mem.WR_ADDR))-1) mem.WR_DATA.next = self.WR_DATA if self.WR: mem.WR.next = 1 @always_comb def wr_full_comb(): self.WR_FULL.next = 0 if gray_encode(wr_new ^ self.depth) == wr_sync_rd_gray: self.WR_FULL.next = 1 @always_seq(self.WR_CLK.posedge, self.WR_RST) def wr_seq(): wr_cur.next = wr_new wr_gray.next = gray_encode(wr_new) ################################################################ # Read side of the FIFO rd_cur = Signal(gray_init) rd_new = Signal(gray_init) # Gray encoded read pointer synchronized to the write clock domain rd_sync_wr_gray = Signal(gray_init) rd_sync_inst = syncro(self.RD_CLK, wr_gray, rd_sync_wr_gray, num_sync_ff = 2) @always_comb def rd_new_comb(): rd_new.next = rd_cur if self.RD: rd_new.next = (rd_cur + 1) & ((1<<len(rd_new))-1) @always_comb def rd_data_comb(): mem.RD.next = 1 mem.RD_ADDR.next = rd_new & ((1<<len(mem.RD_ADDR))-1) self.RD_DATA.next = mem.RD_DATA @always_comb def rd_empty_comb(): self.RD_EMPTY.next = 0 if gray_encode(rd_new) == rd_sync_wr_gray: self.RD_EMPTY.next = 1 @always_seq(self.RD_CLK.posedge, self.RD_RST) def rd_seq(): rd_cur.next = rd_new rd_gray.next = gray_encode(rd_new) return instances()