예제 #1
0
파일: sdram_sdr.py 프로젝트: Godtec/rhea
def sdram_sdr_controller(clock, reset, ibus, extram, refresh=True):
    """ SDRAM controller
    This module is an SDRAM controller to interface and control
    SDRAM modules.  This module contains a state-machine that 
    controls the different SDRAM modes including refresh etc.

    This module provides the translation from a flat memory-mapped
    bus (e.g. Wishbone, Avalon, AXI, etc.) to the SDRAM interface.
    Also intended to support memory-mapped and streaming (FIFO
    mode).  In streaming / FIFO mode the external memory acts as
    one large FIFO.  The SDRAM controller type is determine by
    the internal interface (ibus) passed.

    This SDRAM controller is a port of the Xess SDRAM controller
    for the Xula boards.
    https://github.com/xesscorp/XuLA/blob/master/FPGA/XuLA_lib/SdramCntl.vhd
    """

    States = enum('INITWAIT', 'INITPCHG', 'INITSETMODE', 'INITRFSH', 
                  'RW', 'ACTIVATE', 'REFRESHROW', 'SELFREFRESH')

    Commands = enum('nop', 'active', 'read', 'write', 
                    'pchg', 'mode', 'rfsh',
                    encoding='binary')

    cmdlut = (intbv('011100')[5:], 
              intbv('001100')[5:],
              intbv('010100')[5:],
              intbv('010000')[5:],
              intbv('001000')[5:],
              intbv('000000')[5:],
              intbv('000100')[5:])

    sdram = extram
    sdram.cmd = Signal(intbv(0)[5:])

    timer = Signal(intbv(0, min=0, max=sdram.cyc_init))
    ras_timer = Signal(intbv(0, min=0, max=sdram.cyc_ras))
    wr_timer = Signal(intbv(0, min=0, max=sdram.cyc_wr))
    
    state = Signal(States.INITWAIT)

    @always_seq(clock.posedge, reset=reset)
    def rtl_sdram_controller():
        
        # this is one big state-machine but ...
        if state == States.INITWAIT:
            if sdram.lock:
                timer.next = sdram.cyc_init
                state.next = States.initpchg
            else:
                sdram.sd_cke.next = False
            sdram.status.next = 1

        elif state == States.INITPCHG:
            sdram.cmd.next = Commands.PCHG
            sdram.addr[CMDBITS] = Commands.ALL_BANKS
            timer.next = sdram.cycles

    return rtl_sdram_controller
예제 #2
0
def whitebox_reset(resetn, dac_clock, clear_enable, clearn):

    state_t = enum('CLEAR', 'CLEARING', 'RUN')
    state = Signal(state_t.CLEAR)

    sync_clear_en = Signal(bool(0))
    clear_en = Signal(bool(0))
    clear_count = Signal(intbv(0)[10:])

    @always_seq(dac_clock.posedge, reset=resetn)
    def controller():
        sync_clear_en.next = clear_enable
        clear_en.next = sync_clear_en
        if state == state_t.CLEAR:
            clearn.next = 0
            clear_count.next = 16
            state.next = state_t.CLEARING
        elif state == state_t.CLEARING:
            clear_count.next = clear_count - 1
            if clear_count == 0:
                state.next = state_t.RUN
            else:
                state.next = state_t.CLEARING
        if state == state_t.RUN:
            clearn.next = 1
            if clear_en:
                state.next = state_t.CLEAR

    return controller
def cezar(clk, reset, y, x):
    state_t = enum('enc', 'dec')
    accumulator = Signal(intbv(0)[32:])
    counter = Signal(intbv(0)[32:])
    state = Signal(state_t.COUNT)
    message = Signal(intbv(0)[4:])
    key = Signal(intbv(0)[3:].signed())

    @always_seq(clk.posedge, reset=reset)
    def enc_proc():
        if state == state_t.dec:
            key.next = -key

        x.next = message + key
        if x > 15:
            x.next = 0 + key
        elif x < 0:
            x.next = 15 + key

        elif state == state_t.enc:
            key.next = key
            x.next = message + key
            if x > 15:
                x.next = 0 + key
            elif x < 0:
                x.next = 15 + key

        else:
            raise ValueError("Undefined state")

    return instances()
예제 #4
0
def get_fmax(fn, info):
    log = open(fn, 'r')
    fmax = []
    States = enum('search', 'fmax')
    state = States.search
    glncnt, lncnt = 0, 0

    for ln in log:
        if state == States.search:
            if glncnt > 100 and 'Fmax Summary' in ln:
                lncnt = 1
                state = States.fmax

        elif state == States.fmax:
            if lncnt == 5:
                fstr = ln.split(';')
                if len(fstr) < 2:
                    state = States.search
                    continue
                fstr = fstr[1].split()
                fstr = fstr[0].strip()
                fmax.append(fstr)

            if lncnt >= 6:
                state = States.search

        lncnt += 1
        glncnt += 1

    if len(fmax) > 0:
        info['fmax'] = min(map(float, fmax))
    else:
        info['fmax'] = -1

    return info
예제 #5
0
 def testUniqueLiterals(self):
     try:
         t_State = enum("SEARCH", "CONFIRM", "SEARCH")
     except ValueError:
         pass
     else:
         self.fail()
예제 #6
0
def get_fmax(fn, info):
    log = open(fn, 'r')
    fmax = []
    States = enum('search', 'fmax')
    state = States.search
    glncnt,lncnt = 0,0

    for ln in log:
        if state == States.search:
            if glncnt > 100 and ln.find('Fmax Summary') != -1:
                lncnt = 1
                state = States.fmax

        elif state == States.fmax:
            if lncnt == 5:
                fstr = ln.split(';')
                if len(fstr) < 2:
                    state = States.search
                    continue
                fstr = fstr[1].split()
                fstr = fstr[0].strip()
                fmax.append(fstr)

            if lncnt >= 6:
                state = States.search

        lncnt += 1
        glncnt += 1

    if len(fmax) > 0:
        info['fmax'] = min(map(float, fmax))
    else:
        info['fmax'] = -1
    
    return info
예제 #7
0
	def gen_wbs_stm(self, *operations):
	"""
		State machine generator for slave
		This function generate the state signal and generator for the state machine
		Basic operations: Single read/write, Block read/write
		Arguments:
		* operations: a list of optional supported operations for the state machine. 
		Example:
		mygen = wishbone_slave_generator(theslave)
		mygen.gen_wbs_stm("")
	"""
		# states definition
		self.wbsstate_t = enum("wbs_idle", "wbs_incycle", "wbs_read_wait", "wbs_write_wait")
		self.wbsstate_cur = Signal(self.wbsstate_t.wbs_idle)
		
		# flag answer signals
		self.flagbusy = Signal(intbv(0)[1:])
		self.flagerr = Signal(intbv(0)[1:])
		# throttle flag
		self.flagwait = Signal(intbv(0)[1:])
		
		# state machine: transitions
		@always(self.wbssig.CLK_I.posedge, self.wbssig.RST_I.negedge)
		def wbsstate_proc():
			if self.wbssig.RST_I = 1:
				self.wbsstate_cur.next = self.wbsstate_t.wbs_idle
			else:
