def _bench_fifo_ramp(): tbdut = fifo_ramp(clock, reset, regbus, fifobus, base_address=0x0000) tbrbor = regbus.interconnect() tbclk = clock.gen() asserr = Signal(bool(0)) @instance def tbstim(): print("start fifo ramp test") try: yield delay(100) yield reset.pulse(111) # verify an incrementing pattern over the fifobus yield regbus.writetrans(0x07, 2) # div of two yield regbus.readtrans(0x07) assert 2 == regbus.get_read_data() yield regbus.writetrans(0x00, 1) # enable yield regbus.readtrans(0x00) assert 1 == regbus.get_read_data(), "cfg reg write failed" # monitor the bus until ?? ramps Nramps, rr, timeout = 128, 0, 0 while rr < Nramps and timeout < (20*Nramps): cnt = 0 for ii, sh in enumerate((24, 16, 8, 0,)): yield delay(1000) yield regbus.readtrans(0x08+ii) cntpart = regbus.get_read_data() cnt = cnt | (cntpart << sh) print("{:<8d}: ramp count[{:<4d}, {:d}]: {:08X}, {:02X} - timeout {:d}".format( now(), rr, ii, cnt, cntpart, timeout)) timeout += 1 # @todo: add ramp check if cnt != rr or (timeout % 1000) == 0: print(" ramp {} {}".format(int(cnt), int(rr),)) rr = int(cnt) print("{}, {}, {}".format(Nramps, rr, timeout)) except AssertionError as err: asserr.next = True for _ in range(10): yield clock.posedge raise err raise StopSimulation # monitor the values from the fifo bus, it should # be a simple "ramp" increasing values _mask = 0xFF _cval = Signal(modbv(0, min=0, max=256)) @always(clock.posedge) def tbmon(): if fifobus.wr: assert _cval == fifobus.wdata _cval.next = _cval+1 return tbclk, tbdut, tbstim, tbmon, tbrbor
def testbench(vhdl_output_path=None): fxp = FixedDef(128, 8) reset = ResetSignal(0, active=0, async=False) clk = Signal(bool(0)) x = Signal(intbv(0)[fxp.width:]) y = Signal(intbv(0)[fxp.width:]) period = 10 # clk_gen = clk_stim(clk, period=10) low_time = int(period / 2) high_time = period - low_time @instance def drive_clk(): while True: yield delay(low_time) clk.next = 1 yield delay(high_time) clk.next = 0 @instance def reset_gen(): reset.next = 0 yield delay(10) yield clk.negedge reset.next = 1 # yield delay(10) # yield clk.negedge # reset.next = 0 @instance def write_stim(): yield reset.posedge yield clk.negedge x.next = fxp.to_fixed(60) yield clk.negedge for i in range(8): yield clk.negedge raise StopSimulation() # @instance # def read_stim(): # yield reset.posedge # yield delay(601) # yield clk.negedge # axis_sum.tready.next = 1 # while True: # yield clk.negedge # if axis_sum.tlast == 1: # break # # for i in range(10): # yield clk.negedge # raise StopSimulation() uut = tanh(clk, reset, x, y, dokladnosc=5, fxp=fxp) if vhdl_output_path is not None: uut.convert(hdl='VHDL', path=vhdl_output_path, initial_values=True) return instances()
def f(): (i for i in all_out).next = Signal(0) all_out[select].next = inp
def testBench(): pc_adder_in, data1_in, data2_in, address32_in = [Signal(intbv(random.randint(-255, 255), min=-(2**31), max=2**31-1)) for i in range(4)] pc_adder_out, data1_out, data2_out, address32_out = [Signal(intbv(0, min=-(2**31), max=2**31-1)) for i in range(4)] rs_in, rd_in, rt_in, rd_out, rt_out, rs_out, = [Signal(intbv(0)[5:]) for i in range(6)] func_in, func_out = [Signal(intbv(0)[6:]) for i in range(2)] RegDst_in, ALUop_in, ALUSrc_in = [Signal(intbv(0)[1:]) for i in range(3)] Branch_in, MemRead_in, MemWrite_in = [Signal(intbv(0)[1:]) for i in range(3)] RegWrite_in, MemtoReg_in = [Signal(intbv(0)[1:]) for i in range(2)] RegDst_out, ALUop_out, ALUSrc_out = [Signal(intbv(0)[1:]) for i in range(3)] Branch_out, MemRead_out, MemWrite_out = [Signal(intbv(0)[1:]) for i in range(3)] RegWrite_out, MemtoReg_out = [Signal(intbv(0)[1:]) for i in range(2)] clk = Signal(intbv(0)[1:]) rst = Signal(intbv(0)[1:]) latch_inst = toVHDL(latch_id_ex, clk, rst, pc_adder_in, data1_in, data2_in, address32_in, rs_in, rt_in, rd_in, func_in, RegDst_in, ALUop_in, ALUSrc_in, #signals to EX pipeline stage Branch_in, MemRead_in, MemWrite_in, #signals to MEM pipeline stage RegWrite_in, MemtoReg_in, #signals to WB pipeline stage pc_adder_out, data1_out, data2_out, address32_out, rs_out, rt_out, rd_out, func_out, RegDst_out, ALUop_out, ALUSrc_out, Branch_out, MemRead_out, MemWrite_out, RegWrite_out, MemtoReg_out) @instance def stimulus(): for i in range(5): if random.random() > 0.25: clk.next = 1 if random.random() > 0.75: rst.next = 1 pc_adder_in.next, data1_in.next, data2_in.next, address32_in.next = [intbv(random.randint(-255, 255)) for i in range(4)] rs_in.next, rd_in.next, rt_in.next, func_in.next = [intbv(random.randint(0, 15)) for i in range(4)] RegDst_in.next, ALUop_in.next, ALUSrc_in.next = [random.randint(0,1) for i in range(3)] Branch_in.next , MemRead_in.next , MemWrite_in.next = [random.randint(0,1) for i in range(3)] RegWrite_in.next , MemtoReg_in.next = [random.randint(0,1) for i in range(2)] yield delay(1) print ("-" * 79) print ("%i %i %i | %i %i %i | %i | %i %i %i %i %i %i %i %i " % ( data1_in, data2_in, address32_in, rs_in, rt_in, rd_in, func_in, RegDst_in, ALUop_in, ALUSrc_in, Branch_in, MemRead_in, MemWrite_in, RegWrite_in, MemtoReg_in)) print ("clk: %i rst: %i " % (clk, rst)) print ("%i %i %i | %i %i %i | %i | %i %i %i %i %i %i %i %i " % ( data1_out, data2_out, address32_out, rs_out, rt_out, rd_out, func_out, RegDst_out, ALUop_out, ALUSrc_out, Branch_out, MemRead_out, MemWrite_out, RegWrite_out, MemtoReg_out)) clk.next = 0 rst.next = 0 yield delay(1) return instances()
def bench_fifo_mem_rand(): nloops = 100 w = width = 8 wmax = 2**width # random data and addresses for test rand_data = tuple([randint(0, wmax - 1) for _ in range(nloops)]) rand_addr = tuple([randint(0, wmax - 1) for _ in range(nloops)]) clock, write, read = Signals(bool(0), 3) write_data, write_addr, read_data, read_addr = Signals(intbv(0)[w:0], 4) wad = Signal(write_addr.val) tbdut = fifo_mem(clock, write, write_data, write_addr, clock, read, read_data, read_addr, wad) @instance def tbclkw(): clock.next = False while True: yield delay(5) clock.next = not clock @instance def tbstim(): print("start sim") write.next = False write_data.next = 0 write_addr.next = 0 read.next = False read_addr.next = 0 print("delay some") yield delay(10) for ii in range(5): yield clock.posedge for ii in range(wmax): write.next = True write_data.next = 0 yield clock.posedge write.next = False print("write loop") for ii in range(nloops): write.next = True write_data.next = rand_data[ii] write_addr.next = rand_addr[ii] read_addr.next = wad yield clock.posedge write.next = False for jj in range(3): yield clock.posedge print("%d %d %d %d" % (write_addr, write_data, read_addr, read_data)) write.next = False print("read loop") for ii in range(nloops): write_data.next = rand_data[ii] write_addr.next = rand_addr[ii] read_addr.next = rand_addr[ii] yield clock.posedge print("%d %d %d %d" % (write_addr, write_data, read_addr, read_data)) write.next = False yield clock.posedge print("end sim") raise StopSimulation return myhdl.instances()
sel -- control input: select a if asserted, otherwise b """ @always_comb def muxLogic(): if sel == 1: z.next = a else: z.next = b return muxLogic from random import randrange z, a, b, sel = [Signal(0) for i in range(4)] mux_1 = Mux(z, a, b, sel) def test(): print "z a b sel" for i in range(8): a.next, b.next, sel.next = randrange(8), randrange(8), randrange(2) yield delay(10) print "%s %s %s %s" % (z, a, b, sel) test_1 = test()
import sys import os sys.path.append( os.path.abspath("../../src/") ) import myhdl from myhdl import block, Signal, intbv from ClkDriver import ClkDriver #from fpga25_snip4 import led_stroby from shift import shift num_led = 8 clock = Signal(False) leds = Signal(intbv(0)[num_led:]) @block def test_shifter(clock,leds): clkdrv = ClkDriver(clock, period=10) tbdut = shift(clock, leds, num_led=num_led, cnt_max=5) return tbdut, clkdrv @block def shifter(clock,leds): tbdut = shift(clock, leds, num_led) return tbdut if "--test" in str(sys.argv): do_test=True else: do_test=False
def fun(): clk = Signal(bool(0)) inst = gen(clk) return inst
def dummy(): clk = Signal(bool(0)) inst = gen(clk) return 1
def fifo_fast(clock, reset, fbus, use_srl_prim=False): """ Often small simple, synchronous, FIFOs can be implemented with specialized hardware in an FPGA (e.g. vertically chaining LUTs). This FIFO is intended to be used for small fast FIFOs. But when used for large ... This FIFO is a small FIFO (currently fixed to 16) that is implemented to take advantage of some hardware implementations. Typical FPGA synthesis will infer shift-register-LUT (SRL) for small synchronous FIFOs. This FIFO is implemented generically, consult the synthesis and map reports. PORTS ===== PARAMETERS ========== use_slr_prim: this parameter indicates to use the SRL primitive (inferrable primitive). If SRL are not inferred from the generic description this option can be used. Note, srl_prim will only use a size (FIFO depth) of 16. """ # @todo: this is intended to be used for small fast fifo's but it # can be used for large synchronous fifo as well N = 32 # default and max size if use_srl_prim: N = 16 elif fbus.size > N: print("@W: m_fifo_fast only supports size < %d, for fast" % (N)) print(" forcing size (depth) to %d" % (N)) else: N = fbus.size mem = [Signal(intbv(0)[fbus.width:]) for _ in range(N)] addr = Signal(intbv(0, min=0, max=N)) # aliases to the FIFO bus interface srlce = fbus.wr # single cycle write # note: use_srl_prim has not been tested! # note: signal slices wdata() will need to be used instead of # bit slices wsdata[]. Have add if use_srl_prim: gsrl = [None for _ in range(N)] for ii in range(N): gsrl[ii] = fifo_srl(clock, fbus.wdata(ii), fbus.wr, addr, fbus.rdata(ii)) else: # the SRL based FIFO always writes to address 0 and shifts # the FIFO, only a read address is accounted. @always(clock.posedge) def rtl_srl_in(): if srlce: mem[0].next = fbus.wdata for ii in range(1, N): mem[ii].next = mem[ii - 1] @always_comb def rtl_srl_out(): fbus.rdata.next = mem[addr] @always_comb def rtl_vld(): fbus.rvld.next = fbus.rd # no delay on reads # the address is the read address, the write address is always # zero but on a write all values are shifted up one index, only # the read address is accounted in the following. @always_seq(clock.posedge, reset=reset) def rtl_fifo(): if fbus.clear: addr.next = 0 fbus.empty.next = True fbus.full.next = False elif fbus.rd and not fbus.wr: fbus.full.next = False if addr == 0: fbus.empty.next = True else: addr.next = addr - 1 elif fbus.wr and not fbus.rd: fbus.empty.next = False if not fbus.empty: addr.next = addr + 1 if addr == N - 2: fbus.full.next = True # nothing happens if read and write at the same time # note: failures occur if write/read when full/empty respectively nvacant = Signal(intbv(N, min=0, max=N + 1)) # # empty slots ntenant = Signal(intbv(0, min=0, max=N + 1)) # # filled slots @always_seq(clock.posedge, reset=reset) def rtl_occupancy(): if fbus.clear: nvacant.next = N ntenant.next = 0 elif fbus.rd and not fbus.wr: nvacant.next = nvacant + 1 ntenant.next = ntenant - 1 elif fbus.wr and not fbus.rd: nvacant.next = nvacant - 1 ntenant.next = ntenant + 1 @always_comb def rtl_count(): fbus.count.next = ntenant gens = ( rtl_srl_in, rtl_srl_out, rtl_vld, rtl_fifo, rtl_occupancy, rtl_count, ) return gens
def CPU(): # the main block which will connect all of our blocks ''' creating the nessecry signal to connect the blocks ''' enable, enable2, clock, RestClk, MEMread, MEMwrite, REGwrite, PCSrc, ALUMUXsig, MEMtoREG, zero, Branch = [ Signal(bool(0)) for i in range(12) ] instructionIN = Signal(intbv(0)[32:]) PCsignal = Signal(intbv(0, min=-1024)) PC_Mux_result = Signal(intbv(0, min=-1024)) PC_Branch_result = Signal(intbv(0, min=-1024)) PC_adder_result = Signal(intbv(0, min=-1024)) instruction = Signal(intbv(0)) rs1OUT, rs2OUT = [ Signal(intbv(0, min=-2**31, max=2**31)) for i in range(2) ] rd, rs1, rs2, ALUsig, MEMsignal = [Signal(intbv(0)[5:]) for i in range(5)] Mux_RB_result = Signal(intbv(0, min=-2**31, max=2**31)) imm = Signal(intbv(0, min=-2**31, max=2**31)) Mux_ALUsrc_result = Signal(intbv(0, min=-2**31, max=2**31)) ALUoutput = Signal(intbv(0, min=-2**31, max=2**31)) MEMoutput = Signal(intbv(0, min=-2**31, max=2**31)) PCclk = Signal(bool(0)) counter = Signal(intbv(0)) '''a clock specified for the PC to slow the process of sending an instruction (to prevent pipelining )''' @always(delay(25)) def clockGENpc(): PCclk.next = not PCclk '''a faster clock for the instructions ''' @always(delay(5)) def clockGEN(): if counter == 4: RestClk.next = 1 counter.next = 0 enable2.next = 1 else: RestClk.next = 0 counter.next = counter + 1 clock.next = not clock PCSrc.next = ( Branch & zero ) # an and gate updated by each clock to determine if the branch is taken or not '''<----------------------------connecting the blocks----------------------->''' PC_driver = pc(PCclk, PC_Mux_result, enable, PCsignal) Adder = adder(PCsignal, PC_adder_result) Adder_Branch = BranchAdder(PCsignal, imm, PC_Branch_result) Mux_pc = mux(PC_Mux_result, PC_adder_result, PC_Branch_result, PCSrc) Instruction_MEM = inst_memory(clock, enable, PCsignal, instructionIN, instruction, RestClk) DECODE = decoder(instruction, rs1, rs2, rd, imm) CONTROL = ControlUnit(instruction, ALUsig, ALUMUXsig, REGwrite, Branch, MEMwrite, MEMtoREG, MEMread, MEMsignal, clock, enable2, RestClk) Regsters = RegisterFile(rs1, rs2, rd, rs1OUT, rs2OUT, REGwrite, Mux_RB_result, clock, enable2, RestClk) Mux_ALUsrc = mux(Mux_ALUsrc_result, rs2OUT, imm, ALUMUXsig) Perform_operations = ALU(rs1OUT, Mux_ALUsrc_result, ALUsig, ALUoutput, zero, PCsignal) MEMaccess = MainMemory(ALUoutput, rs2OUT, MEMoutput, MEMwrite, MEMread, MEMsignal, clock, RestClk) Mux_RB = mux(Mux_RB_result, ALUoutput, MEMoutput, MEMtoREG) @instance def stimulate(): '''<---------------------start load the instructions into the instruction memory-------------------->''' enable.next = 0 # 1 instructionIN.next = 0b00011111010000000000001110010011 yield PCclk.posedge # 2 instructionIN.next = 0b00000000000000000000010110010011 yield PCclk.posedge # 3 instructionIN.next = 0b00000000000100000000011000010011 yield PCclk.posedge # 4 instructionIN.next = 0b00011111010000000000001100010011 yield PCclk.posedge # 5 instructionIN.next = 0b00000000101101100000011000110011 yield PCclk.posedge # 6 instructionIN.next = 0b00000000110000110010001000100011 yield PCclk.posedge # 7 instructionIN.next = 0b00000000010000110000001100010011 yield PCclk.posedge # 8 instructionIN.next = 0b00000000000101011000010110010011 yield PCclk.posedge # 9 instructionIN.next = 0b11111110011101011100100011100011 yield PCclk.posedge # 10 instructionIN.next = 0b00011111010000000000001100010011 yield PCclk.posedge # 11 instructionIN.next = 0b00000000110000110010000000100011 yield PCclk.posedge # 12 instructionIN.next = 0b00000000000000110010010100000011 yield PCclk.posedge '''<------------------------done loading the instructions ------------------------>''' enable.next = 1 # enable the the instructions memory and the PC to start running yield clock.negedge while True: # a while loop to print each instruction when it's executing print('time: ', now(), 'PC---->', int(PCsignal)) print( '_________________________________________________________________' '_______________________________________________________________________________' ) print( '\nthe instruction is : %s ||operands: rd: x%d , rs1: x%d , rs2: x%d , imm: %d ' % (bin(instruction, 32), int(rd), int(rs1), int(rs2), int(imm))) print( 'the signals are : ALUsignal: %s | ALUMUXsig: %s | REGwrite: %s | PCSrc: %s ' '| MEMwrite: %s | MEMtoREG: %s | MEMread: %s | MEMsignal: %s ' % (bin(ALUsig, 5), bin(ALUMUXsig, 1), bin(REGwrite, 1), bin(PCSrc, 1), bin(MEMwrite, 1), bin( MEMtoREG, 6), bin(MEMread, 1), bin(MEMsignal, 3))) print('PC Equals: ', int(PCsignal)) print( '______________________________________________________________________________________' '__________________________________________________________') yield PCclk.negedge return instances()
def sim_streaming_chain_mult(pars_obj): global rxdata_filename global txdata0_filename global txdata1_filename # removing the files if already available for i in range(NB_CHAIN_MULTIPLIERS): txdata0_filename[i] = "transmit_data_inpA_mult{:d}.log".format(i) if (os.path.exists(txdata0_filename[i])): os.remove(txdata0_filename[i]) txdata1_filename[i] = "transmit_data_inpB_mult{:d}.log".format(i) if (os.path.exists(txdata1_filename[i])): os.remove(txdata1_filename[i]) if (os.path.exists(rxdata_filename)): os.remove(rxdata_filename) reset = Signal(bool(1)) clk = Signal(bool(0)) elapsed_time = Signal(0) nb_transmit = [Signal(int(0)) for i in range(NB_CHAIN_MULTIPLIERS)] nb_transmit0 = [Signal(int(0)) for i in range(NB_CHAIN_MULTIPLIERS)] nb_transmit1 = [Signal(int(0)) for i in range(NB_CHAIN_MULTIPLIERS)] nb_receive = Signal(int(0)) av_src0_bfm = [ AvalonST_SRC(STREAM_DATA_WIDTH) for i in range(NB_CHAIN_MULTIPLIERS) ] av_src1_bfm = [ AvalonST_SRC(STREAM_DATA_WIDTH) for i in range(NB_CHAIN_MULTIPLIERS) ] av_snk0 = [ AvalonST_SNK(STREAM_DATA_WIDTH) for i in range(NB_CHAIN_MULTIPLIERS) ] av_snk1 = [ AvalonST_SNK(STREAM_DATA_WIDTH) for i in range(NB_CHAIN_MULTIPLIERS) ] av_snk_bfm = AvalonST_SNK(STREAM_DATA_WIDTH) src_bfm_i = [ AvalonST_SNK(STREAM_DATA_WIDTH) for i in range(NB_CHAIN_MULTIPLIERS) ] src_bfm_0 = [ AvalonST_SNK(STREAM_DATA_WIDTH) for i in range(NB_CHAIN_MULTIPLIERS) ] src_bfm_1 = [ AvalonST_SNK(STREAM_DATA_WIDTH) for i in range(NB_CHAIN_MULTIPLIERS) ] src_bfm_o = AvalonST_SRC(STREAM_DATA_WIDTH) clkgen = clk_driver(elapsed_time, clk, period=20) src0_bfm_inst = [None for i in range(NB_CHAIN_MULTIPLIERS)] src1_bfm_inst = [None for i in range(NB_CHAIN_MULTIPLIERS)] snk_bfm_inst = None VALID_PATTERN0 = [ random.randint(0x0100, 0xffff) for i in range(NB_CHAIN_MULTIPLIERS) ] VALID_PATTERN1 = [ random.randint(0x0100, 0xffff) for i in range(NB_CHAIN_MULTIPLIERS) ] READY_PATTERN = [ random.randint(0x0100, 0xffff) for i in range(NB_CHAIN_MULTIPLIERS) ] for i in range(NB_CHAIN_MULTIPLIERS): print("Chain Mult: " + str(i) + " Valid0: " + str(VALID_PATTERN0[i]) + " Valid1: " + str(VALID_PATTERN1[i]) + " Ready: " + str(READY_PATTERN[i])) src0_bfm_inst[i] = src_bfm(reset, clk, VALID_PATTERN0[i], src_bfm_0[i], av_src0_bfm[i]) src1_bfm_inst[i] = src_bfm(reset, clk, VALID_PATTERN1[i], src_bfm_1[i], av_src1_bfm[i]) snk_bfm_inst = snk_bfm(reset, clk, READY_PATTERN[0], av_snk_bfm, src_bfm_o) i = NB_CHAIN_MULTIPLIERS * 2 nb_chain_mults = 0 nb_chain_mults_list = [] mod_list = [] nb_mult_stages = 0 while i > 1: mod_val = 0 if (i % 2 == 0 or i == 1) else 1 mod_list.append(mod_val) i = i / 2 if (i % 2 == 0) else i / 2 + 1 nb_chain_mults += i nb_chain_mults_list.append(i) nb_mult_stages += 1 print("nb_chain_mults: " + str(nb_chain_mults)) print("nb_mult_stages: " + str(nb_mult_stages)) print("mod_list: " + str(mod_list)) print("nb_chain_mults_list: " + str(nb_chain_mults_list)) av_snk0_cmb = [[ AvalonST_SNK(STREAM_DATA_WIDTH) for i in range(NB_CHAIN_MULTIPLIERS) ] for j in range(nb_mult_stages)] av_snk1_cmb = [[ AvalonST_SNK(STREAM_DATA_WIDTH) for i in range(NB_CHAIN_MULTIPLIERS) ] for j in range(nb_mult_stages)] av_src = [[ AvalonST_SRC(STREAM_DATA_WIDTH) for i in range(NB_CHAIN_MULTIPLIERS) ] for j in range(nb_mult_stages)] snk0_valid_inst = [None for i in range(NB_CHAIN_MULTIPLIERS)] snk0_data_inst = [None for i in range(NB_CHAIN_MULTIPLIERS)] snk0_ready_inst = [None for i in range(NB_CHAIN_MULTIPLIERS)] snk1_valid_inst = [None for i in range(NB_CHAIN_MULTIPLIERS)] snk1_data_inst = [None for i in range(NB_CHAIN_MULTIPLIERS)] snk1_ready_inst = [None for i in range(NB_CHAIN_MULTIPLIERS)] src_valid_inst = None src_data_inst = None src_ready_inst = None streaming_chain_mult_inst = [None for i in range(nb_mult_stages)] add_i = [None for i in range(nb_mult_stages)] add_pars = [None for i in range(nb_mult_stages)] snk0_inst = [] snk1_inst = [] for i in range(nb_mult_stages): add_pars[i] = StreamingChainMultPars() add_pars[i].SNK0_DATAWIDTH = STREAM_DATA_WIDTH add_pars[i].SNK1_DATAWIDTH = STREAM_DATA_WIDTH add_pars[i].SRC_DATAWIDTH = STREAM_DATA_WIDTH add_pars[i].NB_CHAIN_MULTIPLIERS = NB_CHAIN_MULTIPLIERS add_pars[i](add_pars[i]) add_i[i] = StreamingChainMult() if (i != 0 and i <= nb_mult_stages - 1): for j in range(nb_chain_mults_list[i]): k = j * 2 snk0_inst.append( simple_wire_assign(av_snk0_cmb[i][j].valid_i, av_src[i - 1][k].valid_o)) snk0_inst.append( simple_wire_assign(av_snk0_cmb[i][j].data_i, av_src[i - 1][k].data_o)) snk0_inst.append( simple_wire_assign(av_src[i - 1][k].ready_i, av_snk0_cmb[i][j].ready_o)) if (mod_list[i] == 1 and j == (nb_chain_mults_list[i]) - 1): snk1_inst.append( simple_wire_assign(av_snk1_cmb[i][j].valid_i, Signal(1))) snk1_inst.append( simple_wire_assign(av_snk1_cmb[i][j].data_i, Signal(1))) snk1_inst.append( simple_wire_assign(Signal(1), av_snk1_cmb[i][j].ready_o)) else: snk1_inst.append( simple_wire_assign(av_snk1_cmb[i][j].valid_i, av_src[i - 1][k + 1].valid_o)) snk1_inst.append( simple_wire_assign(av_snk1_cmb[i][j].data_i, av_src[i - 1][k + 1].data_o)) snk1_inst.append( simple_wire_assign(av_src[i - 1][k + 1].ready_i, av_snk1_cmb[i][j].ready_o)) elif (i == 0): for k in range(NB_CHAIN_MULTIPLIERS): snk0_valid_inst[k] = simple_wire_assign( av_snk0_cmb[0][k].valid_i, av_src0_bfm[k].valid_o) snk0_data_inst[k] = simple_wire_assign( av_snk0_cmb[0][k].data_i, av_src0_bfm[k].data_o) snk0_ready_inst[k] = simple_wire_assign( av_src0_bfm[k].ready_i, av_snk0_cmb[0][k].ready_o) snk1_valid_inst[k] = simple_wire_assign( av_snk1_cmb[0][k].valid_i, av_src1_bfm[k].valid_o) snk1_data_inst[k] = simple_wire_assign( av_snk1_cmb[0][k].data_i, av_src1_bfm[k].data_o) snk1_ready_inst[k] = simple_wire_assign( av_src1_bfm[k].ready_i, av_snk1_cmb[0][k].ready_o) streaming_chain_mult_inst[i] = add_i[i].block_connect( add_pars[i], reset, clk, av_snk0_cmb[i], av_snk1_cmb[i], av_src[i]) src_valid_inst = simple_wire_assign(av_snk_bfm.valid_i, av_src[nb_mult_stages - 1][0].valid_o) src_data_inst = simple_wire_assign(av_snk_bfm.data_i, av_src[nb_mult_stages - 1][0].data_o) src_ready_inst = simple_wire_assign(av_src[nb_mult_stages - 1][0].ready_i, av_snk_bfm.ready_o) @always(clk.posedge) def stimulus(): if elapsed_time == 40: reset.next = 0 INIT_DATA0 = [ random.randint(1, RANDRANGE) for i in range(NB_CHAIN_MULTIPLIERS) ] INIT_DATA1 = [ random.randint(1, RANDRANGE) for i in range(NB_CHAIN_MULTIPLIERS) ] data_in0 = [Signal(int(0)) for i in range(NB_CHAIN_MULTIPLIERS)] data_in1 = [Signal(int(0)) for i in range(NB_CHAIN_MULTIPLIERS)] src_bfm_0_valid_inst = [] src_bfm_1_valid_inst = [] src_bfm_0_data_inst = [] src_bfm_1_data_inst = [] for i in range(NB_CHAIN_MULTIPLIERS): src_bfm_0_data_inst.append( conditional_wire_assign( src_bfm_0[i].data_i, (av_src0_bfm[i].ready_i and av_src0_bfm[i].valid_o), data_in0[i], src_bfm_0[i].data_i)) src_bfm_1_data_inst.append( conditional_wire_assign( src_bfm_1[i].data_i, (av_src1_bfm[i].ready_i and av_src1_bfm[i].valid_o), data_in1[i], src_bfm_1[i].data_i)) for i in range(NB_CHAIN_MULTIPLIERS): src_bfm_0_valid_inst.append( conditional_wire_assign_lt(src_bfm_0[i].valid_i, nb_transmit0[i], Signal(MAX_NB_TRANSFERS), 1, 0)) src_bfm_1_valid_inst.append( conditional_wire_assign_lt(src_bfm_1[i].valid_i, nb_transmit1[i], Signal(MAX_NB_TRANSFERS), 1, 0)) data_in0_inst = [] data_in1_inst = [] nb_transmit0_inst = [] nb_transmit1_inst = [] transmit_data0_append_inst = [] transmit_data1_append_inst = [] receive_data_append_inst = [] for i in range(NB_CHAIN_MULTIPLIERS): data_in0_inst.append( conditional_random_generator( reset, clk, data_in0[i], int(INIT_DATA0[i]), (av_src0_bfm[i].ready_i and av_src0_bfm[i].valid_o and src_bfm_0[i].valid_i), RANDRANGE)) data_in1_inst.append( conditional_random_generator( reset, clk, data_in1[i], int(INIT_DATA1[i]), (av_src1_bfm[i].ready_i and av_src1_bfm[i].valid_o and src_bfm_1[i].valid_i), RANDRANGE)) nb_transmit0_inst.append( conditional_reg_counter( reset, clk, nb_transmit0[i], Reset.LOW, (av_src0_bfm[i].ready_i and av_src0_bfm[i].valid_o and src_bfm_0[i].valid_i))) nb_transmit1_inst.append( conditional_reg_counter( reset, clk, nb_transmit1[i], Reset.LOW, (av_src1_bfm[i].ready_i and av_src1_bfm[i].valid_o and src_bfm_1[i].valid_i))) transmit_data0_append_inst.append( conditional_clocked_appendfile( reset, clk, (av_src0_bfm[i].ready_i and av_src0_bfm[i].valid_o and src_bfm_0[i].valid_i), data_in0[i], txdata0_filename[i])) transmit_data1_append_inst.append( conditional_clocked_appendfile( reset, clk, (av_src1_bfm[i].ready_i and av_src1_bfm[i].valid_o and src_bfm_1[i].valid_i), data_in1[i], txdata1_filename[i])) receive_data_append_inst.append( conditional_clocked_appendfile(reset, clk, (src_bfm_o.valid_o), src_bfm_o.data_o, rxdata_filename)) recv_inst = None recv_inst = conditional_reg_counter(reset, clk, nb_receive, Reset.LOW, src_bfm_o.valid_o) @always(clk.posedge) def receive_data_process(): TIME_SHUTDOWN = 5000 nb_recv = 0 sim_time_now = now() nb_recv += nb_receive if (nb_recv == (MAX_NB_TRANSFERS)): print("INF242: Num ready pulses: " + str(int(ready_pulses))) raise StopSimulation("Simulation Finished in %d clks: In total " % now() + str(nb_recv) + " data words received") @always(clk.posedge) def simulation_time_check(): sim_time_now = now() if (sim_time_now > MAX_SIM_TIME): raise StopSimulation( "Warning! Simulation Exited upon reaching max simulation time of " + str(MAX_SIM_TIME) + " clocks") ready_pulse_cnt_inst = None ready_pulse_cnt_inst = conditional_reg_counter(reset, clk, ready_pulses, Reset.LOW, (av_snk_bfm.ready_o)) return instances()
import random # for randomized test #from __future__ import print_function MAX_NB_TRANSFERS = 10 NB_CHAIN_MULTIPLIERS = 5 STREAM_DATA_WIDTH = 32 RANDRANGE = pow(2, 3) - 1 # Maximum value allowed is 2^15-1 for avoiding overflow MAX_SIM_TIME = 100000 txdata0_filename = ["" for i in range(NB_CHAIN_MULTIPLIERS)] txdata1_filename = ["" for i in range(NB_CHAIN_MULTIPLIERS)] rxdata_filename = "receive_data.log" ready_pulses = [Signal(int(0)) for i in range(NB_CHAIN_MULTIPLIERS)] ready_pulses0 = [Signal(int(0)) for i in range(NB_CHAIN_MULTIPLIERS)] ready_pulses1 = [Signal(int(0)) for i in range(NB_CHAIN_MULTIPLIERS)] ready_pulses = Signal(int(0)) def sim_streaming_chain_mult(pars_obj): global rxdata_filename global txdata0_filename global txdata1_filename # removing the files if already available for i in range(NB_CHAIN_MULTIPLIERS): txdata0_filename[i] = "transmit_data_inpA_mult{:d}.log".format(i) if (os.path.exists(txdata0_filename[i])): os.remove(txdata0_filename[i])
def lt24lcd(glbl, vmem, lcd): """ A video display driver for the terasic LT24 LCD display. This driver reads pixels from the VideoMemory interface and transfers them to the LT24 display. This hardware module (component) will also perform the initial display configuration. Ports: glbl (Global): global signals, clock, reset, enable, etc. vmem (VideoMemory): video memory interface, the driver will read pixels from this interface. lcd (LT24Interface): The external LT24 interface. Parameters: None RGB 5-6-5 (8080-system 16bit parallel bus) """ assert isinstance(lcd, LT24Interface) resolution, refresh_rate = (240, 320), 60 number_of_pixels = resolution[0] * resolution[1] # local references to signals in interfaces clock, reset = glbl.clock, glbl.reset # make sure the user timer is configured assert glbl.tick_user is not None # write out a new VMEM to the LCD display, a write cycle # consists of putting the video data on the bus and latching # with the `wrx` signal. Init (write once) the column and # page addresses (cmd = 2A, 2B) then write mem (2C) states = enum( 'init_wait_reset', # wait for the controller to reset the LCD 'init_start', # start the display init sequence 'init_start_cmd', # send a command, port of the display seq 'init_next', # determine if another command 'write_cmd_start', # command subroutine 'write_cmd', # command subroutine 'display_update_start', # update the display 'display_update_start_p', # delay for command ack 'display_update', # update the display 'display_update_next', # wait for driver to ack pixel xfered 'display_update_end' # end of display update ) state = Signal(states.init_wait_reset) state_prev = Signal(states.init_wait_reset) cmd = Signal(intbv(0)[8:]) return_state = Signal(states.init_wait_reset) num_hor_pxl, num_ver_pxl = resolution print("resolution {}x{} = {} number of pixes".format( num_hor_pxl, num_ver_pxl, number_of_pixels)) hcnt = intbv(0, min=0, max=num_hor_pxl) vcnt = intbv(0, min=0, max=num_ver_pxl) # signals to start a new command transaction to the LCD datalen = Signal(intbv(0, min=0, max=number_of_pixels + 1)) data = Signal(intbv(0)[16:]) datasent = Signal(bool(0)) datalast = Signal(bool(0)) cmd_in_progress = Signal(bool(0)) # -------------------------------------------------------- # LCD driver gdrv = lt24lcd_driver(glbl, lcd, cmd, datalen, data, datasent, datalast, cmd_in_progress) # -------------------------------------------------------- # build the display init sequency ROM rom, romlen, maxpause = build_init_rom(init_sequence) offset = Signal(intbv(0, min=0, max=romlen + 1)) pause = Signal(intbv(0, min=0, max=maxpause + 1)) # -------------------------------------------------------- # state-machine @always_seq(clock.posedge, reset=reset) def rtl_state_machine(): state_prev.next = state if state == states.init_wait_reset: if lcd.reset_complete: state.next = states.init_start elif state == states.init_start: v = rom[offset] # @todo: change the table to only contain the number of # @todo: bytes to be transferred datalen.next = v - 3 p = rom[offset + 1] pause.next = p offset.next = offset + 2 state.next = states.init_start_cmd elif state == states.init_start_cmd: v = rom[offset] cmd.next = v if datalen > 0: v = rom[offset + 1] data.next = v offset.next = offset + 2 else: offset.next = offset + 1 state.next = states.write_cmd_start return_state.next = states.init_next elif state == states.init_next: if pause == 0: if offset == romlen: state.next = states.display_update_start else: state.next = states.init_start elif glbl.tick_ms: pause.next = pause - 1 elif state == states.write_cmd_start: state.next = states.write_cmd elif state == states.write_cmd: if cmd_in_progress: if datasent and not datalast: v = rom[offset] data.next = v offset.next = offset + 1 else: cmd.next = 0 state.next = return_state elif state == states.display_update_start: if glbl.tick_user: cmd.next = 0x2C state.next = states.display_update_start_p datalen.next = number_of_pixels elif state == states.display_update_start_p: state.next = states.display_update elif state == states.display_update: assert cmd_in_progress if vcnt == num_ver_pxl - 1: hcnt[:] = 0 vcnt[:] = 0 elif hcnt == num_hor_pxl - 1: hcnt[:] = 0 vcnt[:] = vcnt + 1 else: hcnt[:] = hcnt + 1 # this will be the pixel for the next write cycle vmem.hpxl.next = hcnt vmem.vpxl.next = vcnt # this is the pixel for the current write cycle if hcnt == 0 and vcnt == 0: cmd.next = 0 state.next = states.display_update_end else: data.next = concat(vmem.red, vmem.green, vmem.blue) state.next = states.display_update_next elif state == states.display_update_next: if cmd_in_progress: if datasent and not datalast: state.next = states.display_update else: cmd.next = 0 state.next = states.display_update_end elif state == states.display_update_end: # wait till the driver ack the command completion if not cmd_in_progress: state.next = states.display_update_start return gdrv, rtl_state_machine
def gain_corrector(clearn, clock, gain_i, gain_q, in_sign, out_sign): """Analog quadrature gain corrector. Lets you correct for gain imbalance with an AQM. :param clearn: The reset signal. :param clock: The clock. :param correct_i: An intbv to add to multiply each sample's i channel by. :param correct_q: An intbv to add to multiply each sample's q channel by. :param in_sign: The incomming signature. :param out_sign: The outgoing signature. :returns: A synthesizable MyHDL instance. """ in_valid = in_sign.valid in_last = in_sign.last in_i = in_sign.i in_q = in_sign.q out_valid = out_sign.valid out_last = out_sign.last out_i = out_sign.i out_q = out_sign.q s = len(in_i) + len(gain_i) mul_i = Signal(intbv(0, min=-2**s, max=2**s)) mul_q = Signal(intbv(0, min=-2**s, max=2**s)) mul_valid = Signal(bool(False)) mul_last = Signal(bool(False)) @always_seq(clock.posedge, reset=clearn) def gain_correct(): if in_valid: mul_valid.next = in_valid mul_last.next = in_last #print 'i', ia.signed()/2.**9, '*', ix.signed() / float(ix.max), '=', ia.signed()/2**9 * (ix.signed() / float(ix.max)) mul_i.next = in_i.signed() * concat(bool(0), gain_i).signed() mul_q.next = in_q.signed() * concat(bool(0), gain_q).signed() else: mul_valid.next = False mul_last.next = False mul_i.next = 0 mul_q.next = 0 if mul_valid: out_valid.next = mul_valid out_last.next = mul_last #print 'm', mul_q[len(mul_q)-2] ^ mul_q[len(mul_q)-3] out_i.next = mul_i[len(mul_i) - 2:len(mul_i) - len(out_i) - 2].signed() out_q.next = mul_q[len(mul_q) - 2:len(mul_q) - len(out_q) - 2].signed() else: out_valid.next = False out_last.next = False out_i.next = 0 out_q.next = 0 return gain_correct
def get_nibbles(n): return [Signal(intbv(0)[4:]) for i in range(n)]
from myhdl._compat import to_bytes from myhdl._Cosimulation import Cosimulation, CosimulationError, _error from utils import raises_kind random.seed(1) # random, but deterministic MAXLINE = 4096 exe = "python {0} ".format(os.path.abspath(__file__)) fromSignames = ['a', 'bb', 'ccc'] fromSizes = [1, 11, 63] fromVals = [0x2, 0x43, 0x24] fromSigs = {} for s, v in zip(fromSignames, fromVals): fromSigs[s] = Signal(v) toSignames = ['d', 'ee', 'fff', 'g'] toSizes = [32, 12, 3, 6] toSigs = {} for s in toSignames: toSigs[s] = Signal(0) toVals = [0x3, 0x45, 0x14, 0x12] toXVals = ["X00", "FZ3", "34XZ", "56U"] allSigs = fromSigs.copy() allSigs.update(toSigs) class TestCosimulation: def setup_method(self, method): gc.collect()
def rfe( resetn, pclk, paddr, psel, penable, pwrite, pwdata, pready, prdata, #pslverr, clearn, clear_enable, loopen, tx_status_led, tx_dmaready, rx_status_led, rx_dmaready, tx_fifo_we, tx_fifo_wdata, tx_fifo_empty, tx_fifo_full, tx_fifo_afval, tx_fifo_aeval, tx_fifo_afull, tx_fifo_aempty, tx_fifo_wack, tx_fifo_dvld, tx_fifo_overflow, tx_fifo_underflow, tx_fifo_rdcnt, tx_fifo_wrcnt, rx_fifo_re, rx_fifo_rdata, rx_fifo_empty, rx_fifo_full, rx_fifo_afval, rx_fifo_aeval, rx_fifo_afull, rx_fifo_aempty, rx_fifo_wack, rx_fifo_dvld, rx_fifo_overflow, rx_fifo_underflow, rx_fifo_rdcnt, rx_fifo_wrcnt, fir_load_coeff_ram_addr, fir_load_coeff_ram_din0, fir_load_coeff_ram_din1, fir_load_coeff_ram_blk, fir_load_coeff_ram_wen, fir_load_coeff_ram_dout0, fir_load_coeff_ram_dout1, firen, fir_bank1, fir_bank0, fir_N, interp, shift, fcw, tx_correct_i, tx_correct_q, tx_gain_i, tx_gain_q, txen, txstop, ddsen, txfilteren, decim, rx_correct_i, rx_correct_q, rxen, rxstop, rxfilteren, duc_underrun, dac_last, ddc_overrun, adc_last, **kwargs): """The Radio Front End glues together the APB3 interface and the DSP chains. It consists of a synchronizer and a controller. The synchronizer safely transfers register data between the system and sample clock domains. The controller responds to read and write requests to the register file on the APB3 bus. :returns: A MyHDL synthesizable module """ state_t = enum( 'IDLE', 'ACCESS', 'READ', 'READ2', 'READ_SAMPLE', 'READ_SAMPLE2', 'READ_SAMPLE3', 'READ_SAMPLE4', 'DONE', ) state = Signal(state_t.IDLE) addr = Signal(intbv(0)[8:]) # Local registers # overrun = Signal(modbv(0, min=0, max=2**16)) underrun = Signal(modbv(0, min=0, max=2**16)) counter = Signal(intbv(0)[len(prdata):]) afval = Signal(intbv(0)[len(tx_fifo_afval):]) aeval = Signal(intbv(0)[len(tx_fifo_aeval):]) # Synchronizer registers # sync_clearn = Signal(bool(1)) clear_ackn = Signal(bool(1)) sync_tx_afull = Signal(bool(0)) tx_afull = Signal(bool(0)) sync_tx_aempty = Signal(bool(1)) tx_aempty = Signal(bool(1)) sync_tx_underrun = Signal(modbv(0, min=0, max=2**16)) tx_underrun = Signal(modbv(0, min=0, max=2**16)) sync_txlast = Signal(bool(0)) txlast = Signal(bool(0)) sync_rx_afull = Signal(bool(0)) rx_afull = Signal(bool(0)) sync_rx_aempty = Signal(bool(1)) rx_aempty = Signal(bool(1)) sync_rx_overrun = Signal(modbv(0, min=0, max=2**16)) rx_overrun = Signal(modbv(0, min=0, max=2**16)) sync_rxlast = Signal(bool(0)) rxlast = Signal(bool(0)) write_count = Signal(intbv(0)[32:]) read_count = Signal(intbv(0)[32:]) @always_seq(pclk.posedge, reset=resetn) def synchronizer(): sync_clearn.next = clearn clear_ackn.next = sync_clearn sync_tx_afull.next = tx_fifo_afull tx_afull.next = sync_tx_afull sync_tx_aempty.next = tx_fifo_aempty tx_aempty.next = sync_tx_aempty sync_tx_underrun.next = duc_underrun tx_underrun.next = sync_tx_underrun sync_txlast.next = dac_last txlast.next = sync_txlast sync_rx_afull.next = rx_fifo_afull rx_afull.next = sync_rx_afull sync_rx_aempty.next = rx_fifo_aempty rx_aempty.next = sync_rx_aempty sync_rx_overrun.next = ddc_overrun rx_overrun.next = sync_rx_overrun sync_rxlast.next = adc_last rxlast.next = sync_rxlast len_fir_load_coeff_ram_din = len(fir_load_coeff_ram_din0) + len( fir_load_coeff_ram_din1) len_fir_N = len(fir_N) fir_load_coeff_k = Signal(intbv(0, min=0, max=fir_N.max)) fir_accessing = Signal(bool(0)) fir_accessing_next = Signal(bool(0)) @always_seq(pclk.posedge, reset=resetn) def coeff_controller(): if state == state_t.IDLE: if psel and fir_accessing: fir_load_coeff_ram_blk.next = False fir_load_coeff_ram_addr.next = concat(fir_bank1, fir_bank0, fir_load_coeff_k) fir_load_coeff_ram_wen.next = not pwrite # active high to active low fir_load_coeff_ram_din0.next = pwdata[9:] fir_load_coeff_ram_din1.next = pwdata[18:9] else: fir_load_coeff_ram_blk.next = True elif state == state_t.ACCESS: if psel and fir_accessing and not pwrite: fir_load_coeff_ram_blk.next = False # Pipelined read else: fir_load_coeff_ram_blk.next = True else: fir_load_coeff_ram_blk.next = True @always_seq(pclk.posedge, reset=resetn) def controller(): #pslverr.next = 0 tx_dmaready.next = not tx_fifo_full rx_dmaready.next = not rx_fifo_empty tx_status_led.next = txen or ddsen rx_status_led.next = rxen if not clear_ackn: clear_enable.next = False txen.next = 0 txstop.next = 0 ddsen.next = 0 overrun.next = 0 rxen.next = 0 rxstop.next = 0 underrun.next = 0 write_count.next = 0 fir_accessing.next = 0 if txlast: txen.next = 0 txstop.next = 0 if rxlast: rxen.next = 0 rxstop.next = 0 if state == state_t.IDLE: if not psel: state.next = state_t.IDLE else: state.next = state_t.ACCESS addr.next = paddr[8:] pready.next = False if state == state_t.ACCESS: if fir_accessing: fir_load_coeff_k.next = fir_load_coeff_k + 1 if pwrite: state.next = state_t.DONE pready.next = True else: pready.next = False state.next = state_t.READ else: if not pwrite and addr == WR_SAMPLE_ADDR: pready.next = False state.next = state_t.READ_SAMPLE else: pready.next = True state.next = state_t.DONE if pwrite: if addr == WE_SAMPLE_ADDR: write_count.next = write_count + 1 if tx_fifo_full: overrun.next = overrun + 1 else: tx_fifo_wdata.next = pwdata tx_fifo_we.next = True elif addr == WE_STATUS_ADDR: if pwdata[WS_CLEAR]: clear_enable.next = True elif pwdata[WS_LOOPEN]: loopen.next = pwdata[WS_LOOPEN] elif pwdata[WES_TXSTOP]: txstop.next = True else: txen.next = pwdata[WES_TXEN] txfilteren.next = pwdata[WES_FILTEREN] ddsen.next = pwdata[WES_DDSEN] firen.next = pwdata[WS_FIREN] elif addr == WE_INTERP_ADDR: interp.next = pwdata[len(interp):] shift.next = pwdata[len(shift) + 16:16] elif addr == WE_FCW_ADDR: fcw.next = pwdata elif addr == WE_THRESHOLD_ADDR: tx_fifo_afval.next = pwdata[26:16] tx_fifo_aeval.next = pwdata[10:] elif addr == WE_CORRECTION_ADDR: tx_correct_q.next = pwdata[26:16].signed() tx_correct_i.next = pwdata[10:].signed() elif addr == WE_GAIN_ADDR: tx_gain_q.next = pwdata[26:16] tx_gain_i.next = pwdata[10:] elif addr == W_FIR_ADDR: fir_bank1.next = pwdata[len_fir_N + 2] fir_bank0.next = pwdata[len_fir_N + 1] fir_N.next = pwdata[len_fir_N + 1:] #fir_accessing.next = pwdata[WF_ACCESS_COEFFS] fir_accessing_next.next = pwdata[WF_ACCESS_COEFFS] fir_load_coeff_k.next = 0 elif addr == WR_STATUS_ADDR: if pwdata[WS_CLEAR]: clear_enable.next = True elif pwdata[WS_LOOPEN]: loopen.next = pwdata[WS_LOOPEN] elif pwdata[WRS_RXSTOP]: rxstop.next = True else: rxen.next = pwdata[WRS_RXEN] rxfilteren.next = pwdata[WRS_FILTEREN] elif addr == WR_DECIM_ADDR: decim.next = pwdata[len(decim):] elif addr == WR_THRESHOLD_ADDR: rx_fifo_afval.next = pwdata[26:16] rx_fifo_aeval.next = pwdata[10:] elif addr == WR_CORRECTION_ADDR: rx_correct_q.next = pwdata[26:16].signed() rx_correct_i.next = pwdata[10:].signed() else: if addr == WE_STATUS_ADDR: prdata.next = concat( # BYTE 3 NIBBLE 2 - RESERVED intbv(0)[4:], # BYTE 3 NIBBLE 1 - COMBINED FLAGS intbv(0)[3:], firen, # BYTE 2 NIBBLE 2 - RX FIFO FLAGS intbv(0)[4:], # BYTE 2 NIBBLE 1 - RX DSP FLAGS intbv(0)[4:], # BYTE 1 NIBBLE 2 - TX FIFO FLAGS not tx_fifo_empty, not tx_fifo_full, tx_afull, tx_aempty, # BYTE 1 NIBBLE 1 - TX DSP FLAGS bool(0), ddsen, txfilteren, txen, # BYTE 0 - RESERVED intbv(0)[6:], loopen, not clearn) elif addr == WE_INTERP_ADDR: prdata.next = concat( intbv(0)[16 - len(shift):], shift, intbv(0)[16 - len(interp):], interp) elif addr == WE_FCW_ADDR: prdata.next = fcw elif addr == WE_RUNS_ADDR: prdata.next = concat(tx_underrun, overrun) elif addr == WE_THRESHOLD_ADDR: prdata.next = concat( intbv(0)[6:], tx_fifo_afval, intbv(0)[6:], tx_fifo_aeval) elif addr == WE_CORRECTION_ADDR: prdata.next = concat( intbv(0)[6:], tx_correct_q, intbv(0)[6:], tx_correct_i) elif addr == WE_GAIN_ADDR: prdata.next = concat( intbv(0)[6:], tx_gain_q, intbv(0)[6:], tx_gain_i) elif addr == WE_AVAILABLE_ADDR: prdata.next = concat( intbv(0)[32 - len(tx_fifo_wrcnt):], tx_fifo_wrcnt) elif addr == WE_DEBUG_ADDR: prdata.next = write_count elif addr == W_FIR_ADDR: prdata.next = concat( intbv(0)[32 - len_fir_N - 2:], fir_bank1, fir_bank0, fir_N) elif addr == WR_SAMPLE_ADDR: read_count.next = read_count + 1 if rx_fifo_empty: underrun.next = underrun + 1 else: rx_fifo_re.next = True elif addr == WR_STATUS_ADDR: prdata.next = concat( # BYTE 3 NIBBLE 2 - RESERVED intbv(0)[4:], # BYTE 3 NIBBLE 1 - COMBINED FLAGS intbv(0)[3:], firen, # BYTE 2 NIBBLE 2 - RX FIFO FLAGS not rx_fifo_empty, not rx_fifo_full, rx_afull, rx_aempty, # BYTE 2 NIBBLE 1 - RX DSP FLAGS bool(0), bool(0), rxfilteren, rxen, # BYTE 1 NIBBLE 2 - TX FIFO FLAGS intbv(0)[4:], # BYTE 1 NIBBLE 1 - TX DSP FLAGS intbv(0)[4:], # BYTE 0 - Misc Flags intbv(0)[6:], loopen, not clearn) elif addr == WR_DECIM_ADDR: prdata.next = concat(intbv(0)[32 - len(decim):], decim) elif addr == WR_RUNS_ADDR: prdata.next = concat(rx_overrun, underrun) elif addr == WR_THRESHOLD_ADDR: prdata.next = concat( intbv(0)[6:], rx_fifo_afval, intbv(0)[6:], rx_fifo_aeval) elif addr == WR_CORRECTION_ADDR: prdata.next = concat( intbv(0)[6:], rx_correct_q, intbv(0)[6:], rx_correct_i) elif addr == WR_AVAILABLE_ADDR: prdata.next = concat( intbv(0)[32 - len(rx_fifo_rdcnt):], rx_fifo_rdcnt) elif addr == WR_DEBUG_ADDR: prdata.next = intbv(0)[32:] else: prdata.next = 0 elif state == state_t.READ: pready.next = False state.next = state_t.READ2 elif state == state_t.READ2: pready.next = True prdata.next = concat(fir_load_coeff_ram_dout1, fir_load_coeff_ram_dout0).signed() state.next = state_t.DONE elif state == state_t.READ_SAMPLE: pready.next = False rx_fifo_re.next = False state.next = state_t.READ_SAMPLE2 elif state == state_t.READ_SAMPLE2: pready.next = False rx_fifo_re.next = False state.next = state_t.READ_SAMPLE3 elif state == state_t.READ_SAMPLE3: pready.next = False rx_fifo_re.next = False state.next = state_t.READ_SAMPLE4 elif state == state_t.READ_SAMPLE4: pready.next = True rx_fifo_re.next = False prdata.next = rx_fifo_rdata state.next = state_t.DONE elif state == state_t.DONE: tx_fifo_we.next = False rx_fifo_re.next = False pready.next = True state.next = state_t.IDLE fir_accessing_next.next = False if not fir_accessing: fir_accessing.next = fir_accessing_next elif fir_load_coeff_k == fir_N: fir_accessing.next = False return synchronizer, controller, coeff_controller
def testbench(vhdl_output_path=None): reset = ResetSignal(0, active=0, async=False) clk = Signal(bool(0)) axis_raw = Axis(32) axis_sum = Axis(32) clk_gen = clk_stim(clk, period=10) @instance def reset_gen(): reset.next = 0 yield delay(54) yield clk.negedge reset.next = 1 @instance def write_stim(): #values = [100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100] values = [106, 118, 151, 147, 149, 145, 155, 129, 166, 156, 141, 153, 130, 150, 160, 137, 150, 133, 105, 106, 131, 101, 112, 108, 83, 100, 102, 72, 70, 105, 78, 91, 108, 83, 93, 87, 89, 97, 114, 126, 136, 114, 146, 140, 138, 127, 127, 146, 135, 138, 148, 148, 137, 125, 161, 133, 123, 117, 116, 135, 132, 124, 90, 97, 88, 99, 105, 90, 106, 76, 90, 105, 108, 99, 102, 105, 99, 91, 116, 105, 115, 115, 117, 146, 156, 163, 135, 153, 140, 145, 138, 148, 134, 131, 131, 136, 126, 144, 127, 0] # values = [] # for i in range(1, 500): # values.append(int(100 + 40*random() + 30 * math.sin(2 * math.pi * 0.005 * i))) # # values.append(0) i = 0 yield reset.posedge while i < len(values): yield clk.negedge axis_raw.tvalid.next = 1 axis_raw.tdata.next = values[i] if i == len(values) - 1: axis_raw.tlast.next = 1 else: axis_raw.tlast.next = 0 if axis_raw.tready == 1: i += 1 yield clk.negedge axis_raw.tvalid.next = 0 @instance def read_stim(): yield reset.posedge yield delay(601) yield clk.negedge axis_sum.tready.next = 1 for _ in range(200): # while True: yield clk.negedge if axis_sum.tlast == 1: break for i in range(10): yield clk.negedge raise StopSimulation() uut = my_rc(clk, reset, axis_raw, axis_sum) if vhdl_output_path is not None: uut.convert(hdl='VHDL', path=vhdl_output_path) return instances()
def test_underflow_fifo_fast(args=None): """ verify the synchronous FIFO """ reset = ResetSignal(0, active=1, async=True) clock = Signal(bool(0)) if args is None: args = Namespace(width=8, size=16, name='test') else: # @todo: verify args has the attributes needed for the FIFOBus pass fbus = FIFOBus(width=args.width) glbl = Global(clock, reset) @myhdl.block def bench_fifo_underflow(): # @todo: use args.fast, args.use_srl_prim tbdut = cores.fifo.fifo_fast(glbl, fbus, size=args.size, use_srl_prim=False) @always(delay(10)) def tbclk(): clock.next = not clock @instance def tbstim(): fbus.write_data.next = 0xFE reset.next = reset.active yield delay(33) reset.next = not reset.active for ii in range(5): yield clock.posedge rand = randrange(args.size + 2, 2 * args.size + 1) for num_bytes in range(args.size, rand): for ii in range(args.size): try: fbus.write_data.next = ii fbus.write.next = True yield clock.posedge except ValueError: assert fbus.count == args.size assert fbus.full, "FIFO should be full!" assert not fbus.empty, "FIFO should not be empty" else: assert fbus.count <= args.size if (fbus.count < args.size): assert not fbus.full fbus.write.next = False fbus.write_data.next = 0xFE for delay_clk in range(5): yield clock.posedge if ii == (args.size - 1): assert fbus.count == args.size assert fbus.full, "FIFO should be full!" assert not fbus.empty, "FIFO should not be empty" yield clock.posedge for ii in range(num_bytes): try: fbus.read.next = True yield clock.posedge # yield clock.posedge # test works for 2 # yield clock.posedge stmts except ValueError: assert fbus.empty else: # print("rdata %x ii %x " % (fbus.read_data, ii)) assert fbus.read_valid assert fbus.read_data == ii, "rdata %x ii %x " % ( fbus.read_data, ii) fbus.read.next = False yield clock.posedge assert fbus.empty fbus.clear.next = True yield clock.posedge fbus.clear.next = not fbus.clear for ii in range(5): yield clock.posedge raise StopSimulation return myhdl.instances() with pytest.raises(ValueError): run_testbench(bench_fifo_underflow)
def core_testbench(hex_file): """ Connect the Core to the simulation memory, using wishbone interconnects. Assert the core for RESET_TIME. Finish the test after TIMEOUT units of time, or a write to toHost register. If toHost is different of 1, the test failed. """ clk = Signal(True) rst = Signal(False) imem = WishboneIntercon() dmem = WishboneIntercon() toHost = Signal(modbv(0)[32:]) config = cp.ConfigParser() config.read('Simulation/core/algol.ini') dut_core = Core(clk_i=clk, rst_i=rst, imem=imem, dmem=dmem, toHost=toHost, IC_ENABLE=config.getboolean('ICache', 'Enable'), IC_BLOCK_WIDTH=config.getint('ICache', 'BlockWidth'), IC_SET_WIDTH=config.getint('ICache', 'SetWidth'), IC_NUM_WAYS=config.getint('ICache', 'Ways'), DC_ENABLE=config.getboolean('DCache', 'Enable'), DC_BLOCK_WIDTH=config.getint('DCache', 'BlockWidth'), DC_SET_WIDTH=config.getint('DCache', 'SetWidth'), DC_NUM_WAYS=config.getint('DCache', 'Ways')) memory = Memory(clka_i=clk, rsta_i=rst, imem=imem, clkb_i=clk, rstb_i=rst, dmem=dmem, SIZE=int(config.get('Memory', 'Size'), 16), HEX=hex_file, BYTES_X_LINE=config.getint('Memory', 'Bytes_x_line')) @always(delay(int(TICK_PERIOD / 2))) def gen_clock(): clk.next = not clk @always(toHost) def toHost_check(): """ Wait for a write to toHost register. """ if toHost != 1: raise Error('Test failed. MTOHOST = {0}. Time = {1}'.format( toHost, now())) print("Time: {0}".format(now())) raise StopSimulation @instance def timeout(): """ Wait until timeout. """ rst.next = True yield delay(RESET_TIME * TICK_PERIOD) rst.next = False yield delay(TIMEOUT * TICK_PERIOD) raise Error("Test failed: Timeout") return dut_core, memory, gen_clock, timeout, toHost_check
def trellis2(clk, rst, selState, state, selTrans, weight, llr0, llr1, llr2, llr3, a, b, m=10, q=8): """ Second trellis and revision logic. m -- second trellis length q -- accumulated distance width clk, rst -- in : clock and negative reset selState -- in : selected state at time (l - 1) state -- in : 4 possible states at time (l - 1) selTrans -- in : 8 selected transitions (1 per state) at time (l - 1) weight -- in : four weights sorted by transition code at time (l - 1) llr0 -- out : LLR for (a, b) = (0, 0) at time (l + m - 1) llr1 -- out : LLR for (a, b) = (0, 1) at time (l + m - 1) llr2 -- out : LLR for (a, b) = (1, 0) at time (l + m - 1) llr3 -- out : LLR for (a, b) = (1, 1) at time (l + m - 1) a, b -- out : decoded values of (a, b) at time (l + m - 1) """ reg = [[Signal(intbv(0, 0, 4)) for i in range(8)] for j in range(m)] free = intbv(255, 0, 256) freeBeg = [bool(1) for i in range(8)] pastState = [intbv(0, 0, 8) for i in range(8)] pathIdReg = [Signal(intbv(i, 0, 8)) for i in range(8)] pathId = [intbv(0, 0, 8) for i in range(8)] freePathId = intbv(0, 0, 8) revWeight = [[Signal(intbv(0, 0, 2**q)) for i in range(m)] for j in range(4)] revWeightTmp = [[intbv(0, 0, 2**q) for i in range(m)] for j in range(4)] revWeightFilt = [intbv(0, 0, 2**q) for j in range(3)] op = [intbv(0, 0, 2**q) for i in range(4)] tmp = [intbv(0, 0, 2**q) for i in range(4)] tmp4 = intbv(0, 0, 2**(q + 1)) notZero = [[intbv(0, 0, 4) for i in range(3)] for j in range(2)] ind = [[intbv(0, 0, 4) for i in range(3)] for j in range(2)] minTmp = [bool(0) for i in range(3)] @always(clk.posedge, rst.negedge) def trellis2Logic(): if rst.val == 0: for i in range(4): for j in range(m): revWeight[i][j].next = 0 a.next = 0 b.next = 0 llr0.next = 0 llr1.next = 0 llr2.next = 0 llr3.next = 0 for i in range(8): pathIdReg[i].next = i for j in range(m): reg[j][i].next = 0 else: free = intbv(255) for i in range(8): pastState[i] = trans2state[i][int(selTrans[i].val)] pathId[i] = pathIdReg[pastState[i]].val free[int(pathId[i])] = 0 freeBeg = [bool(1) for i in range(8)] for i in range(8): if freeBeg[int(pathId[i])] == 1: reg[0][int(pathId[i])].next = selTrans[i].val freeBeg[int(pathId[i])] = 0 pathIdReg[i].next = pathId[i] for j in range(m - 1): reg[j + 1][int(pathId[i])].next = reg[j][int( pathId[i])].val else: if free[1:0] == 1: freePathId = 0 if free[2:0] == 2: freePathId = 1 if free[3:0] == 4: freePathId = 2 if free[4:0] == 8: freePathId = 3 if free[5:0] == 16: freePathId = 4 if free[6:0] == 32: freePathId = 5 if free[7:0] == 64: freePathId = 6 if free[8:0] == 128: freePathId = 7 reg[0][freePathId].next = selTrans[i].val free[freePathId] = 0 pathIdReg[i].next = freePathId for j in range(m - 1): reg[j + 1][freePathId].next = reg[j][int( pathId[i])].val a.next = reg[m - 1][int(pathId[int(selState.val)])].val[1] b.next = reg[m - 1][int(pathId[int(selState.val)])].val[0] for i in range(4): for j in range(m - 1): for k in range(4): if reg[j][int( pathId[int(state[k].val)] )].val == i and state[k].val != selState.val: op[k] = weight[k].val else: op[k] = (2**q) - 1 if op[0] < op[1]: tmp[0] = op[0] else: tmp[0] = op[1] if op[2] < op[3]: tmp[1] = op[2] else: tmp[1] = op[3] if tmp[0] < tmp[1]: tmp[2] = tmp[0] else: tmp[2] = tmp[1] if tmp[2] < revWeight[i][j].val: revWeightTmp[i][j + 1] = tmp[2] else: revWeightTmp[i][j + 1] = revWeight[i][j].val revWeightTmp[i][0] = weight[i].val for j in range(2): if revWeightTmp[0][j] == 0: notZero[j] = [1, 2, 3] elif revWeightTmp[1][j] == 0: notZero[j] = [0, 2, 3] elif revWeightTmp[2][j] == 0: notZero[j] = [0, 1, 3] elif revWeightTmp[3][j] == 0: notZero[j] = [0, 1, 2] if revWeightTmp[int(notZero[j][0])][j] <= revWeightTmp[int( notZero[j][1])][j]: minTmp[0] = 0 else: minTmp[0] = 1 if revWeightTmp[int(notZero[j][0])][j] <= revWeightTmp[int( notZero[j][2])][j]: minTmp[1] = 0 else: minTmp[1] = 1 if revWeightTmp[int(notZero[j][1])][j] <= revWeightTmp[int( notZero[j][2])][j]: minTmp[2] = 0 else: minTmp[2] = 1 if minTmp == [0, 0, 0]: ind[j] = [0, 1, 2] elif minTmp == [0, 0, 1]: ind[j] = [0, 2, 1] elif minTmp == [1, 0, 0]: ind[j] = [1, 0, 2] elif minTmp == [0, 1, 1]: ind[j] = [1, 2, 0] elif minTmp == [1, 1, 0]: ind[j] = [2, 0, 1] elif minTmp == [1, 1, 1]: ind[j] = [2, 1, 0] else: print("ERROR: Configuration does not exist", minTmp) for i in range(3): tmp[3] = revWeightTmp[int(notZero[0][int(ind[0][i])])][0] tmp4 = revWeightTmp[int(notZero[1][int( ind[1][i])])][1] + (2**(q - 4)) if tmp[3] < tmp4: revWeightFilt[int(ind[0][i])] = tmp[3] else: revWeightFilt[int(ind[0][i])] = intbv(tmp4)[q:0] for i in range(3): revWeightTmp[int(notZero[0][i])][0] = revWeightFilt[i] for i in range(4): for j in range(m): revWeight[i][j].next = revWeightTmp[i][j] llr0.next = revWeight[0][m - 1] llr1.next = revWeight[1][m - 1] llr2.next = revWeight[2][m - 1] llr3.next = revWeight[3][m - 1] return trellis2Logic
def __init__(self, n): self.a = Signal(False) self.b = Signal(intbv(0)[n:]) self.c = Signal(False)
def trellis1(clk, rst, selState, selTrans, selStateL2, selStateL1, stateL1, selTransL2, l=20): """ First trellis. l -- first trellis length clk, rst -- in : clock and negative reset selState -- in : selected state at time 0 selTrans -- in : 8 selected transitions (1 per state) at time 0 selStateL2 -- out : selected state at time (l - 2) selStateL1 -- out : selected state at time (l - 1) stateL1 -- out : 4 possible states at time (l - 1) selTransL2 -- out : selected transition at time (l - 2) """ reg = [[Signal(intbv(0, 0, 4)) for i in range(8)] for j in range(l)] free = intbv(255, 0, 256) freeBeg = [bool(1) for i in range(8)] pastState = [intbv(0, 0, 8) for i in range(8)] pathIdReg = [Signal(intbv(i, 0, 8)) for i in range(8)] pathId = [intbv(0, 0, 8) for i in range(8)] freePathId = intbv(0, 0, 8) current_state = intbv(0, 0, 8) outState_l2 = intbv(0, 0, 8) outState_l1 = intbv(0, 0, 8) state_l3 = intbv(0, 0, 4) state_l2 = intbv(0, 0, 4) state_l1 = intbv(0, 0, 4) @always(clk.posedge, rst.negedge) def trellis1Logic(): if rst.val == 0: for i in range(4): stateL1[i].next = 0 selStateL1.next = 0 selStateL2.next = 0 selTransL2.next = 0 for i in range(8): pathIdReg[i].next = i for j in range(l): reg[j][i].next = 0 else: free = intbv(255) for i in range(8): pastState[i] = trans2state[i][int(selTrans[i].val)] pathId[i] = pathIdReg[pastState[i]].val free[int(pathId[i])] = 0 freeBeg = [bool(1) for i in range(8)] for i in range(8): current_state = intbv(i) if freeBeg[int(pathId[int(current_state)])] == 1: reg[0][int( pathId[int(current_state)])].next = current_state[2:0] freeBeg[int(pathId[i])] = 0 pathIdReg[int(current_state)].next = pathId[int( current_state)] for j in range(l - 1): reg[j + 1][int( pathId[int(current_state)])].next = reg[j][int( pathId[int(current_state)])].val else: if free[0] == 1: freePathId = 0 if free[2:0] == 2: freePathId = 1 if free[3:0] == 4: freePathId = 2 if free[4:0] == 8: freePathId = 3 if free[5:0] == 16: freePathId = 4 if free[6:0] == 32: freePathId = 5 if free[7:0] == 64: freePathId = 6 if free[8:0] == 128: freePathId = 7 reg[0][freePathId].next = current_state[2:0] free[freePathId] = 0 pathIdReg[int(current_state)].next = freePathId for j in range(l - 1): reg[j + 1][freePathId].next = reg[j][int( pathId[int(current_state)])].val state_l3 = reg[l - 3][int(pathId[int(selState.val)])].val state_l2 = reg[l - 2][int(pathId[int(selState.val)])].val state_l1 = reg[l - 1][int(pathId[int(selState.val)])].val outState_l2[2] = state_l3[1] ^ (state_l3[0] ^ state_l2[1]) outState_l2[2:0] = state_l2 outState_l1[2] = state_l2[1] ^ (state_l2[0] ^ state_l1[1]) outState_l1[2:0] = state_l1 selStateL1.next = outState_l1 selStateL2.next = outState_l2 selTransL2.next = state2trans[int(outState_l2)][int(state_l1)] for i in range(4): stateL1[i].next = trans2state[int(outState_l2)][i] if __debug__: # Monitor: checks that in the first trellis, from each of the 8 states (trellis' beginning) we arrive at the same state (trellis' end). # (Ignore this message until every iteration is fully started) diff = 0 ref = intbv(0) tmp = intbv(0) state_l2_deb = reg[l - 2][int(pathId[7])].val state_l1_deb = reg[l - 1][int(pathId[7])].val ref[2] = state_l2_deb[1] ^ (state_l2_deb[0] ^ state_l1_deb[1]) ref[2:0] = state_l1_deb for i in range(7): state_l2_deb = reg[l - 2][int(pathId[i])].val state_l1_deb = reg[l - 1][int(pathId[i])].val tmp[2] = state_l2_deb[1] ^ (state_l2_deb[0] ^ state_l1_deb[1]) tmp[2:0] = state_l1_deb if ref != tmp: diff = 1 if diff == 1: print( "WARNING: all paths don't arrive at same state at end of first trellis (you should think about increasing its length)" ) return trellis1Logic
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): glbl (Global): global clock and reset spibus (SPIBus): the external SPI interface fifobus (FIFOBus): the fifo interface cso (ControlStatus): the control status signals """ # 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(size=fifobus.size, width=fifobus.width) writepath = FIFOBus(size=fifobus.size, width=fifobus.width) # the FIFO instances # @todo: replace with fifo_fast tx_fifo_inst = fifo_fast(reset, clock, writepath) rx_fifo_inst = fifo_fast(reset, clock, readpath) 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 isync1_inst = syncro(clock, icap, icaps) isync2_inst = 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 latch_if_id(clk, rst, instruction_in, pc_adder_in, instruction_out, pc_adder_out, stall=Signal(intbv(0)[1:]) ): """ Latch to control state between Instruction Fetch and Instruction Decoder clk -- trigger rst -- reset instruction_in -- 32 bits signal input pc_adder_in -- 32 bits signal input instruction_out -- 32 bits signal output for instruction decoder pc_adder_out -- 32 bits signal output for pc_add stall -- inhibit the count increment """ @always(clk.posedge, rst.posedge) def latch(): if rst == 1: instruction_out.next = 0 pc_adder_out.next = 0 else: if not stall: instruction_out.next = instruction_in pc_adder_out.next = pc_adder_in return latch
def DCache(clk_i, rst_i, cpu, mem, invalidate, ENABLE=True, D_WIDTH=32, BLOCK_WIDTH=5, SET_WIDTH=9, WAYS=2, LIMIT_WIDTH=32): """ The Instruction Cache module. :param clk: System clock :param rst: System reset :param cpu: CPU slave interface (Wishbone Interconnect to master port) :param mem: Memory master interface (Wishbone Interconnect to slave port) :param invalidate: Invalidate the cache :param D_WIDTH: Data width :param BLOCK_WIDTH: Address width for byte access inside a block line :param SET_WIDTH: Address width for line access inside a block :param WAYS: Number of ways for associative cache (Minimum: 2) :param LIMIT_WIDTH: Maximum width for address """ if ENABLE: assert D_WIDTH == 32, "Error: Unsupported D_WIDTH. Supported values: {32}" assert BLOCK_WIDTH > 0, "Error: BLOCK_WIDTH must be a value > 0" assert SET_WIDTH > 0, "Error: SET_WIDTH must be a value > 0" assert not (WAYS & (WAYS - 1)), "Error: WAYS must be a power of 2" # -------------------------------------------------------------------------- WAY_WIDTH = BLOCK_WIDTH + SET_WIDTH # cache mem address width TAG_WIDTH = LIMIT_WIDTH - WAY_WIDTH # tag size TAGMEM_WAY_WIDTH = TAG_WIDTH + 2 # Add the valid and dirty bit TAGMEM_WAY_VALID = TAGMEM_WAY_WIDTH - 2 # Valid bit index TAGMEM_WAY_DIRTY = TAGMEM_WAY_WIDTH - 1 # Dirty bit index TAG_LRU_WIDTH = (WAYS * (WAYS - 1)) >> 1 # (N*(N-1))/2 # -------------------------------------------------------------------------- dc_states = enum('IDLE', 'SINGLE', 'READ', 'WRITE', 'FETCH', 'EVICTING', 'FLUSH1', 'FLUSH2', 'FLUSH3') tag_rw_port = [RAMIOPort(A_WIDTH=SET_WIDTH, D_WIDTH=TAGMEM_WAY_WIDTH) for i in range(WAYS)] tag_flush_port = [RAMIOPort(A_WIDTH=SET_WIDTH, D_WIDTH=TAGMEM_WAY_WIDTH) for i in range(WAYS)] tag_lru_rw_port = RAMIOPort(A_WIDTH=SET_WIDTH, D_WIDTH=TAG_LRU_WIDTH) tag_lru_flush_port = RAMIOPort(A_WIDTH=SET_WIDTH, D_WIDTH=TAG_LRU_WIDTH) cache_read_port = [RAMIOPort(A_WIDTH=WAY_WIDTH - 2, D_WIDTH=D_WIDTH) for _ in range(0, WAYS)] cache_update_port = [RAMIOPort(A_WIDTH=WAY_WIDTH - 2, D_WIDTH=D_WIDTH) for _ in range(0, WAYS)] data_cache = [cache_read_port[i].data_o for i in range(0, WAYS)] data_cache2 = [cache_update_port[i].data_o for i in range(0, WAYS)] tag_entry = Signal(modbv(0)[TAG_WIDTH:]) tag_in = [Signal(modbv(0)[TAGMEM_WAY_WIDTH:]) for _ in range(0, WAYS)] tag_out = [Signal(modbv(0)[TAGMEM_WAY_WIDTH:]) for _ in range(0, WAYS)] lru_in = Signal(modbv(0)[TAG_LRU_WIDTH:]) lru_out = Signal(modbv(0)[TAG_LRU_WIDTH:]) tag_we = Signal(False) lru_select = Signal(modbv(0)[WAYS:]) current_lru = Signal(modbv(0)[TAG_LRU_WIDTH:]) update_lru = Signal(modbv(0)[TAG_LRU_WIDTH:]) access_lru = Signal(modbv(0)[WAYS:]) lru_pre = Signal(modbv(0)[WAYS:]) flush_addr = Signal(modbv(0)[SET_WIDTH:]) flush_we = Signal(False) n_flush_addr = Signal(modbv(0)[SET_WIDTH:]) n_flush_we = Signal(False) dc_update_addr = Signal(modbv(0)[LIMIT_WIDTH - 2:]) evict_data = Signal(modbv(0)[32:]) state = Signal(dc_states.IDLE) n_state = Signal(dc_states.IDLE) miss = Signal(False) miss_w = Signal(modbv(0)[WAYS:]) miss_w_and = Signal(False) valid = Signal(False) dirty = Signal(False) done = Signal(False) final_flush = Signal(False) final_access = Signal(False) fetch = Signal(False) evict = Signal(False) use_cache = Signal(False) cpu_wbs = WishboneSlave(cpu) mem_wbm = WishboneMaster(mem) cpu_busy = Signal(False) cpu_err = Signal(False) cpu_wait = Signal(False) mem_read = Signal(False) mem_write = Signal(False) mem_rmw = Signal(False) @always_comb def next_state_logic(): n_state.next = state if state == dc_states.IDLE: if invalidate: # flush request n_state.next = dc_states.FLUSH1 elif cpu_wbs.cyc_i and not cpu_wbs.we_i and not use_cache: # read (uncached) n_state.next = dc_states.SINGLE elif cpu_wbs.cyc_i and not cpu_wbs.we_i: # read (cached) n_state.next = dc_states.READ elif cpu_wbs.cyc_i and cpu_wbs.we_i and not use_cache: # write (uncached) n_state.next = dc_states.SINGLE elif cpu_wbs.cyc_i and cpu_wbs.we_i: # write (cached) n_state.next = dc_states.WRITE elif state == dc_states.SINGLE: if done: n_state.next = dc_states.IDLE elif state == dc_states.READ: if not miss: # cache hit n_state.next = dc_states.IDLE elif valid and dirty: # cache is valid but dirty n_state.next = dc_states.EVICTING else: # cache miss n_state.next = dc_states.FETCH elif state == dc_states.WRITE: if not miss: # Hit n_state.next = dc_states.IDLE elif valid and dirty: # Cache miss. Line is valid but dirty: write back n_state.next = dc_states.EVICTING else: n_state.next = dc_states.FETCH elif state == dc_states.EVICTING: if done: n_state.next = dc_states.FETCH elif state == dc_states.FETCH: if done: n_state.next = dc_states.IDLE elif state == dc_states.FLUSH1: n_state.next = dc_states.FLUSH2 elif state == dc_states.FLUSH2: if dirty: n_state.next = dc_states.FLUSH3 if final_flush: n_state.next = dc_states.IDLE else: n_state.next = dc_states.FLUSH1 elif state == dc_states.FLUSH3: if done: if final_flush: n_state.next = dc_states.IDLE else: n_state.next = dc_states.FLUSH1 @always(clk_i.posedge) def update_state(): if rst_i: state.next = dc_states.IDLE else: state.next = n_state @always_comb def assignments(): final_access.next = (dc_update_addr[BLOCK_WIDTH - 2:] == modbv(-1)[BLOCK_WIDTH - 2:]) and mem_wbm.ack_i and mem_wbm.cyc_o and mem_wbm.stb_o final_flush.next = flush_addr == 0 lru_select.next = lru_pre current_lru.next = lru_out access_lru.next = ~miss_w use_cache.next = not cpu_wbs.addr_i[31] # Address < 0x8000_0000 use the cache @always_comb def tag_entry_assign(): """ Using the lru history, get the tag entry needed in case of evicting. """ for i in range(0, WAYS): if lru_select[i]: tag_entry.next = tag_out[i][TAG_WIDTH:] @always_comb def done_fetch_evict_assign(): """ Flags to indicate current state of the FSM. fetch: getting data from memory. evic: writing data from cache to memory. done: the last access to memory. """ fetch.next = state == dc_states.FETCH and not final_access evict.next = (state == dc_states.EVICTING or state == dc_states.FLUSH3) and not final_access done.next = final_access if use_cache else mem_wbm.ack_i @always_comb def miss_check(): """ For each way, check tag and valid flag, and reduce the vector using AND. If the vector is full of ones, the data is not in the cache: assert the miss flag. MISS: data not in cache and the memory operation is a valid read. Ignore this if the module is flushing data. """ value = modbv(0)[WAYS:] for i in range(0, WAYS): value[i] = (not tag_out[i][TAGMEM_WAY_VALID] or tag_out[i][TAG_WIDTH:0] != cpu_wbs.addr_i[LIMIT_WIDTH:WAY_WIDTH]) miss_w.next = value @always_comb def miss_check_2(): """ Vector reduce: check for full miss. """ value = True for i in range(0, WAYS): value = value and miss_w[i] miss_w_and.next = value @always_comb def miss_check_3(): """ Check for valid wishbone cycle, and full miss. """ valid_access = cpu_wbs.cyc_i and cpu_wbs.stb_i and use_cache miss.next = miss_w_and and valid_access and not invalidate @always_comb def get_valid_n_dirty(): """ In case of miss get the valid and dirty flags, needed to detect if a evicting must be done first. """ for i in range(0, WAYS): if lru_select[i]: valid.next = tag_out[i][TAGMEM_WAY_VALID] dirty.next = tag_out[i][TAGMEM_WAY_DIRTY] trwp_clk = [tag_rw_port[i].clk for i in range(WAYS)] trwp_addr = [tag_rw_port[i].addr for i in range(WAYS)] trwp_data_i = [tag_rw_port[i].data_i for i in range(WAYS)] trwp_data_o = [tag_rw_port[i].data_o for i in range(WAYS)] trwp_we = [tag_rw_port[i].we for i in range(WAYS)] @always_comb def tag_rport(): for i in range(WAYS): trwp_clk[i].next = clk_i trwp_addr[i].next = cpu_wbs.addr_i[WAY_WIDTH:BLOCK_WIDTH] trwp_data_i[i].next = tag_in[i] trwp_we[i].next = tag_we tag_out[i].next = trwp_data_o[i] # LRU memory tag_lru_rw_port.clk.next = clk_i tag_lru_rw_port.data_i.next = lru_in lru_out.next = tag_lru_rw_port.data_o tag_lru_rw_port.addr.next = cpu_wbs.addr_i[WAY_WIDTH:BLOCK_WIDTH] tag_lru_rw_port.we.next = tag_we @always_comb def tag_write(): for i in range(0, WAYS): tag_in[i].next = tag_out[i] tag_we.next = False lru_in.next = lru_out if state == dc_states.READ or state == dc_states.WRITE: if miss: for i in range(0, WAYS): if lru_select[i]: tag_in[i].next = concat(False, True, cpu_wbs.addr_i[LIMIT_WIDTH:WAY_WIDTH]) tag_we.next = True else: if cpu_wbs.ack_o and cpu_wbs.cyc_i: for i in range(0, WAYS): if lru_select[i]: tag_in[i].next = tag_out[i] | (cpu_wbs.we_i << TAGMEM_WAY_DIRTY) # TODO: Optimize lru_in.next = update_lru tag_we.next = True @always_comb def flush_next_state(): n_flush_we.next = False n_flush_addr.next = flush_addr if state == dc_states.IDLE: if invalidate: n_flush_addr.next = modbv(-1)[SET_WIDTH:] elif state == dc_states.FLUSH1: n_flush_we.next = True elif state == dc_states.FLUSH2: n_flush_we.next = False n_flush_addr.next = flush_addr - modbv(1)[SET_WIDTH:] @always(clk_i.posedge) def update_flush(): if rst_i: flush_addr.next = modbv(-1)[SET_WIDTH:] flush_we.next = False else: flush_addr.next = n_flush_addr flush_we.next = n_flush_we and not dirty @always(clk_i.posedge) def update_addr_fsm(): if rst_i: dc_update_addr.next = 0 else: if state == dc_states.READ or state == dc_states.WRITE: if miss and not dirty: dc_update_addr.next = concat(cpu_wbs.addr_i[LIMIT_WIDTH:BLOCK_WIDTH], modbv(0)[BLOCK_WIDTH - 2:]) elif miss and dirty: dc_update_addr.next = concat(tag_entry, cpu_wbs.addr_i[WAY_WIDTH:2]) elif state == dc_states.FLUSH2: if dirty: dc_update_addr.next = concat(tag_entry, modbv(0)[WAY_WIDTH - 2:]) elif state == dc_states.EVICTING or state == dc_states.FETCH or state == dc_states.FLUSH3: if final_access: dc_update_addr.next = concat(cpu_wbs.addr_i[LIMIT_WIDTH:BLOCK_WIDTH], modbv(0)[BLOCK_WIDTH - 2:]) elif mem_wbm.ack_i and mem_wbm.stb_o: dc_update_addr.next = dc_update_addr + modbv(1)[BLOCK_WIDTH - 2:] else: dc_update_addr.next = 0 tfp_clk = [tag_flush_port[i].clk for i in range(WAYS)] tfp_addr = [tag_flush_port[i].addr for i in range(WAYS)] tfp_data_i = [tag_flush_port[i].data_i for i in range(WAYS)] tfp_we = [tag_flush_port[i].we for i in range(WAYS)] @always_comb def tag_flush_port_assign(): for i in range(WAYS): tfp_clk[i].next = clk_i tfp_addr[i].next = flush_addr tfp_data_i[i].next = modbv(0)[TAGMEM_WAY_WIDTH:] tfp_we[i].next = flush_we # connect to the LRU memory tag_lru_flush_port.clk.next = clk_i tag_lru_flush_port.addr.next = flush_addr tag_lru_flush_port.data_i.next = modbv(0)[TAG_LRU_WIDTH:] tag_lru_flush_port.we.next = flush_we @always_comb def cpu_data_assign(): temp = data_cache[0] for i in range(0, WAYS): if not miss_w[i]: temp = data_cache[i] cpu_wbs.dat_o.next = temp if use_cache else mem_wbm.dat_i @always_comb def evict_data_assign(): for i in range(0, WAYS): if lru_select[i]: evict_data.next = data_cache2[i] @always_comb def mem_port_assign(): mem_wbm.addr_o.next = concat(dc_update_addr, modbv(0)[2:]) if use_cache else cpu_wbs.addr_i mem_wbm.dat_o.next = evict_data if use_cache else cpu_wbs.dat_i mem_wbm.sel_o.next = modbv(0b1111)[4:] if use_cache else cpu_wbs.sel_i # To Verilog crp_clk = [cache_read_port[i].clk for i in range(0, WAYS)] crp_addr = [cache_read_port[i].addr for i in range(0, WAYS)] crp_data_i = [cache_read_port[i].data_i for i in range(0, WAYS)] crp_we = [cache_read_port[i].we for i in range(0, WAYS)] @always_comb def cache_mem_rw(): for i in range(0, WAYS): crp_clk[i].next = clk_i crp_addr[i].next = cpu_wbs.addr_i[WAY_WIDTH:2] crp_data_i[i].next = concat(cpu_wbs.dat_i[32:24] if cpu_wbs.sel_i[3] else data_cache[i][32:24], cpu_wbs.dat_i[24:16] if cpu_wbs.sel_i[2] else data_cache[i][24:16], cpu_wbs.dat_i[16:8] if cpu_wbs.sel_i[1] else data_cache[i][16:8], cpu_wbs.dat_i[8:0] if cpu_wbs.sel_i[0] else data_cache[i][8:0]) crp_we[i].next = state == dc_states.WRITE and not miss_w[i] and cpu_wbs.ack_o and cpu_wbs.we_i # TODO: check for not ACK or ACK? # To Verilog cup_clk = [cache_update_port[i].clk for i in range(0, WAYS)] cup_addr = [cache_update_port[i].addr for i in range(0, WAYS)] cup_data_i = [cache_update_port[i].data_i for i in range(0, WAYS)] cup_we = [cache_update_port[i].we for i in range(0, WAYS)] @always_comb def cache_mem_update(): for i in range(0, WAYS): cup_clk[i].next = clk_i cup_addr[i].next = dc_update_addr[WAY_WIDTH - 2:] cup_data_i[i].next = mem_wbm.dat_i cup_we[i].next = lru_select[i] and mem_wbm.ack_i and state == dc_states.FETCH @always_comb def wbs_cpu_flags(): cpu_err.next = mem_wbm.err_i cpu_wait.next = miss_w_and or not (state == dc_states.READ or state == dc_states.WRITE) if use_cache else not mem_wbm.ack_i cpu_busy.next = False @always_comb def wbm_mem_flags(): mem_read.next = fetch if use_cache else not cpu_wbs.we_i and cpu_wbs.cyc_i mem_write.next = evict if use_cache else cpu_wbs.we_i and cpu_wbs.cyc_i mem_rmw.next = False # Remove warnings: Signal is driven but not read for i in range(WAYS): tag_flush_port[i].data_o = None tag_lru_flush_port.data_o = None # Generate the wishbone interfaces wbs_cpu = WishboneSlaveGenerator(clk_i, rst_i, cpu_wbs, cpu_busy, cpu_err, cpu_wait).gen_wbs() # noqa wbm_mem = WishboneMasterGenerator(clk_i, rst_i, mem_wbm, mem_read, mem_write, mem_rmw).gen_wbm() # noqa # Instantiate tag memories tag_mem = [RAM_DP(tag_rw_port[i], tag_flush_port[i], A_WIDTH=SET_WIDTH, D_WIDTH=TAGMEM_WAY_WIDTH) for i in range(WAYS)] # noqa tag_lru = RAM_DP(tag_lru_rw_port, tag_lru_flush_port, A_WIDTH=SET_WIDTH, D_WIDTH=TAG_LRU_WIDTH) # noqa # Instantiate main memory (Cache) cache_mem = [RAM_DP(cache_read_port[i], cache_update_port[i], A_WIDTH=WAY_WIDTH - 2, D_WIDTH=D_WIDTH) for i in range(0, WAYS)] # noqa # LRU unit lru_m = CacheLRU(current_lru, access_lru, update_lru, lru_pre, None, NUMWAYS=WAYS) # noqa return instances() else: @always_comb def rtl(): mem.addr.next = cpu.addr mem.dat_o.next = cpu.dat_o mem.sel.next = cpu.sel mem.we.next = cpu.we cpu.dat_i.next = mem.dat_i cpu.ack.next = mem.ack cpu.err.next = mem.err @always(clk_i.posedge) def classic_cycle(): mem.cyc.next = cpu.cyc if not mem.ack else False mem.stb.next = cpu.stb if not mem.ack else False return instances()
def fifo_sync(clock, reset, fbus): """ Simple synchronous FIFO PORTS ===== PARAMETERS ========== """ # @todo: this is intended to be used for small fast fifo's but it # can be used for large synchronous fifo as well N = fbus.size if fmod(log(N, 2), 1) != 0: Asz = int(ceil(log(N, 2))) N = 2**Asz print("@W: m_fifo_sync only supports power of 2 size") print(" forcing size (depth) to %d instread of %d" % (N, fbus.size)) wptr = Signal(modbv(0, min=0, max=N)) rptr = Signal(modbv(0, min=0, max=N)) _vld = Signal(False) # generic memory model g_fifomem = fifo_mem_generic(clock, fbus.write, fbus.write_data, wptr, clock, fbus.read_data, rptr, mem_size=fbus.size) # @todo: almost full and almost empty flags read = fbus.read write = fbus.write @always_seq(clock.posedge, reset=reset) def rtl_fifo(): if fbus.clear: wptr.next = 0 rptr.next = 0 fbus.full.next = False fbus.empty.next = True elif read and not write: fbus.full.next = False if not fbus.empty: rptr.next = rptr + 1 if rptr == (wptr - 1): fbus.empty.next = True elif write and not read: fbus.empty.next = False if not fbus.full: wptr.next = wptr + 1 if wptr == (rptr - 1): fbus.full.next = True elif write and read: wptr.next = wptr + 1 rptr.next = rptr + 1 _vld.next = read @always_comb def rtl_assign(): fbus.read_valid.next = _vld & fbus.read nvacant = Signal(intbv(N, min=-0, max=N + 1)) # # empty slots ntenant = Signal(intbv(0, min=-0, max=N + 1)) # # filled slots @always_seq(clock.posedge, reset=reset) def dbg_occupancy(): if fbus.clear: nvacant.next = N ntenant.next = 0 else: v = nvacant f = ntenant if fbus.read_valid: v = v + 1 f = f - 1 if fbus.write: v = v - 1 f = f + 1 nvacant.next = v ntenant.next = f fbus.count = ntenant return ( g_fifomem, rtl_fifo, rtl_assign, dbg_occupancy, )
def test_block_conversion(): """Test bench used for conversion purpose""" # clock and reset signals clock = Signal(bool(0)) reset = ResetSignal(0, active=1, async=True) # width of the runlength width_runlength = 4 # width of the vli size width_size = 4 # width of the vli amplitude ref width_amplitude = 12 # width of address register width_addr = 6 # width of the output data width_packed_byte = 8 # image width width = 8 # image height height = 8 huffmandatastream = HuffmanDataStream(width_runlength, width_size, width_amplitude, width_addr) assert isinstance(huffmandatastream, HuffmanDataStream) bufferdatabus = HuffBufferDataBus(width_packed_byte) assert isinstance(bufferdatabus, HuffBufferDataBus) huffmancntrl = HuffmanCntrl() assert isinstance(huffmancntrl, HuffmanCntrl) # color component class component = Component() assert isinstance(component, Component) # image size class img_size = ImgSize(width, height) assert isinstance(img_size, ImgSize) # input fifo is empty rle_fifo_empty = Signal(bool(0)) @block def bench_entropycoder(): """This bench is used for conversion purpose""" # instantiate module, clock and reset inst = huffman(clock, reset, huffmancntrl, bufferdatabus, huffmandatastream, img_size, rle_fifo_empty) inst_clock = clock_driver(clock) inst_reset = reset_on_start(reset, clock) @instance def tbstim(): """dummy tests for conversion purpose""" yield clock.posedge print("Conversion done!!") raise StopSimulation return tbstim, inst, inst_clock, inst_reset # verify conversion using iverilog verify.simulator = 'iverilog' assert bench_entropycoder().verify_convert() == 0
from __future__ import generators from myhdl import Signal, Simulation, Cosimulation from myhdl import delay, intbv, now import os cmd = "iverilog -o tb_test.o ./tb_test.v " os.system(cmd) a = Signal(intbv(1)) b = Signal(intbv(2)) c = Signal(intbv(3)) cosim = Cosimulation("vvp -v -m ../myhdl.vpi tb_test.o", a=a, b=b, c=c) def stimulus(a, b): for i in range(10): yield delay(10) # print "Python a=%s b=%s" % (a, b) a.next = a + 1 b.next = b + 2 def response(c): while 1: yield c print "Python: %s %s %s %s" % (now(), c, a, b) sim = Simulation(stimulus(a=a, b=b), response(c=c), cosim)