def arbiter_priority(req_vec, gnt_vec=None, gnt_idx=None, gnt_vld=None): """ Static priority arbiter: grants the request with highest priority, which is the lower index req_vec - (i) vector of request signals, req_vec[0] is with the highest priority gnt_vec - (o) optional, vector of grants, one grant per request, only one grant can be active at at time gnt_idx - (o) optional, grant index, index of the granted request gnt_vld - (o) optional, grant valid, indicate that there is a granted request """ REQ_NUM = len(req_vec) gnt_vec_s = Signal(intbv(0)[REQ_NUM:]) gnt_idx_s = Signal(intbv(0, min=0, max=REQ_NUM)) gnt_vld_s = Signal(bool(0)) @always_comb def prioroty_encoder(): gnt_vec_s.next = 0 gnt_idx_s.next = 0 gnt_vld_s.next = 0 for i in range(REQ_NUM): if ( req_vec[i]==1 ): gnt_vec_s.next[i] = 1 gnt_idx_s.next = i gnt_vld_s.next = 1 break if gnt_vec!=None: _vec = assign(gnt_vec, gnt_vec_s) if gnt_idx!=None: _idx = assign(gnt_idx, gnt_idx_s) if gnt_vld!=None: _vld = assign(gnt_vld, gnt_vld_s) return instances()
def arbiter_roundrobin(rst, clk, req_vec, gnt_vec=None, gnt_idx=None, gnt_vld=None, gnt_rdy=None): """ Round Robin arbiter: finds the active request with highest priority and presents its index on the gnt_idx output. req_vec - (i) vector of request signals, priority changes dynamically gnt_vec - (o) optional, vector of grants, one grant per request, only one grant can be active at at time gnt_idx - (o) optional, grant index, index of the granted request gnt_vld - (o) optional, grant valid, indicate that there is a granted request gnt_rdy - (i) grant ready, indicates that the current grant is consumed and priority should be updated. The priority is updated only if there is a valid grant when gnt_rdy is activated. When priority is updated, the currently granted req_vec[gnt_idx] gets the lowest priority and req_vec[gnt_idx+1] gets the highest priority. gnt_rdy should be activated in the same clock cycle when output the grant is used """ REQ_NUM = len(req_vec) ptr = Signal(intbv(0, min=0, max=REQ_NUM)) gnt_vec_s = Signal(intbv(0)[REQ_NUM:]) gnt_idx_s = Signal(intbv(0, min=0, max=REQ_NUM)) gnt_vld_s = Signal(bool(0)) @always(clk.posedge) def ptr_proc(): if (rst): ptr.next = REQ_NUM-1 elif (gnt_rdy and gnt_vld_s): ptr.next = gnt_idx_s @always_comb def roundrobin_encoder(): gnt_vec_s.next = 0 gnt_idx_s.next = 0 gnt_vld_s.next = 0 for i in range(REQ_NUM): if (i>ptr): if ( req_vec[i]==1 ): gnt_vec_s.next[i] = 1 gnt_idx_s.next = i gnt_vld_s.next = 1 return for i in range(REQ_NUM): if ( req_vec[i]==1 ): gnt_vec_s.next[i] = 1 gnt_idx_s.next = i gnt_vld_s.next = 1 return if gnt_vec!=None: _vec = assign(gnt_vec, gnt_vec_s) if gnt_idx!=None: _idx = assign(gnt_idx, gnt_idx_s) if gnt_vld!=None: _vld = assign(gnt_vld, gnt_vld_s) return instances()
def hs_arbmux(rst, clk, ls_hsi, hso, sel, ARBITER_TYPE="priority"): """ [Many-to-one] Arbitrates a list of input handshake interfaces. Selects one of the active input interfaces and connects it to the output. Active input is an input interface with asserted "valid" signal ls_hsi - (i) list of input handshake tuples (ready, valid) hso - (o) output handshake tuple (ready, valid) sel - (o) indicates the currently selected input handshake interface ARBITER_TYPE - selects the arbiter type to be used, "priority" or "roundrobin" """ N = len(ls_hsi) ls_hsi_rdy, ls_hsi_vld = zip(*ls_hsi) ls_hsi_vld = list(ls_hsi_vld) # Needed to avoid: "myhdl.ConversionError: Signal in multiple list is not supported:" ls_vld = [Signal(bool(0)) for _ in range(N)] _a = [assign(ls_vld[i], ls_hsi_vld[i]) for i in range(N)] sel_s = Signal(intbv(0, min=0, max=N)) @always_comb def _sel(): sel.next = sel_s priority_update = None if (ARBITER_TYPE == "roundrobin"): hso_rdy, hso_vld = hso priority_update = Signal(bool(0)) @always_comb def _prio(): priority_update.next = hso_rdy and hso_vld _arb = arbiter(rst=rst, clk=clk, req_vec=ls_vld, gnt_idx=sel_s, gnt_rdy=priority_update, ARBITER_TYPE=ARBITER_TYPE) _mux = hs_mux(sel=sel_s, ls_hsi=ls_hsi, hso=hso) return instances()
def checksum(rst, clk, rx_vld, rx_sop, rx_eop, rx_dat, rx_mty, chksum, sum16=None, sumN=None, init_sum=None, MAX_BYTES=1500): """ Calculates checksum on a stream of packetised data rx_vld - (i) valid data rx_sop - (i) start of packet rx_eop - (i) end of packet rx_dat - (i) data rx_mty - (i) empty bits when rx_eop init_sum - (i) initial value for the sum (e.g. sum of the some fields from a packet header) sumN - (o) optional, plane sum sum16 - (o) optional, 16 bit sum (every time the sum overflows, the overflow is added to the sum) chksum - (o) optional, checksum (~sum16) MAX_BYTES - a limit: maximum number of bytes that may arrive in a single packet Assumes Big-endian data. The results are ready in the first clock cycle after rx_eop """ DATA_WIDTH = len(rx_dat) assert DATA_WIDTH%16==0, "checksum: expects len(rx_dat)=16*x, but len(tx_dat)={}".format(DATA_WIDTH) NUM_BYTES = DATA_WIDTH // 8 NUM_WORDS = DATA_WIDTH // 16 SUM_WIDTH = 16 + int(ceil(log(MAX_BYTES/2,2))) + 1 SUM16_WIDTH = 16 + int(ceil(log(NUM_WORDS,2))) + 1 if (init_sum != None): assert len(init_sum)<=16, "checksum: expects len(init_sum)<={}, but len(init_sum)={}".format(16, len(init_sum)) SUM_WIDTH += 1 SUM16_WIDTH += 1 else: init_sum = 0 FF_MASK = intbv(0)[DATA_WIDTH:].max-1 mdata = Signal(intbv(0)[DATA_WIDTH:]) @always_comb def _mask_empty(): mdata.next = rx_dat if rx_eop: mdata.next = rx_dat & (FF_MASK<<(rx_mty*8)) # Slice masked data in 16 bit words mdata16 = [Signal(intbv(0)[16:]) for _ in range(NUM_WORDS)] _ass = [assign(mdata16[w], mdata((w+1)*16, w*16)) for w in range(NUM_WORDS)] if sumN!=None: assert len(sumN)>=SUM_WIDTH, "checksum: expects len(sumN)>={}, but len(sumN)={}".format(SUM_WIDTH, len(sumN)) sumN_reg = Signal(intbv(0)[SUM_WIDTH:]) @always_seq(clk.posedge, reset=rst) def _accuN(): ''' Accumulate ''' if (rx_vld): s = 0 if (rx_sop): s = int(init_sum) else: s = int(sumN_reg) for w in range(NUM_WORDS): s += mdata16[w] sumN_reg.next = s @always_comb def _passN(): sumN.next = sumN_reg if chksum!=None or sum16!=None: sum16_reg = Signal(intbv(0)[SUM16_WIDTH:]) @always_seq(clk.posedge, reset=rst) def _accu16(): ''' Accumulate 16 bit words''' if (rx_vld): s = 0 if (rx_sop): s = int(init_sum) else: s = int(sum16_reg) for w in range(NUM_WORDS): s += mdata16[w] ss = intbv(s)[SUM16_WIDTH:] sum16_reg.next = ss[:2*8] + ss[2*8:] if sum16!=None: assert len(sum16)>=16, "checksum: expects len(sum16)>={}, but len(sum16)={}".format(16, len(sum16)) @always_comb def _pass16(): sum16.next = sum16_reg[16:] if chksum!=None: assert len(chksum)>=16, "checksum: expects len(chksum)>={}, but len(chksum)={}".format(16, len(chksum)) @always_comb def _invert(): chksum.next = ~sum16_reg[16:] & 0xFFFF return instances()