def convert_to_verilog(args): clk = createSignal(0, 1) rst = createSignal(0, 1) anodos = createSignal(0, 4) segmentos = createSignal(0, 8) shift = createSignal(0, 1) clk_xtal = args.clock * 1000000 dut = banner(clk_i=clk, rst_i=rst, anodos_o=anodos, segmentos_o=segmentos, shift_o=shift, CLK_XTAL=clk_xtal, RST_NEG=args.rst_neg) dut.convert(path=args.path, name=args.filename, trace=False, testbench=False)
def driver7seg(clk_i, rst_i, tick_i, valor_i, off_i, anodos_o, segmentos_o): """ Driver para manejar display de 7 segmentos """ assert len(valor_i) == 4, "[driver7seg] Error: longitud de valor_i debe ser 4. Valor actual: {0}".format(len(valor_i)) assert len(anodos_o) == 4, "[driver7seg] Error: longitud de anodos_o debe ser 4. Valor actual: {0}".format(len(anodos_o)) assert len(segmentos_o) == 8, "[driver7seg] Error: longitud de segmentos_o debe ser 8. Valor actual: {0}".format(len(segmentos_o)) anodos = createSignal(0, len(anodos_o)) segment_ROM = (0x03, 0x9f, 0x25, 0x0d, 0x99, 0x49, 0x41, 0x1f, 0x01, 0x09, 0x11, 0xc1, 0x63, 0x85, 0x61, 0x71) @hdl.always(clk_i.posedge) def anodos_proc(): if rst_i: anodos.next = hdl.modbv(1)[4:] elif tick_i: anodos.next = hdl.concat(anodos[3:0], anodos[3]) @hdl.always_comb def segmentos_proc(): if off_i: segmentos_o.next = hdl.modbv(0xff)[len(segmentos_o):] else: segmentos_o.next = segment_ROM[valor_i] anodos_o.next = anodos return hdl.instances()
def clk_div(clk_xtal_i, rst_i, clk_display_o, clk_banner_o, CLK_XTAL=50000000, CLK_DISPLAY=60, CLK_BANNER=1): assert ( (CLK_DISPLAY / CLK_BANNER) % 4 == 0 ), "[clk_div] Error: (CLK_DISPLAY / CLK_BANNER) debe ser múltiplo de 4 para evitar display glitches" MAX_CNT_DISPLAY = int(CLK_XTAL / CLK_DISPLAY) MAX_CNT_BANNER = int(CLK_XTAL / CLK_BANNER) cnt_display = createSignal(0, log2up(MAX_CNT_DISPLAY)) cnt_banner = createSignal(0, log2up(MAX_CNT_BANNER)) @hdl.always(clk_xtal_i.posedge) def clk_display_proc(): if rst_i: cnt_display.next = 0 clk_display_o.next = 0 elif cnt_display == MAX_CNT_DISPLAY - 1: cnt_display.next = 0 clk_display_o.next = 1 else: cnt_display.next = cnt_display + 1 clk_display_o.next = 0 @hdl.always(clk_xtal_i.posedge) def clk_banner_proc(): if rst_i: cnt_banner.next = 0 clk_banner_o.next = 0 elif cnt_banner == MAX_CNT_BANNER - 1: cnt_banner.next = 0 clk_banner_o.next = 1 else: cnt_banner.next = cnt_banner + 1 clk_banner_o.next = 0 return hdl.instances()
def banner_testbench(): clk = createSignal(0, 1) rst = createSignal(0, 1) anodos = createSignal(0, 4) segmentos = createSignal(0, 8) shift = createSignal(0, 1) dut = banner(clk, rst, anodos, segmentos, shift, CLK_XTAL=CLK_XTAL, CLK_BANNER=CLK_BANNER, CLK_DISPLAY=CLK_DISPLAY, RST_NEG=False) cmd1 = 'iverilog -o {0}/{1}.o {0}/{1}.v {0}/tb_{1}.v'.format( PATH, FILENAME) cmd2 = 'vvp -v -m myhdl {0}/{1}.o'.format(PATH, FILENAME) dut.convert(path=PATH, name=FILENAME, trace=True, testbench=True) # Aux text = ('off', 'off', 'off', 'off', 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15) segment_ROM = (0x03, 0x9f, 0x25, 0x0d, 0x99, 0x49, 0x41, 0x1f, 0x01, 0x09, 0x11, 0xc1, 0x63, 0x85, 0x61, 0x71) index_text = createSignal(0, log2up(len(text))) def banner_compilation(): os.system(cmd1) return hdl.Cosimulation(cmd2, clk_i=clk, rst_i=rst, anodos_o=anodos, segmentos_o=segmentos, shift_o=shift) def get_segment_out(idx): _idx = text[idx] if _idx == 'off': return 0xff else: return segment_ROM[_idx] # generate clk @hdl.always(hdl.delay(int(TICK_PERIOD / 2))) def gen_clock(): clk.next = not clk # shift the text to show 1 position to the right @hdl.always(shift.posedge) def shit_text_proc(): index_text.next = (index_text + 1) % len(text) @hdl.instance def check_segment_output_proc(): while True: yield anodos yield hdl.delay(1) # wait for combinatorial outputs if anodos == 0b0001: assert segmentos == get_segment_out( index_text ), "Error: output mismatch. Index = {0}, anodos = {1}, segment_o = {2}".format( index_text, anodos, hex(segmentos)) elif anodos == 0b0010: assert segmentos == get_segment_out( (index_text + 1) % len(text)), "Error: output mismatch. Index = {0}".format( index_text) elif anodos == 0b0100: assert segmentos == get_segment_out( (index_text + 2) % len(text)), "Error: output mismatch. Index = {0}".format( index_text) elif anodos == 0b1000: assert segmentos == get_segment_out( (index_text + 3) % len(text)), "Error: output mismatch. Index = {0}".format( index_text) else: yield hdl.Error("Invalid patter for anodos: {}".format( hdl.bin(anodos, width=4))) # run the test for N full rotations @hdl.instance def run_n_rotations_proc(): for i in range(ROTATIONS): for j in range(len(text)): yield shift.posedge raise hdl.StopSimulation # timeout. I dont want to die waiting for results in case of errors @hdl.instance def timeout(): rst.next = True yield hdl.delay(RESET_TIME * TICK_PERIOD) rst.next = False yield hdl.delay(TIMEOUT * TICK_PERIOD) raise hdl.Error("Test failed: TIMEOUT") return hdl.instances(), banner_compilation()
def banner(clk_i, rst_i, anodos_o, segmentos_o, shift_o, CLK_XTAL=50000000, CLK_DISPLAY=240, CLK_BANNER=1, RST_NEG=False): """ Banner para mostrar números 0-9, izquierda a derecha """ TXT = "fedcba9876543210dead" NMBR = int(TXT, base=16) NCHAR = len(TXT) NBITS = 4 * len(TXT) clk_display = createSignal(0, 1) clk_banner = createSignal(0, 1) number2show = createSignal(0, 4) table2show = createSignal(0, NBITS) table2off = createSignal(0, NCHAR) index_sel = createSignal(0, 2) anodos = createSignal(0, len(anodos_o)) rst_aux_o = createSignal(0, 1) off_driver = createSignal(0, 1) clk_div_d = clk_div( clk_i, rst_aux_o, clk_display, clk_banner, # noqa CLK_XTAL=CLK_XTAL, CLK_DISPLAY=CLK_DISPLAY, CLK_BANNER=CLK_BANNER) driver = driver7seg(clk_i, rst_aux_o, clk_display, number2show, off_driver, anodos, segmentos_o) # noqa @hdl.always_comb def rst_proc(): if RST_NEG: rst_aux_o.next = not rst_i else: rst_aux_o.next = rst_i @hdl.always(clk_i.posedge) def shift_banner_proc(): if rst_aux_o: table2show.next = hdl.modbv(NMBR)[NBITS:] table2off.next = hdl.modbv(0xF)[NCHAR:] elif clk_banner: table2show.next = hdl.concat(table2show[4:0], table2show[NBITS:4]) table2off.next = hdl.concat(table2off[0], table2off[NCHAR:1]) @hdl.always_comb def index_proc(): if anodos == 0b0001: index_sel.next = 0 elif anodos == 0b0010: index_sel.next = 1 elif anodos == 0b0100: index_sel.next = 2 elif anodos == 0b1000: index_sel.next = 3 else: index_sel.next = 0 @hdl.always_comb def select_digit_proc(): """verilator lint_off WIDTH""" number2show.next = (table2show >> (index_sel * 4)) & hdl.modbv(0xf)[4:] off_driver.next = table2off[index_sel] """verilator lint_on WIDTH""" anodos_o.next = anodos shift_o.next = clk_banner return hdl.instances()