예제 #8
0
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
예제 #9
0
def sigmoid(t_clk, t_reset, t_y_out, t_x, t_prec=4, fraction=16):
    """

    :param x:
    :param prec:
    :return:
    """
    const_1 = Signal(intbv(65536)[32:])
    state_t = enum('count', 'result')
    state = Signal(state_t.count)
    accumulator = Signal(intbv(0)[32:])
    counter = Signal(intbv(0)[32:])
    t_exp_out, t_exp_end = [Signal(intbv(0)[32:]) for i in range(2)]
    t_exp_start = Signal(intbv(1)[32:])
    exponential_1 = exponential(t_clk, t_reset, t_exp_out, t_x.tdata, t_exp_end, t_exp_start, t_prec, fraction)

    @always_seq(t_clk.posedge, reset=t_reset)
    def sigmoids():
        """

        :return:
        """
        if state == state_t.count:
            if t_exp_end == 1:
                t_exp_start.next = 0
                accumulator.next = ((t_exp_out << fraction) // (t_exp_out + const_1))
                state.next = state_t.result
        elif state == state_t.result:
            t_exp_start.next = 1
            t_y_out.tdata.next = accumulator
            state.next = state_t.count
        else:
            raise ValueError("Undefined state")

    return instances()
예제 #10
0
def iir_sliding_window(clk, rstn, ready, input, output, samples, count):

    c_floating_bit = ceil(log2(samples)) + 3
    c_mantissa_bit = ceil(log2(count))
    c_bit_count = c_mantissa_bit + c_floating_bit
    c_gain = round(2**c_floating_bit - (samples / count))

    t_state = enum("idle", "update_request")

    s_internal = Signal(intbv(0)[c_bit_count:])
    s_state = Signal(t_state.idle)

    @always_seq(clk.posedge, rstn)
    def on_clock():
        if ready and s_state == t_state.idle:
            if input:
                v_error = s_internal[:c_floating_bit] >= (count - 1)
                output.next = v_error
                if not v_error:
                    s_internal.next = s_internal + 2**c_floating_bit
            s_state.next = t_state.update_request
        elif s_state == t_state.update_request:
            v_value = intbv(int(s_internal))[(c_bit_count + c_floating_bit):]
            v_value *= c_gain
            s_internal.next = v_value[:c_floating_bit]

            output.next = False
            s_state.next = t_state.idle

    return on_clock
예제 #11
0
파일: sdram_model.py 프로젝트: cfelton/rhea
    def __init__(self, intf):
        """ SDRAM Model
        This will model the behavior and cycle accurate interface to
        an SDRAM device.

        Usage:
            extmembus = SDRAMInterface()          # interface and transactors
            sdram_model = SDRAMModel(extmembus)   # model
            sdram_proc = sdram_model.process()    # send to simulator

        This model implements the functionality described in the Micron
        datasheet for a 256Mb device:
        http://www.micron.com/parts/dram/sdram/mt48lc16m16a2b4-6a-it?pc=%7B5144650B-31FA-410A-993E-BADF981C54DD%7D

        Not convertible.
        """
        assert isinstance(intf, SDRAMInterface)

        # external interface to the controller, the SDRAM interface
        # also contains the SDRAM timing parameters.
        self.intf = intf

        # emulate banks in an SDRAM
        self.banks = [{} for _ in range(intf.num_banks)]

        # typically DRAM is defined using states (@todo add reference)
        self.States = enum("IDLE", "ACTIVE")
        self.Commands = intf.Commands
예제 #12
0
파일: sdram_model.py 프로젝트: rowhit/rhea
    def __init__(self, intf):
        """ SDRAM Model
        This will model the behavior and cycle accurate interface to
        an SDRAM device.

        Usage:
            extmembus = SDRAMInterface()          # interface and transactors
            sdram_model = SDRAMModel(extmembus)   # model
            sdram_proc = sdram_model.process()    # send to simulator

        This model implements the functionality described in the Micron
        datasheet for a 256Mb device:
        http://www.micron.com/parts/dram/sdram/mt48lc16m16a2b4-6a-it?pc=%7B5144650B-31FA-410A-993E-BADF981C54DD%7D

        Not convertible.
        """
        assert isinstance(intf, SDRAMInterface)

        # external interface to the controller, the SDRAM interface
        # also contains the SDRAM timing parameters.
        self.intf = intf

        # emulate banks in an SDRAM
        self.banks = [{} for _ in range(intf.num_banks)]

        # typically DRAM is defined using states (@todo add reference)
        self.States = enum("IDLE", "ACTIVE")
        self.Commands = intf.Commands
예제 #13
0
파일: whitebox.py 프로젝트: n8ohu/whitebox
def whitebox_reset(resetn,
                  dac_clock,
                  clear_enable,
                  clearn):

    state_t = enum('CLEAR', 'CLEARING', 'RUN')
    state = Signal(state_t.CLEAR)

    sync_clear_en = Signal(bool(0))
    clear_en = Signal(bool(0))
    clear_count = Signal(intbv(0)[10:])

    @always_seq(dac_clock.posedge, reset=resetn)
    def controller():
        sync_clear_en.next = clear_enable
        clear_en.next = sync_clear_en
        if state == state_t.CLEAR:
            clearn.next = 0
            clear_count.next = 16
            state.next = state_t.CLEARING
        elif state == state_t.CLEARING:
            clear_count.next = clear_count - 1
            if clear_count == 0:
                state.next = state_t.RUN
            else:
                state.next = state_t.CLEARING
        if state == state_t.RUN:
            clearn.next = 1
            if clear_en:
                state.next = state_t.CLEAR
    
    return controller
예제 #14
0
파일: uartbase.py 프로젝트: rowhit/rhea
def uarttx(glbl, fbustx, tx, baudce):
    """UART transmitter  function
    
    Arguments(Ports):
        glbl : rhea.Global interface, clock and reset
        fbustx : FIFOBus interface to the TX fifo
        tx : The actual transmition line

    Parameters:
        baudce : The transmittion baud rate

    myhdl convertible
    """
    clock, reset = glbl.clock, glbl.reset

    states = enum('wait', 'start', 'byte', 'stop', 'end')
    state = Signal(states.wait)
    txbyte = Signal(intbv(0)[8:])
    bitcnt = Signal(intbv(0, min=0, max=9))

    @always_seq(clock.posedge, reset=reset)
    def beh_tx():
        # default values
        fbustx.read.next = False

        # state handlers
        if state == states.wait:
            if not fbustx.empty and baudce:
                txbyte.next = fbustx.read_data
                fbustx.read.next = True
                state.next = states.start

        elif state == states.start:
            if baudce:
                bitcnt.next = 0
                tx.next = False
                state.next = states.byte

        elif state == states.byte:
            if baudce:
                bitcnt.next = bitcnt + 1
                tx.next = txbyte[bitcnt]
            elif bitcnt == 8:
                state.next = states.stop
                bitcnt.next = 0

        elif state == states.stop:
            if baudce:
                tx.next = True
                state.next = states.end

        elif state == states.end:
            if baudce:
                state.next = states.wait

        else:
            assert False, "Invalid state %s" % (state)

    return myhdl.instances()
예제 #15
0
파일: uartbase.py 프로젝트: cfelton/rhea
def uarttx(glbl, fbustx, tx, baudce):
    """UART transmitter  function
    
    Arguments(Ports):
        glbl : rhea.Global interface, clock and reset
        fbustx : FIFOBus interface to the TX fifo
        tx : The actual transmition line

    Parameters:
        baudce : The transmittion baud rate

    myhdl convertible
    """
    clock, reset = glbl.clock, glbl.reset

    states = enum("wait", "start", "byte", "stop", "end")
    state = Signal(states.wait)
    txbyte = Signal(intbv(0)[8:])
    bitcnt = Signal(intbv(0, min=0, max=9))

    @always_seq(clock.posedge, reset=reset)
    def beh_tx():
        # default values
        fbustx.read.next = False

        # state handlers
        if state == states.wait:
            if not fbustx.empty and baudce:
                txbyte.next = fbustx.read_data
                fbustx.read.next = True
                state.next = states.start

        elif state == states.start:
            if baudce:
                bitcnt.next = 0
                tx.next = False
                state.next = states.byte

        elif state == states.byte:
            if baudce:
                bitcnt.next = bitcnt + 1
                tx.next = txbyte[bitcnt]
            elif bitcnt == 8:
                state.next = states.stop
                bitcnt.next = 0

        elif state == states.stop:
            if baudce:
                tx.next = True
                state.next = states.end

        elif state == states.end:
            if baudce:
                state.next = states.wait

        else:
            assert False, "Invalid state %s" % (state)

    return myhdl.instances()
예제 #16
0
def uart_rx(clk_i, rst_i, rx_tick_i, rx_i, dat_o, ready_o):
    RXTICKX = 8
    NBITSP = log2up(RXTICKX)
    NBITSTART = NBITSP - 1
    rx_sync = createSignal(0b111, 3)
    rx_r = createSignal(1, 1)
    bit_spacing = createSignal(0, NBITSP)
    bit_start = createSignal(0, NBITSTART)
    nxt_bit = createSignal(0, 1)
    bit_cnt = createSignal(0, 3)
    dat_r = createSignal(0, 8)
    rx_state = hdl.enum('IDLE', 'DATA', 'STOP')
    state = hdl.Signal(rx_state.IDLE)

    @hdl.always_seq(clk_i.posedge, reset=rst_i)
    def rx_sync_proc():
        if rx_tick_i:
            rx_sync.next = hdl.concat(rx_sync[2:0], rx_i)

    @hdl.always_comb
    def assign_proc():
        rx_r.next = rx_sync == 0b111 or rx_sync == 0b011 or rx_sync == 0b101 or rx_sync == 0b110
        dat_o.next = dat_r

    @hdl.always_seq(clk_i.posedge, reset=rst_i)
    def nxt_bit_proc():
        nxt_bit.next = bit_spacing == RXTICKX - 1
        if rx_tick_i and state != rx_state.IDLE:
            bit_spacing.next = bit_spacing + 1

    @hdl.always_seq(clk_i.posedge, reset=rst_i)
    def start_bit_proc():
        if state == rx_state.IDLE and not rx_r:
            bit_start.next = bit_start + rx_tick_i
        else:
            bit_start.next = 0

    @hdl.always_seq(clk_i.posedge, reset=rst_i)
    def fsm_proc():
        ready_o.next = False
        if rx_tick_i:
            if state == rx_state.IDLE:
                if not rx_r and bit_start == hdl.modbv(RXTICKX // 2 -
                                                       1)[NBITSTART:]:
                    state.next = rx_state.DATA
            elif state == rx_state.DATA:
                if nxt_bit:
                    dat_r.next = hdl.concat(rx_r, dat_r[8:1])
                    bit_cnt.next = bit_cnt + 1
                    if bit_cnt == 7:
                        state.next = rx_state.STOP
            elif state == rx_state.STOP:
                if nxt_bit:
                    state.next = rx_state.IDLE
                    ready_o.next = True
            else:
                state.next = rx_state.IDLE

    return hdl.instances()
예제 #17
0
    def process(self, glbl, lcd):
        """
        """
        self.update_cnt = 0

        # ...
        self.states = enum('init')
        
        # use a dictionary to capture all the 
        regfile = {}

        # emulate the behavior of the LT24 LCD interface, the min pulses
        # (strobes) is 15ns and require 15ns between, the max write rate 
        # is 33 Mpix/sec.  Most (all) commands accept 4 bytes (4 writes)
        # for a command.
        @instance
        def beh():

            while True:
                command_in_progress = False
                # numbytes actually the number of transfers
                numbytes, cmdbytes = 0, []
                self.reset_cursor()

                # wait for a new command
                # @todo: add timing checks
                yield lcd.csn.negedge
                wrn, rdn = bool(lcd.wrn), bool(lcd.rdn)

                # handle a transaction (csn low pulse)
                while not lcd.csn or command_in_progress:
                    if lcd.csn and command_in_progress:
                        regfile[cmd] = copy(cmdbytes)
                        command_in_progress = False
                        print("{:<10d}:LT24: cmd 0x{:02X}, numdata {}, data {}".format(
                            now(), cmd, numbytes, list(map(hex, cmdbytes[:])), ))
                    # check for rising edge of wrn or rdn
                    if not wrn and lcd.wrn:
                        if not lcd.dcn:
                            # a command received
                            command_in_progress = True
                            cmd = int(lcd.data[8:])
                            if cmd not in regfile:
                                regfile[cmd] = []
                        else:
                            if command_in_progress:
                                if cmd == 0x2C:
                                    self.update_next_pixel(int(lcd.data))
                                else:
                                    cmdbytes += [int(lcd.data[8:])]
                                numbytes += 1
                            else:
                                assert False, "Unexpected data!"

                    wrn, rdn = bool(lcd.wrn), bool(lcd.rdn)
                    yield delay(2)

        return beh
예제 #18
0
def exponential(t_clk, t_reset, t_y_out, t_x, t_end, t_start, t_prec=4, fraction=16):
    """

    :param t_clk:
    :param t_reset:
    :param t_y_out:
    :param t_x:
    :param t_prec:
    :param t_end:
    :param t_start:
    :return:
    """
    const_1 = Signal(intbv(65536)[32:])
    state_t = enum('count', 'result')
    state = Signal(state_t.count)
    accumulator = Signal(intbv(0)[32:])
    y_pow = Signal(intbv(0)[32:])
    counter = Signal(intbv(0)[32:])
    y_fac = Signal(intbv(1)[32:])
    t_pow_end, t_fac_end = [Signal(intbv(0)[32:]) for i in range(2)]
    t_pow_start, t_fac_start = [Signal(intbv(1)[32:]) for i in range(2)]
    power_1 = power(t_clk, t_reset, y_pow, t_x, counter, t_pow_end, t_pow_start)
    factorial_1 = factorial(t_clk, t_reset, y_fac, counter, t_fac_end, t_fac_start)

    @always_seq(t_clk.posedge, reset=t_reset)
    def exponentials():
        """

        :return:
        """
        if state == state_t.count:
            if t_start == 1:
                t_end.next = 0
                if t_pow_end == 1 and t_fac_end == 1:
                    t_pow_start.next = 0
                    t_fac_start.next = 0
                    if counter == 0:
                        counter.next = 1
                        accumulator.next = const_1
                    else:
                        accumulator.next = accumulator + ((y_pow << fraction) << fraction) // (y_fac << fraction)
                        counter.next = counter + 1
                    if counter > t_prec-1:
                        state.next = state_t.result
                        counter.next = 0
                    t_pow_start.next = 1
                    t_fac_start.next = 1
        elif state == state_t.result:
            t_pow_start.next = 1
            t_fac_start.next = 1
            t_end.next = 1
            t_y_out.next = accumulator
            accumulator.next = const_1
            state.next = state_t.count
        else:
            raise ValueError("Undefined state")

    return instances()
예제 #19
0
    def process(self, glbl, vga):
        """
        """
        # keep track of the number of updates
        self.update_cnt = 0

        # VGA driver essentially a state-machine with the following
        # states.  Typically implemented as a bunch of counters.
        self.States = enum('INIT', 'DISPLAY', 
                           'HFP', 'HSYNC', 'HBP', 
                           'VFP', 'VSYNC', 'VBP',
                           'END')

        # state table, small function to handle each state
        self.StateFuncs = {
            self.States.INIT: None,
            self.States.DISPLAY: self._state_display,
            self.States.HFP: self._state_hor_front_porch,
            self.States.HSYNC: self._state_hor_sync,
            self.States.HBP: self._state_hor_back_porch,
            self.States.VFP: self._state_ver_front_porch,
            self.States.VSYNC: self._state_ver_sync,
            self.States.VBP: self._state_ver_back_porch,
            self.States.END: None
        }
        
        self.state = self.States.INIT
        counters = Counters()

        # montior signals for debugging
        #_state = Signal(intbv(0, min=0, max=len(self.States)))
        _state = Signal(str(""))
        hcnt = Signal(intbv(0)[16:])
        vcnt = Signal(intbv(0)[16:])
        # end monitors

        @instance
        def g_capture_vga():            
            while True:
                #print(self.state)
                if self.state == self.States.INIT:
                    print("%10d Screen update, %d, in progress" % (now(), self.update_cnt))
                    counters.reset()
                    self.state = self.States.DISPLAY
                elif self.state == self.States.END:
                    self.state = self.States.INIT
                else:
                    yield self.StateFuncs[self.state](glbl, vga, counters)

        # monitor, sample each variable at each clock
        @always(glbl.clock.posedge)
        def g_monitor():
            _state.next = self.state._name
            hcnt.next = counters.hcnt
            vcnt.next = counters.vcnt
                        
        return g_capture_vga, g_monitor
예제 #20
0
    def process(self, glbl, vga):
        """
        """
        # keep track of the number of updates
        self.update_cnt = 0

        # VGA driver essentially a state-machine with the following
        # states.  Typically implemented as a bunch of counters.
        self.States = enum('INIT', 'DISPLAY', 
                           'HFP', 'HSYNC', 'HBP', 
                           'VFP', 'VSYNC', 'VBP',
                           'END')

        # state table, small function to handle each state
        self.StateFuncs = {
            self.States.INIT: None,
            self.States.DISPLAY: self._state_display,
            self.States.HFP: self._state_hor_front_porch,
            self.States.HSYNC: self._state_hor_sync,
            self.States.HBP: self._state_hor_back_porch,
            self.States.VFP: self._state_ver_front_porch,
            self.States.VSYNC: self._state_ver_sync,
            self.States.VBP: self._state_ver_back_porch,
            self.States.END: None
        }
        
        self.state = self.States.INIT
        counters = Counters()

        # montior signals for debugging
        #_state = Signal(intbv(0, min=0, max=len(self.States)))
        _state = Signal(str(""))
        hcnt = Signal(intbv(0)[16:])
        vcnt = Signal(intbv(0)[16:])
        # end monitors

        @instance
        def g_capture_vga():            
            while True:
                #print(self.state)
                if self.state == self.States.INIT:
                    print("%10d Screen update, %d, in progress" % (now(), self.update_cnt))
                    counters.reset()
                    self.state = self.States.DISPLAY
                elif self.state == self.States.END:
                    self.state = self.States.INIT
                else:
                    yield self.StateFuncs[self.state](glbl, vga, counters)

        # monitor, sample each variable at each clock
        @always(glbl.clock.posedge)
        def g_monitor():
            _state.next = self.state._name
            hcnt.next = counters.hcnt
            vcnt.next = counters.vcnt
                        
        return g_capture_vga, g_monitor
def ram_interface(ram, wb_bus, pattern_mode, clock, config):
    """
        Instantiate a RAM interface  for simulation

        ram : RAM Array, should be [Signal(modbv(0)[xlen:]) for ii in range(0, ram_size)]
        wb_bus: Wishbone bus (class CacheMasterWishboneBundle)
        pattern_mode : if True, insted of RAM content an address dependant pattern is read
        clock, reset : Clock and reset
        config : CacheConfig
    """

    t_mstate = enum('m_idle', 'm_burst')
    m_state = Signal(t_mstate.m_idle)

    def get_pattern(adr):

        bitpos = 0
        word_adr = modbv(0)[wb_bus.adrLow:]
        d = modbv(0)[config.master_data_width:]
        for i in range(0, config.master_data_width // 32):
            d[bitpos + 32:bitpos] = concat(adr, word_adr)
            bitpos += 32
            word_adr += 4

        return d

    @always_comb
    def mem_read():
        if wb_bus.wbm_stb_o and not wb_bus.wbm_we_o:
            if pattern_mode:
                wb_bus.wbm_db_i.next = get_pattern(wb_bus.wbm_adr_o)
            else:
                assert wb_bus.wbm_adr_o < len(
                    ram), "Out of bound RAM access to address {}".format(
                        wb_bus.wbm_adr_o)
                wb_bus.wbm_db_i.next = ram[wb_bus.wbm_adr_o]

    @always(clock.posedge)
    def mem_simul():
        if wb_bus.wbm_cyc_o and wb_bus.wbm_stb_o and wb_bus.wbm_we_o:
            for i in range(0, len(wb_bus.wbm_sel_o)):
                if wb_bus.wbm_sel_o[i]:
                    ram[wb_bus.wbm_adr_o].next[(i + 1) * 8:i *
                                               8] = wb_bus.wbm_db_o[(i + 1) *
                                                                    8:i * 8]

        if m_state == t_mstate.m_idle:
            if wb_bus.wbm_cyc_o and wb_bus.wbm_stb_o:
                m_state.next = t_mstate.m_burst
                wb_bus.wbm_ack_i.next = True
        else:
            if wb_bus.wbm_cti_o == 0b000 or wb_bus.wbm_cti_o == 0b111:
                wb_bus.wbm_ack_i.next = False
                m_state.next = t_mstate.m_idle

    return instances()
예제 #22
0
파일: _uart.py 프로젝트: robtaylor/rhea
def uarttx(glbl, fbustx, tx, baudce):
    """
    """
    clock, reset = glbl.clock, glbl.reset

    states = enum('wait', 'start', 'byte', 'stop', 'end')
    state = Signal(states.wait)
    txbyte = Signal(intbv(0)[8:])
    bitcnt = Signal(intbv(0, min=0, max=9))

    @always_seq(clock.posedge, reset=reset)
    def rtltx():
        # default values
        fbustx.rd.next = False

        # state handlers
        if state == states.wait:
            if not fbustx.empty and baudce:
                txbyte.next = fbustx.rdata
                fbustx.rd.next = True
                state.next = states.start

        elif state == states.start:
            if baudce:
                bitcnt.next = 0
                tx.next = False
                state.next = states.byte

        elif state == states.byte:
            if baudce:
                bitcnt.next = bitcnt + 1
                tx.next = txbyte[bitcnt]
            elif bitcnt == 8:
                state.next = states.stop
                bitcnt.next = 0

        elif state == states.stop:
            if baudce:
                tx.next = True
                state.next = states.end

        elif state == states.end:
            if baudce:
                state.next = states.wait

        else:
            assert False, "Invalid state %s" % (state)

    return rtltx
예제 #23
0
파일: _uart.py 프로젝트: robtaylor/rhea
def uarttx(glbl, fbustx, tx, baudce):
    """
    """
    clock, reset = glbl.clock, glbl.reset

    states = enum('wait', 'start', 'byte', 'stop', 'end')
    state = Signal(states.wait)
    txbyte = Signal(intbv(0)[8:])
    bitcnt = Signal(intbv(0, min=0, max=9))

    @always_seq(clock.posedge, reset=reset)
    def rtltx():
        # default values
        fbustx.rd.next = False

        # state handlers
        if state == states.wait:
            if not fbustx.empty and baudce:
                txbyte.next = fbustx.rdata
                fbustx.rd.next = True
                state.next = states.start

        elif state == states.start:
            if baudce:
                bitcnt.next = 0
                tx.next = False
                state.next = states.byte

        elif state == states.byte:
            if baudce:
                bitcnt.next = bitcnt + 1
                tx.next = txbyte[bitcnt]
            elif bitcnt == 8:
                state.next = states.stop
                bitcnt.next = 0

        elif state == states.stop:
            if baudce:
                tx.next = True
                state.next = states.end

        elif state == states.end:
            if baudce:
                state.next = states.wait

        else:
            assert False, "Invalid state %s" % (state)

    return rtltx
예제 #24
0
        def test(clock, reset, axis_source, axis_sink):

            return_objects = []

            return_objects.append(
                self.axis_buffer_check(
                    clock, reset, axis_source, axis_sink,
                    max_n_samples=max_n_samples,
                    randomise_axis_control_signals=True))

            return_objects.append(self.count_tests(clock, n_tests))

            t_stim_state = enum(
                'UNINTERRUPTED', 'AWAIT_DATA', 'RESET', 'HOLD')
            stim_state = Signal(t_stim_state.UNINTERRUPTED)

            @always(clock.posedge)
            def reset_stim():

                if stim_state == t_stim_state.UNINTERRUPTED:
                    # Allow an uninterrupted packet
                    if (axis_sink.TVALID and
                        axis_sink.TREADY and
                        axis_sink.TLAST):
                        # One full packet has gone through the buffer
                        stim_state.next = t_stim_state.AWAIT_DATA

                elif stim_state == t_stim_state.AWAIT_DATA:
                    # Await the next packet
                    if axis_sink.TVALID:
                        # The next packet has started
                        stim_state.next = t_stim_state.RESET

                elif stim_state == t_stim_state.RESET:
                    if random.random() < 0.1:
                        # Randomly send a reset
                        reset.next = True
                        stim_state.next = t_stim_state.HOLD

                elif stim_state == t_stim_state.HOLD:
                    if random.random() < 0.2:
                        # Keep reset high for a random period
                        reset.next = False
                        stim_state.next = t_stim_state.UNINTERRUPTED

            return_objects.append(reset_stim)

            return return_objects
예제 #25
0
def uart_tx(clk_i, rst_i, tx_tick_i, dat_i, start_i, ready_o, tx_o):
    cnt = createSignal(0, 4)  # Contará de 0 a 9
    data = createSignal(0, 8)  # Ancho del FIFO
    tx_state = hdl.enum('IDLE', 'TX')  # 2 estados de la FSM
    state = hdl.Signal(tx_state.IDLE)  # Estado inicial de estoy ocioso

    @hdl.always_seq(clk_i.posedge, reset=rst_i)
    def tx_state_m():  # 50MHz
        if state == tx_state.IDLE:
            ready_o.next = 1
            if start_i:  # Condición para cambiar de estado
                data.next = dat_i
                ready_o.next = 0
                state.next = tx_state.TX
            else:
                tx_o.next = 1

        elif state == tx_state.TX:
            if tx_tick_i:  #Usando el divisor del clk_i
                #lectura de los 8 bits que nos impartan para el caracter
                if cnt >= 1 and cnt <= 8:
                    tx_o.next = data[0]
                    data.next = hdl.concat(
                        False,
                        data[8:1])  #Usando una logica similar al uart_rx
                    cnt.next = cnt + 1
                else:
                    tx_o.next = 0
                    cnt.next = cnt + 1

                #cuando termina de leer el ultimo bit del caracter, reinicia todo.
                if cnt == 9:
                    tx_o.next = 1
                    ready_o.next = 1
                    state.next = tx_state.IDLE
                    cnt.next = 0

        else:
            state.next = tx_state.IDLE  #Default

    return hdl.instances()


# Local Variables:
# flycheck-flake8-maximum-line-length: 200
# flycheck-flake8rc: ".flake8rc"
# End:
예제 #26
0
	def gen_wbm_stm(self, *operations):
	"""
		State machine generator for master
		This function generate the state signal and generator for the state machine
		Basic operations: Single read/write, Block read/write
		Arguments:
		* operations: a list of optional supported operations for the state machine. 
		Example:
		mygen = wishbone_master_generator(themaster)
		mygen.gen_wbm_stm("")
	"""
		# states definition
		self.wbmstate_t = enum("wbm_idle", "wbm_incycle", "wbm_read_wait", "wbm_write_wait", "wbm_rmw_rdwait", "wbm_rmw_midwait", "wbm_rmw_wrwait")
		self.wbmstate_cur = Signal(self.wbmstate_t.wbm_idle)
		
		# list of trigger signals and related states
		self.list_trigsignals = []
		for i in zip(("trig_read", "trig_write", "trig_rmw"), self.wbmstate_t._names[2:5]):
			self.list_trigsignals.append({"name": i[0], "initstate": i[1], "trig": Signal(intbv(0)[1:])})
			
		# Vector of triggers: for use in state machine
		trig_vector = Signal(intbv(0)[3:])
		trig_list = (x["trig"] for x in self.list_trigsignals)
		@always_comb
		def trigvectgen():
			trig_vector.next = concat(*trig_list)
			
		# Vector of acknowledge signals: for use in state machine
		ack_list = [self.ACK_I]
		if self.RTY_I != None:
			ack_list.append(self.RTY_I)
		if self.ERR_I != None:
			ack_list.append(self.ERR_I)
		ack_vector = Signal(intbv(0)[len(ack_list):])
		# the error signals can be sliced with [1:]
		@always_comb
		def ackvectgen():
			ack_vector.next = concat(*ack_list)
		
		# state machine: transitions
		@always(self.wbmsig.CLK_I.posedge, self.wbmsig.RST_I.negedge)
		def wbmstate_proc():
			if self.wbmsig.RST_I = 1:
				self.wbmstate_cur.next = self.wbmstate_t.wbm_idle
			else:
예제 #27
0
def PS2Keyboard(
        code,
        finish,
        kb_dat,
        kb_clk,
        rst
    ):
    States = enum('READ', 'FINISH')

    state = Signal(States.FINISH)

    # Eight Data bits and One Parity. 
    bits = [Signal(bool(0)) for k in range(9)]
    code_reg = ConcatSignal(*bits)
    bit_counter = Signal(intbv(0, min=0, max=10))
    
    @always_seq(kb_clk.posedge, reset=rst)
    def receiving():
        if state == States.FINISH:
            if not kb_dat:
                # kb_dat=0, device starts a new transmission. 
                state.next = States.READ
                finish.next = 0
            else:
                # kb_dat=1, the stop bit. 
                code.next = code_reg
                finish.next = 1
        elif state == States.READ:
            # Shift Register. 
            bits[0].next = kb_dat
            for k in range(1, 9):
                bits[k].next = bits[k-1]
            # End Shift Register.
            if bit_counter == 8:
                # Have got all the 8bits and parity.
                state.next = States.FINISH
                bit_counter.next = 0
            else:
                bit_counter.next = bit_counter + 1
        else:
            raise ValueError('Undefined state.')

    return instances()
예제 #28
0
def apb3_simple_slave(bus, status_led):
    bus_presetn = bus.presetn
    bus_pclk = bus.pclk
    bus_paddr = bus.paddr
    bus_psel = bus.psel
    bus_penable = bus.penable
    bus_pwrite = bus.pwrite
    bus_pwdata = bus.pwdata
    bus_pready = bus.pready
    bus_prdata = bus.prdata
    bus_pslverr = bus.pslverr

    state_t = enum(
        'IDLE',
        'DONE',
    )
    state = Signal(state_t.IDLE)

    counter = Signal(intbv(0)[len(bus_prdata):])

    @always_seq(bus_pclk.posedge, reset=bus_presetn)
    def state_machine():
        status_led.next = counter[0]
        if state == state_t.IDLE:
            if bus_penable and bus_psel:
                if bus_paddr[8:] == 0x40:
                    bus_pready.next = False
                    if bus_pwrite:
                        counter.next = bus_pwdata
                        state.next = state_t.DONE
                    else:
                        bus_prdata.next = counter
                        counter.next = counter + 1
                        state.next = state_t.DONE
                else:
                    state.next = state_t.DONE
            else:
                state.next = state_t.IDLE
        elif state == state_t.DONE:
            bus_pready.next = True
            state.next = state_t.IDLE

    return state_machine
예제 #29
0
def my_sum(clk, reset, axis_s_raw, axis_m_sum):
    state_t = enum('CALCULATE', 'END', 'START')
    vin = Signal(intbv(0)[32:].signed())
    Vin = Signal(intbv(0)[32:].signed())
    Vout = Signal(intbv(0)[32:].signed())
    d = Signal(intbv(0)[32:].signed())
    state = Signal(state_t.START)

    @always_seq(clk.posedge, reset=reset)
    def sum_proc():
        if state == state_t.START:
            Vout.next = 0
            d.next = 0
            state.next = state_t.CALCULATE

        elif state == state_t.CALCULATE:
            axis_m_sum.tvalid.next = 1
            axis_m_sum.tlast.next = 0
            axis_s_raw.tready.next = 1
            if axis_s_raw.tvalid == 1:  # jeżeli przyszły dane to:
                # vin =       #zapisz gołe dane z IPcore'a
                Vin.next = axis_s_raw.tdata * 256  # dane przesunięte w lewo by uzyskać stały przecinek
                d.next = (
                    Vin - Vout
                ) // 8  # przeliczenie różnicy in-out wraz z przeskalowaniem o arbitralnie ustalony czyn
                Vout.next = Vout + d  # wpisanie stanu wyjścia do akumulatora
                # axis_m_sum.tdata.next: object = Signal(Vout // 256)  # wystawienie danych na zewnątrz z przywróceniem miejsca przecinka
                axis_m_sum.tdata.next = Vout >> 8  # wystawienie danych na zewnątrz z przywróceniem miejsca przecinka
                if axis_s_raw.tlast == 1:
                    state.next = state_t.END
        elif state == state_t.END:
            axis_s_raw.tready.next = 0
            axis_m_sum.tvalid.next = 1
            axis_m_sum.tlast.next = 1
            axis_m_sum.tdata.next = d // 256  # Wypisz na koniec skumulowaną wartość offsetu sygnału
            if axis_m_sum.tready == 1:
                state.next = state_t.START
        else:
            raise ValueError("Undefined state")

    return instances()
예제 #30
0
    def test_val_type_check(self):
        '''Signals should be bools or single bit intbvs.
        '''
        working_test_cases = (('foo', Signal(intbv(0)[1:])), ('bar',
                                                              Signal(bool(0))))

        for name, signal in working_test_cases:
            # Should pass fine
            check_bool_signal(signal, name)

        test_enum = enum('a', 'b')

        failing_test_cases = (('foo', Signal('bleh')),
                              ('foo', Signal(test_enum.a)), ('bar', Signal(
                                  (10))), ('bar', Signal(0)))

        for name, signal in failing_test_cases:
            self.assertRaisesRegex(
                ValueError, 'Port %s signal should be a boolean value or a '
                'single bit intbv value.' % (name, ), check_bool_signal,
                signal, name)
예제 #31
0
    def __init__(self, system, bus, divider, width=32, strict_sdoe=True):
        self.system = system
        self.bus = bus

        self.states = enum("IDLE", "START", "PRE", "FIRST", "SECOND", "POST",
                           "PULSE")
        self.state = Signal(self.states.IDLE)

        self.divider = divider
        self.strict_sdoe = strict_sdoe

        self.data_reg = Signal(intbv(0)[width:])

        self.count = Signal(intbv(0)[8:])
        self.count_port = Port(self.count.val)
        self.cpha_reg = Signal(False)
        self.cpol_reg = Signal(False)
        self.pulse_reg = Signal(False)
        self.cs_reg = Signal(self.bus.CS.val)

        self.div_val = Signal(intbv(0, 0, self.divider + 1))
예제 #32
0
    def __init__(self, system, bus, divider, width = 32, strict_sdoe = True):
        self.system = system
        self.bus = bus

        self.states = enum(
            "IDLE", "START", "PRE", "FIRST", "SECOND", "POST", "PULSE")
        self.state = Signal(self.states.IDLE)

        self.divider = divider
        self.strict_sdoe = strict_sdoe

        self.data_reg = Signal(intbv(0)[width:])

        self.count = Signal(intbv(0)[8:])
        self.count_port = Port(self.count.val)
        self.cpha_reg = Signal(False)
        self.cpol_reg = Signal(False)
        self.pulse_reg = Signal(False)
        self.cs_reg = Signal(self.bus.CS.val)

        self.div_val = Signal(intbv(0, 0, self.divider + 1))
예제 #33
0
def power(t_clk, t_reset, t_y_out, t_base, t_power, t_end, t_start):
    """

    :param t_clk:   clock
    :param t_reset: reset
    :param t_y_out: output
    :param t_base:
    :param t_power:
    :param t_end:
    :param t_start:
    :return:
    """
    state_t = enum('count', 'result')
    state = Signal(state_t.count)
    accumulator = Signal(intbv(1)[32:])
    counter = Signal(intbv(0)[32:])

    @always_seq(t_clk.posedge, reset=t_reset)
    def powers():
        """

        :return:
        """
        if state == state_t.count:
            if t_start == 1:
                t_end.next = 0
                accumulator.next = accumulator * t_base
                counter.next = counter + 1
                if counter >= t_power-1:
                    state.next = state_t.result
                    counter.next = 0
        elif state == state_t.result:
            t_end.next = 1
            t_y_out.next = accumulator
            accumulator.next = 1
            state.next = state_t.count
        else:
            raise ValueError("Undefined state")

    return instances()
예제 #34
0
def apb3_simple_slave(bus, status_led):
    bus_presetn = bus.presetn
    bus_pclk = bus.pclk
    bus_paddr = bus.paddr
    bus_psel = bus.psel
    bus_penable = bus.penable
    bus_pwrite = bus.pwrite
    bus_pwdata = bus.pwdata
    bus_pready = bus.pready
    bus_prdata = bus.prdata
    bus_pslverr = bus.pslverr

    state_t = enum('IDLE', 'DONE',)
    state = Signal(state_t.IDLE)

    counter = Signal(intbv(0)[len(bus_prdata):])

    @always_seq(bus_pclk.posedge, reset=bus_presetn)
    def state_machine():
        status_led.next = counter[0]
        if state == state_t.IDLE:
            if bus_penable and bus_psel:
                if bus_paddr[8:] == 0x40:
                    bus_pready.next = False
                    if bus_pwrite:
                        counter.next = bus_pwdata
                        state.next = state_t.DONE
                    else:
                        bus_prdata.next = counter
                        counter.next = counter + 1
                        state.next = state_t.DONE
                else:
                    state.next = state_t.DONE
            else:
                state.next = state_t.IDLE
        elif state == state_t.DONE:
            bus_pready.next = True
            state.next = state_t.IDLE

    return state_machine
예제 #35
0
def factorial(t_clk, t_reset, t_y_out, t_factorial, t_end, t_start):
    """

    :param t_clk:
    :param t_reset:
    :param t_y_out:
    :param t_factorial:
    :param t_end:
    :param t_start:
    :return:
    """
    state_t = enum('count', 'result')
    state = Signal(state_t.count)
    accumulator = Signal(intbv(1)[32:])
    counter = Signal(intbv(0)[32:])

    @always_seq(t_clk.posedge, reset=t_reset)
    def factorials():
        if state == state_t.count:
            if t_start == 1:
                t_end.next = 0
                if counter == 0:
                    counter.next = 1
                    accumulator.next = 1
                else:
                    accumulator.next = accumulator * counter
                    counter.next = counter + 1
                if counter > t_factorial-1:
                    state.next = state_t.result
                    counter.next = 0
        elif state == state_t.result:
            t_end.next = 1
            t_y_out.next = accumulator
            accumulator.next = 1
            state.next = state_t.count
        else:
            raise ValueError("Undefined state")

    return instances()
예제 #36
0
def uart_tx(clk_i, rst_i, tx_tick_i, dat_i, start_i, ready_o, tx_o):
	cnt = createSignal(0,4) # Contará de 0 a 9
	data = createSignal(0,8) # Ancho del FIFO
	tx_state = hdl.enum('IDLE','TX') # 2 estados de la FSM
	state = hdl.Signal(tx_state.IDLE) # Estado inicial de estoy ocioso
	

	@hdl.always_seq(clk_i.posedge, reset=rst_i)
	def tx_state_m(): # 50MHz
		if state == tx_state.IDLE:
			ready_o.next = 1
			if start_i: # Condición para cambiar de estado
				data.next = dat_i
				ready_o.next = 0
				state.next = tx_state.TX
			else:
				tx_o.next = 1

		elif state == tx_state.TX:
			if tx_tick_i: #Usando el divisor del clk_i
				if cnt >=1 and cnt <= 8:
					tx_o.next    = data[0]
					data.next   = hdl.concat(False, data[8:1])
					cnt.next = cnt + 1
				else: 
					tx_o.next = 0
					cnt.next = cnt + 1

				if cnt == 9:
						tx_o.next    = 1 
						ready_o.next = 1
						state.next   = tx_state.IDLE
						cnt.next = 0
						
		else:
			state.next = tx_state.IDLE

	return hdl.instances()
예제 #37
0
def my_sum(clk, reset, axis_s_raw, axis_m_sum):
    state_t = enum('COUNT', 'WRITE_COUNT', 'WRITE_SUM')
    accumulator = Signal(intbv(0)[32:])
    counter = Signal(intbv(0)[32:])
    state = Signal(state_t.COUNT)

    @always_seq(clk.posedge, reset=reset)
    def sum_proc():
        if state == state_t.COUNT:
            axis_m_sum.tvalid.next = 0
            axis_m_sum.tlast.next = 0
            axis_s_raw.tready.next = 1
            if axis_s_raw.tvalid == 1:
                accumulator.next = accumulator + axis_s_raw.tdata
                counter.next = counter + 1
                if axis_s_raw.tlast == 1:
                    state.next = state_t.WRITE_COUNT
        elif state == state_t.WRITE_COUNT:
            axis_s_raw.tready.next = 0
            axis_m_sum.tvalid.next = 1
            axis_m_sum.tlast.next = 0
            axis_m_sum.tdata.next = counter
            if axis_m_sum.tready == 1:
                state.next = state_t.WRITE_SUM
                counter.next = 0
        elif state == state_t.WRITE_SUM:
            axis_s_raw.tready.next = 0
            axis_m_sum.tvalid.next = 1
            axis_m_sum.tlast.next = 1
            axis_m_sum.tdata.next = accumulator
            if axis_m_sum.tready == 1:
                state.next = state_t.COUNT
                accumulator.next = 0
        else:
            raise ValueError("Undefined state")

    return instances()
예제 #38
0
    def test_dut_convertible_top_raises_with_enum_signals(self):
        '''enum signals passed to dut_convertible_top should raise

        Whilst enum signals are not supported for conversion, they should 
        raise a proper ValueError.
        '''
        simulated_input_cycles = 20

        args = self.default_args.copy()

        enum_names = ('a', 'b', 'c', 'd', 'e')
        enum_vals = enum(*enum_names)
        args['output'] = Signal(enum_vals.a)
        args['test_input'] = Signal(enum_vals.a)

        test_obj = SynchronousTest(self.identity_factory,
                                   self.identity_factory, args,
                                   self.default_arg_types)

        test_obj.cosimulate(simulated_input_cycles)

        self.assertRaisesRegex(ValueError,
                               'enum signals are currently unsupported',
                               test_obj.dut_convertible_top, 'foobarfile')
예제 #39
0
def uart_tx(clk_i, rst_i, tx_tick_i, dat_i, start_i, ready_o, tx_o):
    dat_r = createSignal(0, 8)
    bit_cnt = createSignal(0, 3)
    tx_state = hdl.enum('IDLE', 'START', 'DATA', 'STOP')
    state = hdl.Signal(tx_state.IDLE)

    @hdl.always_seq(clk_i.posedge, reset=rst_i)
    def fsm_proc():
        if state == tx_state.IDLE:
            ready_o.next = True
            if start_i:
                dat_r.next = dat_i
                state.next = tx_state.START
                ready_o.next = False
            else:
                tx_o.next = True
        elif state == tx_state.START:
            if tx_tick_i:
                tx_o.next = False
                state.next = tx_state.DATA
        elif state == tx_state.DATA:
            if tx_tick_i:
                tx_o.next = dat_r[0]
                dat_r.next = hdl.concat(False, dat_r[8:1])
                bit_cnt.next = bit_cnt + 1
                if bit_cnt == 7:
                    state.next = tx_state.STOP
        elif state == tx_state.STOP:
            if tx_tick_i:
                state.next = tx_state.IDLE
                tx_o.next = True
                ready_o.next = True
        else:
            state.next = tx_state.IDLE

    return hdl.instances()
예제 #40
0
파일: adc128s022.py 프로젝트: FelixVi/rhea
def adc128s022(glbl, fifobus, spibus, channel):
    """An interface to the ADC 128s022

    Arguments:
        glbl: global interface, clock, reset, enable, etc.
        fifobus: FIFO interface
        channel: channel to read
    """
    assert isinstance(fifobus, FIFOBus)
    assert isinstance(spibus, SPIBus)

    # local references
    clock, reset = glbl.clock, glbl.reset 
    # use the signals names in the datasheet, datashee names are 
    # from the device perspective, swapped here
    sclk, dout, din, csn = spibus()

    # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    # get a FIFO to put the samples in, each sample is 12 bits 
    # the upper 4 bits contain the channel that was sampled
    assert len(fifobus.write_data) == 16 
    assert len(fifobus.read_data) == 16 
    sample = Signal(intbv(0)[12:])
    
    fifo_inst = fifo_fast(glbl, fifobus, size=16)
    
    # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    # generate the sclk frequency, the clock needs to 
    # be between 1MHz and 3.2MHz.  To read all samples 
    # at the max rate 16*200e3 = 3.2MHz (200 kS/s)
    # the clock directly controls the conversion process
    max_frequency = 3.2e6  
    ndiv = int(ceil(clock.frequency / max_frequency))
    sample_rate = (clock.frequency / ndiv) / 16
    hightick = ndiv // 2
    lowtick = ndiv - hightick
    print("derived sample rate: {} ({}, {}) given a {} MHz clock".format(
          sample_rate, hightick, lowtick, clock.frequency/1e6))
        
    # depending on the system (global) clock frequency the sclk 
    # might not have 50% duty cycle (should be ok)
    # the datasheet indicates it requires at least a 40% cycle
    # for the high,
    # @todo: add a check for duty cycle
    clkcnt = Signal(intbv(hightick, min=0, max=ndiv))
    sclkpos, sclkneg = [Signal(bool(0)) for _ in range(2)]    
    
    @always_seq(clock.posedge, reset=reset)
    def beh_sclk_gen():
        # default case 
        sclkneg.next = False
        sclkpos.next = False
        
        # when the count expires toggle the clock 
        if clkcnt == 1:
            if sclk:
                sclk.next = False
                sclkneg.next = True
                clkcnt.next = lowtick
            else:
                sclk.next = True
                sclkpos.next = True
                clkcnt.next = hightick
        else:
            clkcnt.next = clkcnt-1
    
    # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    # state-machine to drive sample conversion
    states = enum('start', 'capture') 
    state = Signal(states.start)
    bitcnt = Signal(intbv(0, min=0, max=17))
    
    # these could be combined into a single register (future optimization)
    sregout = Signal(intbv(0)[16:])  # shift-out register 
    sregin = Signal(intbv(0)[16:])   # shift-in register 
    
    # the ADC will generate continuous samples, each sample retrieval
    # is 16 bits.  The following state-machine assumes there are a
    # couple clock cycles between sclk pos/neg strobes.  Should add
    # a check
    # @todo: check ndiv > 4 ( ?)
    @always_seq(clock.posedge, reset=reset)
    def beh_state_machine():
        fifobus.write.next = False
        
        if state == states.start:
            # @todo: wait some amount of time
            if sclkneg:
                bitcnt.next = 0
                state.next = states.capture
                csn.next = False
                sregout.next[14:11] = channel
            
        elif state == states.capture:
            if sclkpos:
                bitcnt.next = bitcnt + 1 
                sregin.next = concat(sregin[15:0], din)
            elif sclkneg:
                sregout.next = concat(sregout[15:0], '0')
            
            if bitcnt == 16:
                state.next = states.start
                sample.next = sregin[12:]   # this can be removed
                if not fifobus.full:
                    fifobus.write_data.next = sregin
                    fifobus.write.next = True
                else:
                    print("FIFO full dropping sample")
                    
    # assign the serial out bit to the msb of the shift-register
    assign(dout, sregout(15))
    
    return myhdl.instances()
예제 #41
0
파일: uart_model.py 프로젝트: cfelton/rhea
    def process(self, glbl, serin, serout):
        """ """

        clock, reset = glbl.clock, glbl.reset
        txq, rxq = self._txq, self._rxq

        maxbaud = clock.frequency / self.baudrate
        baudcnt = Signal(0)
        baudce, baudceh = Signal(bool(0)), Signal(bool(0))
        syncbaud = Signal(bool(0))

        @always_seq(clock.posedge, reset=reset)
        def mdlbaud():
            # @todo: need separate tx and rx baud strobes, the rx
            #        syncs the count to the start of a byte frame
            #        can't share a counter if rx and tx are at the
            #        same time.
            # this will not work if currently transmitting
            if syncbaud:
                baudcnt.next = 0
            else:
                if baudcnt > maxbaud:
                    baudcnt.next = 0
                    baudce.next = True
                    baudceh.next = False
                elif baudcnt == maxbaud // 2:
                    baudcnt.next = baudcnt + 1
                    baudce.next = False
                    baudceh.next = True
                else:
                    baudcnt.next = baudcnt + 1
                    baudce.next = False
                    baudceh.next = False

        # tx and rx states
        states = enum("wait", "start", "byte", "parity", "stop", "end")
        txbyte = Signal(intbv(0)[8:])
        txbitcnt = Signal(0)
        txstate = Signal(states.wait)

        @always_seq(clock.posedge, reset=reset)
        def mdltx():
            if txstate == states.wait:
                serout.next = True
                if not txq.empty():
                    txbyte.next = txq.get()
                    txbitcnt.next = 0
                    txstate.next = states.start

            elif txstate == states.start:
                if baudce:
                    serout.next = False
                    txstate.next = states.byte

            elif txstate == states.byte:
                if baudce:
                    serout.next = True if txbyte & 0x01 else False
                    txbitcnt.next = txbitcnt + 1
                    txbyte.next = txbyte >> 1

                elif txbitcnt == 8:
                    txbitcnt.next = 0
                    txstate.next = states.stop

            elif txstate == states.stop:
                if baudce:
                    serout.next = True
                    txbitcnt.next = txbitcnt + 1
                elif txbitcnt.next == self.stopbits:
                    txstate.next = states.end

            elif txstate == states.end:
                txstate.next = states.wait

        rxbyte = Signal(intbv(0)[8:])
        rxbitcnt = Signal(0)
        rxstate = Signal(states.wait)
        _serin = Signal(bool(1))
        serin_posedge, serin_negedge = Signal(bool(0)), Signal(bool(0))

        @always(clock.posedge)
        def mdlrxd():
            _serin.next = serin

        @always_comb
        def mdledges():
            serin_posedge.next = False
            serin_negedge.next = False
            if not _serin and serin:
                serin_posedge.next = True
            elif _serin and not serin:
                serin_negedge.next = True

        @always_seq(clock.posedge, reset=reset)
        def mdlrx():
            syncbaud.next = False

            if rxstate == states.wait:
                if serin_negedge:
                    rxstate.next = states.start
                    syncbaud.next = True

            elif rxstate == states.start:
                if baudceh:
                    rxstate.next = states.byte
                    rxbitcnt.next = 0

            elif rxstate == states.byte:
                if baudceh:
                    rxbyte.next[rxbitcnt] = serin
                    rxbitcnt.next = rxbitcnt + 1
                elif rxbitcnt == 8:
                    rxstate.next = states.stop
                    rxbitcnt.next = 0

            elif rxstate == states.stop:
                if baudceh:
                    assert serin
                    rxbitcnt.next = rxbitcnt + 1
                elif rxbitcnt == self.stopbits:
                    rxstate.next = states.end

            elif rxstate == states.end:
                self._rxq.put(int(rxbyte))
                rxstate.next = states.wait

        return myhdl.instances()
예제 #42
0
파일: mem_test.py 프로젝트: FelixVi/rhea
def mem_test(glbl, memmap, progress, error, done,
        start_address=0x00000000, end_address=0xFFFFFFFF):
    """
    This module performs a memory test over the memory-map bus
    """
    if end_address > memmap.addr.max:
        end_address = memmap.addr.max

    States = enum('init', 'write', 'write_ack', 'compare_read',
                  'compare', 'end')
    state = Signal(States.init)

    clock, reset = glbl.clock, glbl.reset

    rglbl, randgen = random_generator.portmap.values()
    randgen.data = Signal(memmap.wdata.val)
    rglbl.clock, rglbl.reset = clock, reset
    rand_inst = random_generator(glbl, randgen)

    @always_seq(clock.posedge, reset=reset)
    def beh():

        # defaults
        randgen.load.next = False
        randgen.enable.next = False

        if state == States.init:
            randgen.load.next = True
            randgen.enable.next = True
            error.next = False
            progress.next = 0
            memmap.addr.next = start_address

        elif state == States.write:
            progress.next = 1
            memmap.write.next = True
            memmap.wdata.next = randgen.data
            state.next = States.write.ack
            randgen.enable.next = True

        elif state == States.write_ack:
            memmap.write.next = False
            if memmap.addr == end_address-1:
                randgen.load.next = True
                state.next = States.compare_read
                memmap.addr.next = start_address
            else:
                memmap.addr.next = memmap.addr + 1
                state.next = States.write

        elif state == States.compare_read:
            progress.next = 2
            memmap.read.next = True

        elif state == States.compare:
            memmap.read.next = False
            randgen.enable.next = True
            if memmap.rdata != randgen.data:
                error.next = True

            if memmap.addr == end_address-1:
                state.next = States.end
            else:
                memmap.addr.next = memmap.addr + 1
                state.next = States.compare.read

        elif state == States.end:
            pass

        else:
            assert False, "Invalid state %s" % (state,)

    return myhdl.instances()
예제 #43
0
def exciter(
        resetn,
        system_clock,
        pclk,
        paddr,
        psel,
        penable,
        pwrite,
        pwdata,
        pready,
        prdata,
        pslverr,
        dac_clock,
        dac_data):

    ####### FIFO ############
    # Read
    re = Signal(bool(False))
    rclk = system_clock
    Q = Signal(intbv(0)[32:])

    # Write
    we = Signal(bool(False))
    wclk = pclk
    data = Signal(intbv(0)[32:])

    # Threshold
    full = Signal(bool(False))
    full.driven = 'wire'
    afull = Signal(bool(False))
    afull.driven = 'wire'
    empty = Signal(bool(False))
    empty.driven = 'wire'
    aempty = Signal(bool(False))
    aempty.driven = 'wire'

    fifo_args = resetn, re, rclk, Q, we, wclk, data, full, afull, \
        empty, aempty
    fifo = FIFO(*fifo_args,
        width=32,
        depth=1024)


    ######### RESAMPLER ###########

    ######### INTERLEAVER #########
    in_phase = Signal(bool(0))
    sample_i = Signal(intbv(0, 0, 2**10))
    sample_q = Signal(intbv(0, 0, 2**10))

    ########## STATE MACHINE ######
    state_t = enum('IDLE', 'WRITE_SAMPLE', 'DONE',)
    state = Signal(state_t.IDLE)

    ############ TX EN ###########
    txen = Signal(bool(0))

    @always_seq(pclk.posedge, reset=resetn)
    def state_machine():
        if state == state_t.IDLE:
            if penable and psel and pwrite:
                if paddr[8:] == 0x00:
                    state.next = state_t.WRITE_SAMPLE
                    pready.next = 0
                    we.next = 1
                    data.next = pwdata
                    if full:
                        raise OverrunError
                elif paddr[8:] == 0x01:
                    print 'hi', pwdata
                    txen.next = pwdata[0]
            elif psel and not pwrite:
                pass

        elif state == state_t.WRITE_SAMPLE:
            we.next = 0
            state.next = state_t.DONE
            
        elif state == state_t.DONE:
            pready.next = 1
            state.next = state_t.IDLE

    @always(system_clock.posedge)
    def resampler():
        if txen:  # Update the sample out of phase, locking
            if re:
                sample_i.next = Q[9:]
                sample_q.next = Q[32:23]
            re.next = not re

    @always(system_clock.posedge)
    def interleaver():
        if txen:
            dac_data.next = sample_i[10:2] if in_phase else sample_q[10:2]
            dac_clock.next = not in_phase
            in_phase.next = not in_phase

    return fifo, state_machine, resampler, interleaver
예제 #44
0
        self.outp = Signal(bool(0))
        self.inp = Signal(bool(0))
        self.br_op = Signal(bool(0))
        self.jal = Signal(bool(0))
        self.loadh = Signal(bool(0))
        self.indls = Signal(bool(0))
        self.signals = [self.al_ena, self.ah_ena, self.log_add, self.add_sub, self.shr, self.sel_imm, self.store, \
                        self.outp, self.inp, self.br_op, self.jal, self.loadh, self.indls]

class inpSignal():
    def __init__(self):
        self.rd_data = Signal(intbv(0)[16:])


class outpSignal():
    def __init__(self):
        self.wr_data = Signal(intbv(0)[16:])
        self.wr_strobe = Signal(bool(0))
        self.rd_strobe = Signal(bool(0))
        self.io_addr = Signal(intbv(0)[16:])             



dec_op_type = enum('al_ena', 'ah_ena', 'log_add', 'add_sub',
                    'shr', 'sel_imm', 'store', 'outp', 'inp', 'br_op', 'jal',
                    'loadh', 'indls')

alu_op_type = enum('NOP', 'LD', 'AND', 'OR', 'XOR')

IM_BITS = 9
DM_BITS = 8 
예제 #45
0
파일: lt24lcd.py 프로젝트: Godtec/rhea
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
예제 #46
0
def command_bridge(glbl, fifobus, mmbus):
    """ Convert a command packet to a memory-mapped bus transaction
    
    This module will decode the incomming packet and start a bus 
    transaction, the memmap_controller_basic is used to generate
    the bus transactions, it convertes the Barebone interface to 
    the MemoryMapped interface being used. 
    
    The variable length command packet is:
        00: 0xDE
        01: command byte (response msb indicates error)
        02: address high byte 
        03: address byte 
        04: address byte 
        05: address low byte 
        06: length of data (max length 256 bytes)
        07: 0xCA   # sequence number, fixed for now
        08: data high byte 
        09: data byte
        10: data byte
        11: data low byte
        Fixed 12 byte packet currently supported, future
        to support block write/reads up to 256-8-4
        12 - 253: write / read (big-endian)
        @todo: last 2 bytes crc
    The total packet length is 16 + data_length

    Ports:
      glbl: global signals and control
      fifobus: FIFOBus interface, read and write path
      mmbus: memory-mapped bus (interface)

    this module is convertible
    """
    assert isinstance(fifobus, FIFOBus)
    assert isinstance(mmbus, MemoryMapped)

    clock, reset = glbl.clock, glbl.reset 
    bb = Barebone(glbl, data_width=mmbus.data_width,
                  address_width=mmbus.address_width)
    
    states = enum(
        'idle',
        'wait_for_packet',   # receive a command packet
        'check_packet',      # basic command check
        'write',             # bus write
        'write_end',         # end of the write cycle
        'read',              # read bus cycles for response
        'read_end',          # end of the read cycle
        'response',          # send response packet
        'response_full',     # check of RX FIFO full
        'error',             # error occurred
        'end'                # end state
    )

    state = Signal(states.idle)
    ready = Signal(bool(0))
    error = Signal(bool(0))
    bytecnt = intbv(0, min=0, max=256)

    # known knows
    pidx = (0, 7,)
    pval = (0xDE, 0xCA,)
    assert len(pidx) == len(pval)
    nknown = len(pidx)

    bytemon = Signal(intbv(0)[8:])

    # only supporting 12byte packets (single read/write) for now
    packet_length = 12
    data_offset = 8
    packet = [Signal(intbv(0)[8:]) for _ in range(packet_length)]
    command = packet[1]
    address = ConcatSignal(*packet[2:6])
    data = ConcatSignal(*packet[8:12])
    datalen = packet[6]

    # convert generic memory-mapped bus to the memory-mapped interface
    # passed to the controller
    mmc_inst = controller_basic(bb, mmbus)

    @always_comb
    def beh_fifo_read():
        if ready and not fifobus.empty:
            fifobus.read.next = True
        else:
            fifobus.read.next = False

    @always_seq(clock.posedge, reset=reset)
    def beh_state_machine():

        if state == states.idle:
            state.next = states.wait_for_packet
            ready.next = True
            bytecnt[:] = 0

        elif state == states.wait_for_packet:
            if fifobus.read_valid:
                # check the known bytes, if the values is unexpected
                # goto the error state and flush all received bytes.
                for ii in range(nknown):
                    idx = pidx[ii]
                    val = pval[ii]
                    if bytecnt == idx:
                        if fifobus.read_data != val:
                            error.next = True
                            state.next = states.error

                packet[bytecnt].next = fifobus.read_data
                bytecnt[:] = bytecnt + 1

            # @todo: replace 20 with len(CommandPacket().header)
            if bytecnt == packet_length:
                ready.next = False
                state.next = states.check_packet

        elif state == states.check_packet:
            # @todo: some packet checking
            # @todo: need to support different address widths, use
            # @todo: `bb` attributes to determine which bits to assign
            bb.per_addr.next = address[32:28]
            bb.mem_addr.next = address[28:0]
            assert bb.done
            bytecnt[:] = 0

            if command == 1:
                state.next = states.read
            elif command == 2:
                bb.write_data.next = data
                state.next = states.write
            else:
                error.next = True
                state.next = states.error

        elif state == states.write:
            # @todo: add timeout
            if bb.done:
                bb.write.next = True
                state.next = states.write_end

        elif state == states.write_end:
            bb.write.next = False
            if bb.done:
                state.next = states.read

        elif state == states.read:
            # @todo: add timeout
            if bb.done:
                bb.read.next = True
                state.next = states.read_end

        elif state == states.read_end:
            bb.read.next = False
            if bb.done:
                # @todo: support different data_width bus
                packet[data_offset+0].next = bb.read_data[32:24]
                packet[data_offset+1].next = bb.read_data[24:16]
                packet[data_offset+2].next = bb.read_data[16:8]
                packet[data_offset+3].next = bb.read_data[8:0]
                state.next = states.response

        elif state == states.response:
            fifobus.write.next = False
            if bytecnt < packet_length:
                if not fifobus.full:
                    fifobus.write.next = True
                    fifobus.write_data.next = packet[bytecnt]
                    bytecnt[:] = bytecnt + 1
                state.next = states.response_full
            else:
                state.next = states.end
                
        elif state == states.response_full:
            fifobus.write.next = False
            state.next = states.response

        elif state == states.error:
            if not fifobus.read_valid:
                state.next = states.end
                ready.next = False

        elif state == states.end:
            error.next = False
            ready.next = False
            state.next = states.idle

        else:
            assert False, "Invalid state %s" % (state,)

        bytemon.next = bytecnt

    return beh_fifo_read, mmc_inst, beh_state_machine
예제 #47
0
from myhdl import block, always_seq, always_comb, Signal, intbv, enum, \
    ResetSignal
from gemac.crc32 import crc32

txstate = enum('IDLE', 'PREAMBLE', 'SFD', 'FIRSTBYTE', 'INFRAME', 'PADDING',
               'ERROR', 'CRC1', 'CRC2', 'CRC3', 'CRC4', 'SENDPAUSE')


@block
def txengine(txclientintf, txgmii_intf, txflowintf, txconfig, sysreset):
    """Transmit Engine.

    Accepts Ethernet frame data from the Client Transmitter interface,
    adds preamble to the start of the frame, add padding bytes and frame
    check sequence. It ensures that the inter-frame spacing between successive
    frames is at least the minimum specified. The frame is then converted
    into a format that is compatible with the GMII and sent to the GMII Block.

    Args:
        txclientintf (TxClientFIFO) - transmit streaming data interface from transmit FIFO.
        txgmii_intf (TxGMII_Interface) - transmit streaming data interface to GMII.
        flow_intf (TxFlowInterface) - transmit flow control interface.
        txconfig (Signal/intbv)(32 bit) - configregisters - Transmitter configuration word.
            See Xilinx_UG144 pdf, Table 8.5, Pg-80 for detailed description.
        reset - System reset
    """

    state = Signal(txstate.IDLE)
    curbyte = Signal(intbv(1, min=0, max=10000))
    pausereq = Signal(bool(0))
    reset = ResetSignal(0, active=0, async=True)
예제 #48
0
파일: defines.py 프로젝트: wware/myblaze
OPG_ADD = 0b00      # 0b00ixxx add, sub, cmp
OPG_CMP = 0b000101  # 0b000101 cmp
OPG_MUL = 0b01000   # 0b01i000 integer multiply
OPG_BSF = 0b01001   # 0b01i001 barrel shift
OPG_DIV = 0b01010   # 0b010010 integer divide
OPG_FSL = 0b01011   # 0b01d011 fsl command
OPG_FLT = 0b01110   # 0b010110 float
OPG_LOG = 0b100     # 0b10i0xx logic and pattern compare
OPG_IMM = 0b101100  # 0b101100 imm
OPG_EXT = 0b100100  # 0b100100 shift right, sext, cache
OPG_SPR = 0b100101  # 0b100101 move from/to special register
OPG_RET = 0b101101  # 0b101101 return
OPG_BRU = 0b10110   # 0b10i110 unconditional branch
OPG_BCC = 0b10111   # 0b10i111 conditional branch
OPG_MEM = 0b11      # 0b11ixxx load, store


alu_operation = enum('ALU_ADD', 'ALU_OR', 'ALU_AND', 'ALU_XOR',
                     'ALU_SHIFT', 'ALU_SEXT8', 'ALU_SEXT16', #)
                     'ALU_MUL', 'ALU_BS')
src_type_a = enum('REGA', 'NOT_REGA', 'PC', 'REGA_ZERO')
src_type_b = enum('REGB', 'NOT_REGB', 'IMM', 'NOT_IMM')
carry_type = enum('C_ZERO', 'C_ONE', 'ALU', 'ARITH')
branch_condition = enum('BEQ', 'BNE', 'BLT', 'BLE', 'BGT', 'BGE', 
                        'BRU', 'NOP')
transfer_size_type = enum('WORD', 'HALFWORD', 'BYTE')

### EOF ###
# vim:smarttab:sts=4:ts=4:sw=4:et:ai:tw=80:

예제 #49
0
파일: controller.py 프로젝트: FelixVi/rhea
def controller_basic(generic, memmap):
    """
    (arguments == ports)
    Arguments:
        generic: barebone interface
        memmap: any memory-map interface

    This module contains a basic memory map controller, the
    barebone bus can be used to start a bus transaction to
    any of the other implemented memory-mapped buses.

    """

    assert isinstance(generic, Barebone)
    assert isinstance(memmap, MemoryMapped)

    states = enum('idle', 'wait', 'write', 'writeack', 'read',
                  'readdone', 'done', 'end')
    state = Signal(states.idle)

    timeout_max = 33
    tocnt = Signal(intbv(0, min=0, max=timeout_max))

    # map the generic bus to the bus in use
    conv_inst = memmap.map_from_generic(generic)

    @always_seq(memmap.clock.posedge, reset=memmap.reset)
    def beh_sm():

        # ~~~[Idle]~~~
        if state == states.idle:
            if not generic.done:
                state.next = states.wait
            elif generic.write:
                state.next = states.write
            elif generic.read:
                state.next = states.read

        # ~~~[Wait]~~~
        elif state == states.wait:
            if generic.done:
                tocnt.next = 0
                if generic.write:
                    state.next = states.done
                elif generic.read:
                    state.next = states.readdone

        # ~~~[Write]~~~
        elif state == states.write:
            state.next = states.done
            tocnt.next = 0

        # ~~~[Read]~~~
        elif state == states.read:
            state.next = states.readdone

        # ~~~~[ReadDone]~~~
        elif state == states.readdone:
            if generic.done:
                state.next = states.done

        # ~~~[Done]~~~
        elif state == states.done:
            # wait for transaction signals to be release
            if not (generic.write or generic.read):
                state.next = states.idle

        # ~~~[]~~~
        else:
            assert False, "Invalid state %s" % (state,)

    return conv_inst, beh_sm
예제 #50
0
파일: fifo.py 프로젝트: n8ohu/whitebox
def fifo(
    resetn,
    re,
    rclk,
    Q,
    we,
    wclk,
    data,
    full,
    afull,
    empty,
    aempty,
    afval,
    aeval,
    wack,
    dvld,
    overflow,
    underflow,
    rdcnt,
    wrcnt,
    **kwargs
):
    """Main Fifo object.

    This only works as a simulation; when it is transpiled into Verilog,
    an auto-generated IP Core is used instead.  To see how to build the
    the IP core yourself with Libero IDE, check out this video (TODO).
    """

    width = kwargs["width"]
    depth = kwargs["depth"]
    write_active = kwargs.get("write_active", active_high)
    write_edge = kwargs.get("write_edge", posedge)
    read_active = kwargs.get("read_active", active_high)
    read_edge = kwargs.get("read_edge", posedge)
    reset_active = kwargs.get("reset_active", active_low)
    reset_edge = kwargs.get("reset_edge", negedge)
    threshold = kwargs.get("threshold", None)
    max_threshold = kwargs.get("max_threshold", None)
    state_t = enum("IDLE", "ACCESS")
    rstate = Signal(state_t.IDLE)
    verbose = kwargs.get("verbose", False)

    _fifo = kwargs.get("load", [])

    Q_pipe1 = Signal(intbv(0)[len(Q) :])
    dvld_pipe1 = Signal(bool(0))
    Q_pipe2 = Signal(intbv(0)[len(Q) :])
    dvld_pipe2 = Signal(bool(0))

    @always_seq(write_edge(wclk), reset=resetn)
    def write():
        afull.next = len(_fifo) >= afval
        full.next = len(_fifo) >= depth
        if write_active(we):
            if len(_fifo) >= depth:
                if verbose:
                    print "overflow"
                overflow.next = True
                wack.next = False
            else:
                if verbose:
                    print "adding %d" % int(data)
                _fifo.insert(0, int(data))
                overflow.next = False
                wack.next = True
                wrcnt.next = wrcnt - 1
                rdcnt.next = rdcnt + 1
        else:
            overflow.next = False
            wack.next = False

    @always_seq(read_edge(rclk), reset=resetn)
    def read():
        aempty.next = len(_fifo) <= aeval
        empty.next = len(_fifo) == 0
        if read_active(re):
            if len(_fifo) == 0:
                if verbose:
                    print "underflow"
                underflow.next = True
                dvld_pipe1.next = False
            else:
                if verbose:
                    print "removing %d" % _fifo[-1]
                Q_pipe1.next = _fifo.pop()
                dvld_pipe1.next = True
                underflow.next = False
                wrcnt.next = wrcnt + 1
                rdcnt.next = rdcnt - 1
        else:
            underflow.next = False
            dvld_pipe1.next = False

        if dvld_pipe1:
            Q_pipe2.next = Q_pipe1
            dvld_pipe2.next = True
        else:
            dvld_pipe2.next = False

        if dvld_pipe2:
            Q.next = Q_pipe2
            dvld.next = True
        else:
            dvld.next = False

    return instances()
예제 #51
0
파일: _uart.py 프로젝트: robtaylor/rhea
def uartrx(glbl, fbusrx, rx, baudce16):
    """ """
    clock, reset = glbl.clock, glbl.reset

    states = enum('wait', 'byte', 'stop', 'end')
    state = Signal(states.wait)
    rxbyte = Signal(intbv(0)[8:])
    bitcnt = Signal(intbv(0, min=0, max=9))

    # signals use do find the mid bit
    rxd = Signal(bool(0))
    mcnt = Signal(modbv(0, min=0, max=16))
    midbit = Signal(bool(0))
    rxinprog = Signal(bool(0))

    # get the middle of the bits, always sync to the beginning
    # (negedge) of the start bit
    @always(clock.posedge)
    def rtlmid():
        rxd.next = rx
        if (rxd and not rx) and state == states.wait:
            mcnt.next = 0
            rxinprog.next = True
        elif rxinprog and state == states.end:
            rxinprog.next = False
        elif baudce16:
            mcnt.next = mcnt + 1

        # 7 or 8 doesn't really matter
        if rxinprog and mcnt == 7 and baudce16:
            midbit.next = True
        else:
            midbit.next = False

    @always_seq(clock.posedge, reset=reset)
    def rtlrx():
        # defaults
        fbusrx.wr.next = False

        # state handlers
        if state == states.wait:
            if midbit and not rx:
                state.next = states.byte

        elif state == states.byte:
            if midbit:
                rxbyte.next[bitcnt] = rx
                bitcnt.next = bitcnt + 1
            elif bitcnt == 8:
                state.next = states.stop
                bitcnt.next = 0

        elif state == states.stop:
            if midbit:
                #assert rx
                state.next = states.end
                fbusrx.wr.next = True
                fbusrx.wdata.next = rxbyte

        elif state == states.end:
            state.next = states.wait
            bitcnt.next = 0

    return rtlmid, rtlrx
예제 #52
0
def get_utilization(fn=None):    
    """ parse the device resource utilization from the logs

    @todo : the following is fairly ugly and not the most 
       reliable.  There are xml files create (xrp) that would
       be a better source for the utilization - once the xlm
       package is understood these reports can be used instead
       of the log.
    """


    log = open(fn, 'r')
    info = {}
    info['syn'] = {}
    fmax = []
    States = enum('search', 'slc_util', 'io_util', 'ip_util')
    state = States.search

    for ln in log:
        if ln.find('Maximum Frequency:') != -1:
            if len(ln.split(':')) < 3:
                   continue
            fstr = ln.split(':')[2]
            fstr = fstr.replace(')', '')        
            fstr = fstr.replace(' ', '')
            fstr = fstr.strip()
            fmax.append(fstr)
    
        # @todo: probalby better to parse the XML files!
        # synthesis gives results in a table
        #   Slice Logic Utilization:
        #   IO Utilization:
        #   Specific Feature Utilization:
        #    <name>: X out of Y <percent>
        
        #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        if state == States.search:
            if ln.find('Slice Logic Utilization') != -1:
                state = States.slc_util
                lncnt = 1  
                #print(ln)
            elif ln.find('Specific Feature Utilization') != -1:
                state = States.ip_util
                lncnt = 1
                #print(ln)
        
        #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        elif state == States.slc_util:
            ln = ln.strip()
        
            if lncnt in (1,7):
                # check sliptls
                print(ln)
                sp1 = ln.split(':')
                sp2 = sp1[1].split()
                if len(sp1) != 2 or len(sp2) != 5:
                    state = States.search
                    continue  # jump to the next line
        
                #print(lncnt, ln)
                nm,outof = ln.split(':')
                x,out,of,y,p = outof.split()
                #print(x,out,of,y,p)
                x = x.replace(',', '')
                y = y.replace(',', '')
                p = p.replace('%', '')
        
            if lncnt == 1:
                info['syn']['reg'] = tuple(map(int, (x,y,p,)))
            elif lncnt == 7:
                info['syn']['lut'] = tuple(map(int, (x,y,p,)))
            elif lncnt >= 10:
                state = States.search
        
            lncnt += 1
        
        #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        elif state == States.ip_util:
            ln = ln.strip()
        
            if lncnt in (1,2,16):
                #print(ln)
                # check sliptls
                sp1 = ln.split(':')
                if len(sp1) != 2:
                    state = States.search                    
                    continue
                sp2 = sp1[1].split()
                if len(sp2) != 5:
                    state = States.search
                    continue  # jump to the next line
        
                #print(lncnt, ln)
                nm,outof = ln.split(':')
                x,out,of,y,p = outof.split()
                #print(x,out,of,y,p)
                x = x.replace(',', '')
                y = y.replace(',', '')
                p = p.replace('%', '')
        
            if lncnt == 1:    # RAMB16B
                pass
            elif lncnt == 2:  # RAMB8B
                pass
            elif lncnt == 16: # DSP48
                #print(x,out,of,y,p)
                info['syn']['dsp'] = tuple(map(int, (x,y,p,)))
            elif lncnt >= 22:
                state = States.search
            lncnt += 1

        # end of parsing state-machine
        
    if len(fmax) > 0:
        info['fmax'] = fmax[-1]
    else:
        info['fmax'] = -1
    
    return info
예제 #53
0
파일: sdram_intf.py 프로젝트: Godtec/rhea
    def __init__(self, num_banks=4, addr_width=12, data_width=16, ver='sdr'):

        # signals in the interface
        self.frequency = 0.            # @todo:
        self.clk = Signal(bool(0))     # interface clock
        self.cke = Signal(bool(0))     # clock enable
        self.cs = Signal(bool(0))      # chip select
        self.cas = Signal(bool(0))     # column address strobe
        self.ras = Signal(bool(0))     # row address strobe
        self.we = Signal(bool(0))      # write strobe
        self.bs = Signal(intbv(0)[2:]) # bank select
        self.addr = Signal(intbv(0)[addr_width:])
        self.dqm = Signal(bool(0))
        self.dqml = Signal(bool(0))
        self.dqmh = Signal(bool(0))
        self.dq = TristateSignal(intbv(0)[data_width:])
        # the controller and SDRAM bi-dir bus drivers
        self.dqo = self.dq.driver()
        self.dqi = self.dq.driver()

        # the following separate write and read buses are
        # not used in an actual device.  They are used by
        # the model for debug and testing.
        self.wdq = Signal(intbv(0)[data_width:])
        self.rdq = Signal(intbv(0)[data_width:])

        # configurations for the SDRAM interfacing with
        self.num_banks = num_banks
        self.addr_width = addr_width
        self.data_width = data_width
        self.ver = ver

        # saved read, transactors save the read data here
        self.read_data = None

        # generic commands for a DRAM, override these for specific (S)DRAM devices
        # @todo: attribute of the interface or global definition?
        self.Commands = enum(
            "NOP",  # no operation, ignore all inputs
            "ACT",  # activate a row in a particular bank
            "RD",   # read, initiate a read burst to an active row
            "WR",   # write, initial a write burst to an active row
            "PRE",  # precharge, close a row in a particular bank
            "REF",  # refresh, start a refresh operation
            # extended commands (???)
            "LMR",  # load mode register
            )

        # extract the default timing parameters, all parameters in ns
        # but convert to "ps" like ticks.
        cycles = {}
        for k, v in self.timing.items():
            cycles[k] = (v * (self.clock_frequency / 1e9))
            # @todo: if 'ddr' in self.ver: cycles[k] *= 2

        # add the cycle numbers to the
        for k, v in cycles.items():
            # majority of the timing parameters are maximum times,
            # floor error on the side of margin ...
            self.__dict__['cyc_'+k] = int(floor(v))

        # convert the time parameters to simulation ticks
        # @todo: where to get the global simulation step?
        for k, v in self.timing.items():
            self.__dict__['tick_'+k] = int(ceil(v * 1000))
예제 #54
0
def adc128s022_model(spibus, analog_channels, vref_pos=3.3, vref_neg=0.):
    """
    This is a model of the ADC128S022 A/D converter.  It will emulated
    the behavior described in the datasheet.
    """
    assert isinstance(analog_channels, list) and len(analog_channels) == 8 
    
    # use the signals names in the datasheet, names from the device
    # perspective
    sclk, dout, din, csn = spibus()
    
    states = enum('start', 'track', 'hold')
    state = Signal(states.start)

    monbits = Signal(intbv(0)[16:])
    monsmpl = Signal(intbv(0)[16:])
    monbcnt = Signal(intbv(0)[16:])

    @instance
    def beh():
        sample = intbv(0xAA)[16:]
        bitcnt, bitsin = 0, intbv(0)[16:]
        nextch = 0
        dout.next = 0

        while True:
            if state == states.start:
                yield delay(10)
                if not csn:
                    state.next = states.track
                    bitcnt = 15
                    dout.next = 0
                monbcnt.next = bitcnt
                    
            elif state == states.track:
                yield sclk.posedge
                bitsin[bitcnt] = int(din)
                bitcnt -= 1
                monbcnt.next = bitcnt
                # @todo: determine a reasonable model of the track/capture
                levels = [float(val) for val in analog_channels]
                yield sclk.negedge
                if bitcnt == 12:
                    ch = nextch
                    state.next = states.hold
                    # the real converter converts the sample over the next
                    # 12 clock cycles, convert instantly (is fine)
                    sample = convert(levels[ch], (vref_neg, vref_pos))
                    monsmpl.next = sample
                    print("converted channel {} from {} to {:04X}".format(
                          int(ch), float(levels[ch]), int(sample)))

            elif state == states.hold:
                yield sclk.posedge
                bitsin[bitcnt] = int(din)
                bitcnt -= 1
                if bitcnt == 10:
                    nextch = bitsin[14:11]
                    # print("  captured next channel {} ({:04X})".format(nextch, int(bitsin)))
                monbcnt.next = bitcnt
                yield sclk.negedge
                dout.next = sample[bitcnt]
                # print("{:8d}: sample[{:2d}] = {:4d}, {}->{}".format(
                #       now(), bitcnt, int(sample), int(dout.val), int(dout.next)))
                if bitcnt == 0:
                    state.next = states.start
                    yield sclk.posedge  # let the last bit clock in

            # need signals to update before next pass through
            yield delay(1)

    @always(sclk.posedge)
    def mon():
        monbits.next = concat(monbits[15:0], din)
                    
    return instances()
예제 #55
0
파일: loopback.py 프로젝트: ImArcangel/UART
             FIFO_DEPTH=1024,
             CLK_BUS=50_000_000,
             BAUD_RATE=115200):

    tx_start = createSignal(0, 1)  # entrada tx_start_i del UART
    tx_ready = createSignal(0, 1)  # salida tx_ready_o del UART
    rx_ready = createSignal(0, 1)  # salida rx_ready_o del UART
    rx_dat = createSignal(
        0, 8)  # salida rx_dat_o del UART y entrada dat_i del FIFO
    dequeue = createSignal(0, 1)  # entrada dequeue_i del FIFO
    empty = createSignal(0, 1)  #salida empty_o del FIFO
    full = createSignal(0, 1)  # salida full_o del FIFO
    dat = createSignal(0, 8)  # entrada dat_i del tx y salida dat_o del FIFO
    value = createSignal(
        0, 11)  # salida count_o del FIFO y entrada value_i del Driver7Seg
    l_state = hdl.enum(
        'RX', 'TX')  #Declaracion para dos estados, recibiendo y enviando.
    state = hdl.Signal(l_state.RX)

    uart = UART(clk_i=clk_i,
                rst_i=rst_i,
                tx_dat_i=dat,
                tx_start_i=tx_start,
                tx_ready_o=tx_ready,
                tx_o=tx_o,
                rx_dat_o=rx_dat,
                rx_ready_o=rx_ready,
                rx_i=rx_i,
                CLK_BUS=CLK_BUS,
                BAUD_RATE=BAUD_RATE)

    fifo = FIFO(clk_i=clk_i,
예제 #56
0
def ICache(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:  Enable flush 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_wbm address width
        TAG_WIDTH            = LIMIT_WIDTH - WAY_WIDTH  # tag size
        TAGMEM_WAY_WIDTH     = TAG_WIDTH + 1         # Add the valid bit
        TAGMEM_WAY_VALID     = TAGMEM_WAY_WIDTH - 1  # Valid bit index
        TAG_LRU_WIDTH        = (WAYS * (WAYS - 1)) >> 1  # (N*(N-1))/2
        # --------------------------------------------------------------------------
        ic_states = enum('IDLE',
                         'READ',
                         'FETCH',
                         'FLUSH',
                         'FLUSH_LAST')

        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)

        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)]

        state              = Signal(ic_states.IDLE)
        n_state            = Signal(ic_states.IDLE)

        busy               = Signal(False)

        miss               = Signal(False)
        miss_w             = Signal(modbv(0)[WAYS:])
        miss_w_and         = Signal(False)
        final_fetch        = Signal(False)
        final_flush        = 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:])

        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)

        refill_addr        = Signal(modbv(0)[LIMIT_WIDTH - 2:])
        refill_valid       = Signal(False)
        n_refill_addr      = Signal(modbv(0)[LIMIT_WIDTH - 2:])
        n_refill_valid     = Signal(False)

        flush_addr         = Signal(modbv(0)[SET_WIDTH:])
        flush_we           = Signal(False)
        n_flush_addr       = Signal(modbv(0)[SET_WIDTH:])
        n_flush_we         = Signal(False)

        @always_comb
        def assignments():
            final_fetch.next        = (refill_addr[BLOCK_WIDTH - 2:] == modbv(-1)[BLOCK_WIDTH - 2:]) and mem_wbm.ack_i and mem_wbm.stb_o and mem_wbm.cyc_o
            lru_select.next         = lru_pre
            current_lru.next        = lru_out
            access_lru.next         = ~miss_w
            busy.next               = state != ic_states.IDLE
            final_flush.next        = flush_addr == 0

        @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_read = cpu_wbs.cyc_i and cpu_wbs.stb_i and not cpu_wbs.we_i
            miss.next  = miss_w_and and valid_read and not invalidate

        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 next_state_logic():
            n_state.next = state
            if state == ic_states.IDLE:
                if invalidate:
                    # cache flush
                    n_state.next = ic_states.FLUSH
                elif cpu_wbs.cyc_i and not cpu_wbs.we_i:
                    # miss: refill line
                    n_state.next = ic_states.READ
            elif state == ic_states.READ:
                if not miss:
                    # miss: refill line
                    n_state.next = ic_states.IDLE
                else:
                    n_state.next = ic_states.FETCH
            elif state == ic_states.FETCH:
                # fetch a line from memory
                if final_fetch:
                    n_state.next = ic_states.IDLE
            elif state == ic_states.FLUSH:
                # invalidate tag memory
                if final_flush:
                    n_state.next = ic_states.FLUSH_LAST
                else:
                    n_state.next = ic_states.FLUSH
            elif state == ic_states.FLUSH_LAST:
                # last cycle for flush
                n_state.next = ic_states.IDLE

        @always(clk_i.posedge)
        def update_state():
            if rst_i:
                state.next = ic_states.FLUSH
            else:
                state.next = n_state

        @always_comb
        def fetch_fsm():
            n_refill_addr.next  = refill_addr
            n_refill_valid.next = False  # refill_valid

            if state == ic_states.IDLE:
                if invalidate:
                    n_refill_valid.next = False
            elif state == ic_states.READ:
                if miss:
                    n_refill_addr.next  = concat(cpu_wbs.addr_i[LIMIT_WIDTH:BLOCK_WIDTH], modbv(0)[BLOCK_WIDTH - 2:])
                    n_refill_valid.next = True  # not mem_wbm.ready?
            elif state == ic_states.FETCH:
                n_refill_valid.next = True
                if refill_valid and mem_wbm.ack_i:
                    if final_fetch:
                        n_refill_valid.next = False
                        n_refill_addr.next = 0
                    else:
                        n_refill_valid.next = True
                        n_refill_addr.next  = refill_addr + modbv(1)[BLOCK_WIDTH - 2:]

        @always(clk_i.posedge)
        def update_fetch():
            if rst_i:
                refill_addr.next  = 0
                refill_valid.next = False
            else:
                refill_addr.next  = n_refill_addr
                refill_valid.next = n_refill_valid

        @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 == ic_states.IDLE:
                if invalidate:
                    tag_we.next = False
            elif state == ic_states.READ:
                if miss:
                    for i in range(0, WAYS):
                        if lru_select[i]:
                            tag_in[i].next = concat(True, cpu_wbs.addr_i[LIMIT_WIDTH:WAY_WIDTH])
                    tag_we.next = True
                else:
                    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 == ic_states.IDLE:
                if invalidate:
                    n_flush_addr.next = modbv(-1)[SET_WIDTH:]
                    n_flush_we.next   = True
            elif state == ic_states.FLUSH:
                n_flush_addr.next = flush_addr - modbv(1)[SET_WIDTH:]
                n_flush_we.next   = True
            elif state == ic_states.FLUSH_LAST:
                n_flush_we.next = False

        @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

        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():
            # cpu data_in assignment: instruction.
            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

        @always_comb
        def mem_port_assign():
            mem_wbm.addr_o.next = concat(refill_addr, modbv(0)[2:])
            mem_wbm.dat_o.next  = cpu_wbs.dat_i
            mem_wbm.sel_o.next  = modbv(0)[4:]

        # 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_r():
            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 = 0xAABBCCDD
                crp_we[i].next     = False

        # 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):
                # ignore data_o from update port
                cup_clk[i].next    = clk_i
                cup_addr[i].next   = refill_addr[WAY_WIDTH - 2:]
                cup_data_i[i].next = mem_wbm.dat_i
                cup_we[i].next     = lru_select[i] & mem_wbm.ack_i

        @always_comb
        def wbs_cpu_flags():
            cpu_err.next  = mem_wbm.err_i
            cpu_wait.next = miss_w_and or state != ic_states.READ
            cpu_busy.next = busy

        @always_comb
        def wbm_mem_flags():
            mem_read.next  = refill_valid and not final_fetch
            mem_write.next = False
            mem_rmw.next   = False

        # Remove warnings: Signal is driven but not read
        for i in range(WAYS):
            cache_update_port[i].data_o = None
            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()