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
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()
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
def testUniqueLiterals(self): try: t_State = enum("SEARCH", "CONFIRM", "SEARCH") except ValueError: pass else: self.fail()
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
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:
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
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()
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
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
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()
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()
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()
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
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()
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()
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
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
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:
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:
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()
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
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()
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)
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))
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))
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()
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
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()
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()
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()
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')
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()
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()
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()
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()
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
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
def lt24lcd(glbl, vmem, lcd): """ A video display driver for the terasic LT24 LCD display. This driver reads pixels from the VideoMemory interface and transfers them to the LT24 display. This hardware module (component) will also perform the initial display configuration. Ports: glbl (Global): global signals, clock, reset, enable, etc. vmem (VideoMemory): video memory interface, the driver will read pixels from this interface. lcd (LT24Interface): The external LT24 interface. Parameters: None RGB 5-6-5 (8080-system 16bit parallel bus) """ assert isinstance(lcd, LT24Interface) resolution, refresh_rate = (240, 320), 60 number_of_pixels = resolution[0] * resolution[1] # local references to signals in interfaces clock, reset = glbl.clock, glbl.reset # make sure the user timer is configured assert glbl.tick_user is not None # write out a new VMEM to the LCD display, a write cycle # consists of putting the video data on the bus and latching # with the `wrx` signal. Init (write once) the column and # page addresses (cmd = 2A, 2B) then write mem (2C) states = enum( 'init_wait_reset', # wait for the controller to reset the LCD 'init_start', # start the display init sequence 'init_start_cmd', # send a command, port of the display seq 'init_next', # determine if another command 'write_cmd_start', # command subroutine 'write_cmd', # command subroutine 'display_update_start', # update the display 'display_update_start_p', # delay for command ack 'display_update', # update the display 'display_update_next', # wait for driver to ack pixel xfered 'display_update_end' # end of display update ) state = Signal(states.init_wait_reset) state_prev = Signal(states.init_wait_reset) cmd = Signal(intbv(0)[8:]) return_state = Signal(states.init_wait_reset) num_hor_pxl, num_ver_pxl = resolution print("resolution {}x{} = {} number of pixes".format( num_hor_pxl, num_ver_pxl, number_of_pixels)) hcnt = intbv(0, min=0, max=num_hor_pxl) vcnt = intbv(0, min=0, max=num_ver_pxl) # signals to start a new command transaction to the LCD datalen = Signal(intbv(0, min=0, max=number_of_pixels+1)) data = Signal(intbv(0)[16:]) datasent = Signal(bool(0)) datalast = Signal(bool(0)) cmd_in_progress = Signal(bool(0)) # -------------------------------------------------------- # LCD driver gdrv = lt24lcd_driver(glbl, lcd, cmd, datalen, data, datasent, datalast, cmd_in_progress) # -------------------------------------------------------- # build the display init sequency ROM rom, romlen, maxpause = build_init_rom(init_sequence) offset = Signal(intbv(0, min=0, max=romlen+1)) pause = Signal(intbv(0, min=0, max=maxpause+1)) # -------------------------------------------------------- # state-machine @always_seq(clock.posedge, reset=reset) def rtl_state_machine(): state_prev.next = state if state == states.init_wait_reset: if lcd.reset_complete: state.next = states.init_start elif state == states.init_start: v = rom[offset] # @todo: change the table to only contain the number of # @todo: bytes to be transferred datalen.next = v - 3 p = rom[offset+1] pause.next = p offset.next = offset + 2 state.next = states.init_start_cmd elif state == states.init_start_cmd: v = rom[offset] cmd.next = v if datalen > 0: v = rom[offset+1] data.next = v offset.next = offset + 2 else: offset.next = offset + 1 state.next = states.write_cmd_start return_state.next = states.init_next elif state == states.init_next: if pause == 0: if offset == romlen: state.next = states.display_update_start else: state.next = states.init_start elif glbl.tick_ms: pause.next = pause - 1 elif state == states.write_cmd_start: state.next = states.write_cmd elif state == states.write_cmd: if cmd_in_progress: if datasent and not datalast: v = rom[offset] data.next = v offset.next = offset+1 else: cmd.next = 0 state.next = return_state elif state == states.display_update_start: if glbl.tick_user: cmd.next = 0x2C state.next = states.display_update_start_p datalen.next = number_of_pixels elif state == states.display_update_start_p: state.next =states.display_update elif state == states.display_update: assert cmd_in_progress if vcnt == num_ver_pxl-1: hcnt[:] = 0 vcnt[:] = 0 elif hcnt == num_hor_pxl-1: hcnt[:] = 0 vcnt[:] = vcnt + 1 else: hcnt[:] = hcnt + 1 # this will be the pixel for the next write cycle vmem.hpxl.next = hcnt vmem.vpxl.next = vcnt # this is the pixel for the current write cycle if hcnt == 0 and vcnt == 0: cmd.next = 0 state.next = states.display_update_end else: data.next = concat(vmem.red, vmem.green, vmem.blue) state.next = states.display_update_next elif state == states.display_update_next: if cmd_in_progress: if datasent and not datalast: state.next = states.display_update else: cmd.next = 0 state.next = states.display_update_end elif state == states.display_update_end: # wait till the driver ack the command completion if not cmd_in_progress: state.next = states.display_update_start return gdrv, rtl_state_machine
def 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
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)
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:
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
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()
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
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
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))
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()
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,
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()