from myhdl import always, always_seq, block, delay, enum, instance, intbv, ResetSignal, Signal, StopSimulation @block def uart_tx(tx_bit, tx_valid, tx_byte, tx_clk, tx_rst): index = Signal(intbv(0, min=0, max=8)) st = enum('IDLE', 'START', 'DATA') state = Signal(st.IDLE) @always(tx_clk.posedge, tx_rst.negedge) def fsm(): if tx_rst == 0: tx_bit.next = 1 index.next = 0 state.next = st.IDLE else: if state == st.IDLE: tx_bit.next = 1 if tx_valid: # a pulse state.next = st.START elif state == st.START: tx_bit.next = 0 index.next = 7 state.next = st.DATA elif state == st.DATA: tx_bit.next = tx_byte[index] if index == 0: state.next = st.IDLE else: index.next = index - 1 return fsm @block def uart_tx_2(tx_bit, tx_valid, tx_byte, tx_clk, tx_rst): index = Signal(intbv(0, min=0, max=8)) st = enum('IDLE', 'START', 'DATA') state = Signal(st.IDLE) @always_seq(tx_clk.posedge, reset=tx_rst) def fsm(): if state == st.IDLE: tx_bit.next = 1 if tx_valid: # a pulse state.next = st.START elif state == st.START: tx_bit.next = 0 index.next = 7 state.next = st.DATA elif state == st.DATA: tx_bit.next = tx_byte[index] if index == 0: state.next = st.IDLE else: index.next = index - 1 return fsm @block def tb(uart_tx): tx_bit = Signal(bool(1)) tx_valid = Signal(bool(0)) tx_byte = Signal(intbv(0)[8:]) tx_clk = Signal(bool(0)) # tx_rst = Signal(bool(1)) tx_rst = ResetSignal(1, active=0, isasync=True) uart_tx_inst = uart_tx(tx_bit, tx_valid, tx_byte, tx_clk, tx_rst) # toVerilog(uart_tx, tx_bit, tx_valid, tx_byte, tx_clk, tx_rst) @always(delay(10)) def clk_gen(): tx_clk.next = not tx_clk @instance def stimulus(): tx_rst.next = 1 yield delay(100) tx_rst.next = 0 yield delay(100) tx_rst.next = 1 yield delay(100) for v in (0x00, 0xff, 0x55, 0xaa): yield tx_clk.negedge tx_byte.next = v tx_valid.next = 1 yield tx_clk.negedge tx_valid.next = 0 yield delay(16 * 20) raise StopSimulation return clk_gen, stimulus, uart_tx_inst dut = uart_tx_2 inst = tb(dut) inst.config_sim(trace=True) inst.run_sim(10000)