diff --git a/apycula/attrids.py b/apycula/attrids.py index da659df..067280a 100644 --- a/apycula/attrids.py +++ b/apycula/attrids.py @@ -1210,7 +1210,7 @@ 'DIVCIBRST2': 1, 'DIVCIBRST3': 2, 'DIV2': 3, - 'DIVCIBRST0': 4, + 'DIVCIBRST0': 4, 'DIVCIBRST1': 5, 'DIVCIBRST4': 6, 'DIVCIBRST5': 7, diff --git a/apycula/chipdb.py b/apycula/chipdb.py index d6ee5e1..734c035 100644 --- a/apycula/chipdb.py +++ b/apycula/chipdb.py @@ -1186,12 +1186,19 @@ def fse_create_hclk_nodes(dev, device, fse, dat: Datfile): row, col = hclk_loc ttyp = fse['header']['grid'][61][row][col] dev.hclk_pips[(row, col)] = fse_pips(fse, ttyp, table = 48, wn = hclknames) + for dst in dev.hclk_pips[(row, col)].keys(): + # from HCLK to interbank MUX + if dst in {'HCLK_BANK_OUT0', 'HCLK_BANK_OUT1'}: + add_node(dev, f'HCLK{"TBLR".index(side)}_BANK_OUT{dst[-1]}', "GLOBAL_CLK", row, col, dst) # connect local wires like PCLKT0 etc to the global nodes for srcs in dev.hclk_pips[(row, col)].values(): for src in srcs.keys(): for pfx in _global_wire_prefixes: if src.startswith(pfx): add_node(dev, src, "HCLK", row, col, src) + # from interbank MUX to HCLK + if src in {'HCLK_BANK_IN0', 'HCLK_BANK_IN1'}: + add_node(dev, f'HCLKMUX{src[-1]}', "GLOBAL_CLK", row, col, src) # strange GW1N-9C input-input aliases for i in {0, 2}: dev.nodes.setdefault(f'X{col}Y{row}/HCLK9-{i}', ('HCLK', {(row, col, f'HCLK_IN{i}')}))[1].add((row, col, f'HCLK_9IN{i}')) @@ -1236,6 +1243,80 @@ def fse_create_hclk_nodes(dev, device, fse, dat: Datfile): if src.startswith('HCLK'): hclks[src].add((row, col, src)) +# DHCEN (as I imagine) is an additional control input of the HCLK input +# multiplexer. We have four input multiplexers - HCLK_IN0, HCLK_IN1, HCLK_IN2, +# HCLK_IN3 (GW1N-9C with its additional four multiplexers stands separately, +# but we will deal with it later) and two interbank inputs. +# Creating images using IDE where we use the maximum allowable number of DHCEN, +# the CE port of which is connected to the IO ports, then we trace the route +# from IO to the final wire, which will be the CE port of the DHCEN primitive. +# We are not interested in the CLKIN and CLKOUT ports because we are supposed +# to simply disable/enable one of the input multiplexers. +# Let's summarize the experimental data in a table. +# There are 4 multiplexers and interbank inputs on each side of the chip +# (sides: Right Bottom Left Top). +_dhcen_ce = { + 'GW1N-1': + {'B' : [(10, 19, 'D5'), (10, 19, 'D3'), (10, 19, 'D4'), (10, 19, 'D2'), (10, 0, 'C0'), (10, 0, 'C1')]}, + 'GW1NZ-1': + {'R' : [( 0, 19, 'A2'), ( 0, 19, 'A4'), ( 0, 19, 'A3'), ( 0, 19, 'A5'), ( 0, 18, 'C6'), ( 0, 18, 'C7')], + 'T' : [(10, 19, 'A2'), (10, 19, 'A4'), (10, 19, 'A3'), (10, 19, 'A5'), (10, 19, 'C6'), (10, 19, 'C7')]}, + 'GW1NS-2': + {'R' : [(10, 19, 'A4'), (10, 19, 'A6'), (10, 19, 'A5'), (10, 19, 'A7'), (10, 19, 'C4'), (10, 19, 'C5')], + 'B' : [(11, 19, 'A4'), (11, 19, 'A6'), (11, 19, 'A5'), (11, 19, 'A7'), (11, 19, 'C4'), (11, 19, 'C5')], + 'L' : [( 9, 0, 'A0'), ( 9, 0, 'A2'), ( 9, 0, 'A1'), ( 9, 0, 'A3'), ( 9, 0, 'C0'), ( 9, 0, 'C1')], + 'T' : [( 0, 19, 'D5'), ( 0, 19, 'D3'), ( 0, 19, 'D4'), ( 0, 19, 'D2'), ( 0, 0, 'B1'), ( 0, 0, 'B0')]}, + 'GW1N-4': + {'R' : [(18, 37, 'C6'), (18, 37, 'D7'), (18, 37, 'C7'), (18, 37, 'D6'), ( 0, 37, 'D7'), ( 0, 37, 'D6')], + 'B' : [(19, 37, 'A2'), (19, 37, 'A4'), (19, 37, 'A3'), (19, 37, 'A5'), (19, 0, 'B2'), (19, 0, 'B3')], + 'L' : [(18, 0, 'C6'), (18, 0, 'D7'), (18, 0, 'C7'), (18, 0, 'D6'), (19, 0, 'A4'), ( 0, 0, 'B1')]}, + 'GW1NS-4': + {'R' : [(18, 37, 'C6'), (18, 37, 'D7'), (18, 37, 'C7'), (18, 37, 'D6'), ( 0, 37, 'D7'), ( 0, 37, 'D6')], + 'B' : [(19, 37, 'A2'), (19, 37, 'A4'), (19, 37, 'A3'), (19, 37, 'A5'), (19, 0, 'B2'), (19, 0, 'B3')], + 'T' : [( 1, 0, 'B6'), ( 1, 0, 'A0'), ( 1, 0, 'B7'), ( 1, 0, 'A1'), ( 1, 0, 'C4'), ( 1, 0, 'C3')]}, + 'GW1N-9': + {'R' : [(18, 46, 'C6'), (18, 46, 'D7'), (18, 46, 'C7'), (18, 46, 'D6'), (18, 46, 'B6'), (18, 46, 'B7')], + 'B' : [(28, 46, 'A2'), (28, 46, 'A4'), (28, 46, 'A3'), (28, 46, 'A5'), (28, 0, 'B2'), (28, 0, 'B3')], + 'L' : [(18, 0, 'C6'), (18, 0, 'D7'), (18, 0, 'C7'), (18, 0, 'D6'), (18, 0, 'B6'), (18, 0, 'B7')], + 'T' : [( 9, 0, 'C6'), ( 9, 0, 'D7'), ( 9, 0, 'C7'), ( 9, 0, 'D6'), ( 9, 0, 'B6'), ( 9, 0, 'B7')]}, + 'GW1N-9C': + {'R' : [(18, 46, 'C6'), (18, 46, 'D7'), (18, 46, 'C7'), (18, 46, 'D6'), (18, 46, 'B6'), (18, 46, 'B7')], + 'B' : [(28, 46, 'A2'), (28, 46, 'A4'), (28, 46, 'A3'), (28, 46, 'A5'), (28, 0, 'B2'), (28, 0, 'B3')], + 'L' : [(18, 0, 'C6'), (18, 0, 'D7'), (18, 0, 'C7'), (18, 0, 'D6'), (18, 0, 'B6'), (18, 0, 'B7')], + 'T' : [( 9, 0, 'C6'), ( 9, 0, 'D7'), ( 9, 0, 'C7'), ( 9, 0, 'D6'), ( 9, 0, 'B6'), ( 9, 0, 'B7')]}, + 'GW2A-18': + {'R' : [(27, 55, 'A2'), (27, 55, 'A3'), (27, 55, 'D2'), (27, 55, 'D3'), (27, 55, 'D0'), (27, 55, 'D1')], + 'B' : [(54, 27, 'A2'), (54, 27, 'A3'), (54, 27, 'D2'), (54, 27, 'D3'), (54, 27, 'D0'), (54, 27, 'D1')], + 'L' : [(27, 0, 'A2'), (27, 0, 'A3'), (27, 0, 'D2'), (27, 0, 'D3'), (27, 0, 'D0'), (27, 0, 'D1')], + 'T' : [( 0, 27, 'A2'), ( 0, 27, 'A3'), ( 0, 27, 'D2'), ( 0, 27, 'D3'), ( 0,27, 'D0'), ( 0, 27, 'D1')]}, + 'GW2A-18C': + {'R' : [(27, 55, 'A2'), (27, 55, 'A3'), (27, 55, 'D2'), (27, 55, 'D3'), (27, 55, 'D0'), (27, 55, 'D1')], + 'B' : [(54, 27, 'A2'), (54, 27, 'A3'), (54, 27, 'D2'), (54, 27, 'D3'), (54, 27, 'D0'), (54, 27, 'D1')], + 'L' : [(27, 0, 'A2'), (27, 0, 'A3'), (27, 0, 'D2'), (27, 0, 'D3'), (27, 0, 'D0'), (27, 0, 'D1')], + 'T' : [( 0, 27, 'A2'), ( 0, 27, 'A3'), ( 0, 27, 'D2'), ( 0, 27, 'D3'), ( 0,27, 'D0'), ( 0, 27, 'D1')]}, + } +def fse_create_dhcen(dev, device, fse, dat: Datfile): + if device not in _dhcen_ce: + print(f'No DHCEN for {device} for now.') + return + for side, ces in _dhcen_ce[device].items(): + for idx, ce_wire in enumerate(ces): + row, col, wire = ce_wire + extra = dev.extra_func.setdefault((row, col), {}) + dhcen = extra.setdefault('dhcen', []) + # use db.hclk_pips in order to find HCLK_IN cells + for hclk_loc in _hclk_to_fclk[device][side]['hclk']: + if idx < 4: + hclk_name = f'HCLK_IN{idx}' + else: + hclk_name = f'HCLK_BANK_OUT{idx - 4}' + if hclk_name in dev.hclk_pips[hclk_loc]: + hclkin = {'pip' : [f'X{hclk_loc[1]}Y{hclk_loc[0]}', hclk_name, next(iter(dev.hclk_pips[hclk_loc][hclk_name].keys())), side]} + + hclkin.update({ 'ce' : wire}) + dhcen.append(hclkin) + + _pll_loc = { 'GW1N-1': {'TRPLL0CLK0': (0, 17, 'F4'), 'TRPLL0CLK1': (0, 17, 'F5'), @@ -1488,6 +1569,7 @@ def fse_create_clocks(dev, device, dat: Datfile, fse): spines = {f'SPINE{i}' for i in range(32)} + hclk_srcs = {f'HCLK{i}_BANK_OUT{j}' for i in range(4) for j in range(2)} dcs_inputs = {f'P{i}{j}{k}' for i in range(1, 5) for j in range(6, 8) for k in "ABCD"} for row, rd in enumerate(dev.grid): for col, rc in enumerate(rd): @@ -1499,6 +1581,12 @@ def fse_create_clocks(dev, device, dat: Datfile, fse): add_node(dev, dest, "GLOBAL_CLK", row, col, dest) for src in { wire for wire in srcs.keys() if wire not in {'VCC', 'VSS'}}: add_node(dev, src, "GLOBAL_CLK", row, col, src) + elif dest in {'HCLKMUX0', 'HCLKMUX1'}: + # this interbank communication between HCLKs + add_node(dev, dest, "GLOBAL_CLK", row, col, dest) + for src in {wire for wire in srcs.keys() if wire in hclk_srcs}: + add_node(dev, src, "GLOBAL_CLK", row, col, src) + # GBx0 <- GBOx for spine_pair in range(4): # GB00/GB40, GB10/GB50, GB20/GB60, GB30/GB70 tap_start = _clock_data[device]['tap_start'][0] @@ -2088,6 +2176,7 @@ def from_fse(device, fse, dat: Datfile): fse_create_bandgap(dev, device) fse_create_userflash(dev, device, dat) fse_create_logic2clk(dev, device, dat) + fse_create_dhcen(dev, device, fse, dat) disable_plls(dev, device) sync_extra_func(dev) set_chip_flags(dev, device); @@ -3487,6 +3576,8 @@ def fse_wire_delays(db): db.wire_delay[clknames[i]] = "CENT_SPINE_PCLK" for i in range(129, 153): # clock inputs (logic->clock) db.wire_delay[clknames[i]] = "CENT_SPINE_PCLK" + for i in range(1000, 1010): # HCLK + db.wire_delay[clknames[i]] = "X0" # XXX # assign pads with plls # for now use static table and store the bel name although it is always PLL without a number diff --git a/apycula/gowin_pack.py b/apycula/gowin_pack.py index d81b73e..05fd1b2 100644 --- a/apycula/gowin_pack.py +++ b/apycula/gowin_pack.py @@ -185,7 +185,7 @@ def get_bits(init_data): def get_bels(data): later = [] if is_himbaechel: - belre = re.compile(r"X(\d+)Y(\d+)/(?:GSR|LUT|DFF|IOB|MUX|ALU|ODDR|OSC[ZFHWO]?|BUF[GS]|RAM16SDP4|RAM16SDP2|RAM16SDP1|PLL|IOLOGIC|CLKDIV2|CLKDIV|BSRAM|ALU|MULTALU18X18|MULTALU36X18|MULTADDALU18X18|MULT36X36|MULT18X18|MULT9X9|PADD18|PADD9|BANDGAP|DQCE|DCS|USERFLASH)(\w*)") + belre = re.compile(r"X(\d+)Y(\d+)/(?:GSR|LUT|DFF|IOB|MUX|ALU|ODDR|OSC[ZFHWO]?|BUF[GS]|RAM16SDP4|RAM16SDP2|RAM16SDP1|PLL|IOLOGIC|CLKDIV2|CLKDIV|BSRAM|ALU|MULTALU18X18|MULTALU36X18|MULTADDALU18X18|MULT36X36|MULT18X18|MULT9X9|PADD18|PADD9|BANDGAP|DQCE|DCS|USERFLASH|DHCEN)(\w*)") else: belre = re.compile(r"R(\d+)C(\d+)_(?:GSR|SLICE|IOB|MUX2_LUT5|MUX2_LUT6|MUX2_LUT7|MUX2_LUT8|ODDR|OSC[ZFHWO]?|BUFS|RAMW|rPLL|PLLVR|IOLOGIC)(\w*)") @@ -1989,6 +1989,43 @@ def set_osc_attrs(db, typ, params): add_attr_val(db, 'OSC', fin_attrs, attrids.osc_attrids[attr], val) return fin_attrs +_wire2attr_val = { + 'HCLK_IN0': ('HSB0MUX0_HSTOP', 'HCLKCIBSTOP0'), + 'HCLK_IN1': ('HSB1MUX0_HSTOP', 'HCLKCIBSTOP2'), + 'HCLK_IN2': ('HSB0MUX1_HSTOP', 'HCLKCIBSTOP1'), + 'HCLK_IN3': ('HSB1MUX1_HSTOP', 'HCLKCIBSTOP3'), + 'HCLK_BANK_OUT0': ('BRGMUX0_BRGSTOP', 'BRGCIBSTOP0'), + 'HCLK_BANK_OUT1': ('BRGMUX1_BRGSTOP', 'BRGCIBSTOP1'), + } +def find_and_set_dhcen_hclk_fuses(db, tilemap, wire, side): + fin_attrs = set() + attr, attr_val = _wire2attr_val[wire] + val = attrids.hclk_attrvals[attr_val] + add_attr_val(db, 'HCLK', fin_attrs, attrids.hclk_attrids[attr], val) + + def set_fuse(): + ttyp = db.grid[row][col].ttyp + if 'HCLK' in db.shortval[ttyp]: + bits = get_shortval_fuses(db, ttyp, fin_attrs, "HCLK") + tile = tilemap[row, col] + for r, c in bits: + tile[r][c] = 1 + + if side in "TB": + if side == 'T': + row = 0 + else: + row = db.rows - 1 + for col in range(db.cols): + set_fuse() + else: + if side == 'L': + col = 0 + else: + col = db.cols - 1 + for row in range(db.rows): + set_fuse() + def bin_str_to_dec(str_val): bin_pattern = r'^[0,1]+' bin_str = re.findall(bin_pattern, str_val) @@ -2035,7 +2072,6 @@ def set_hclk_attrs(db, params, num, typ, cell_name): add_attr_val(db, 'HCLK', fin_attrs, attrids.hclk_attrids[attr], val) return fin_attrs - _iologic_default_attrs = { 'DUMMY': {}, 'IOLOGIC': {}, @@ -2502,9 +2538,19 @@ def place(db, tilemap, bels, cst, args): cfg_tile = tilemap[(0, 37)] for r, c in bits: cfg_tile[r][c] = 1 + elif typ == "DHCEN": + if 'DHCEN_USED' not in attrs: + continue + # DHCEN as such is just a control wire and does not have a fuse + # itself, but HCLK has fuses that allow this control. Here we look + # for the corresponding HCLK and set its fuses. + _, wire, _, side = db.extra_func[row - 1, col -1]['dhcen'][int(num)]['pip'] + hclk_attrs = find_and_set_dhcen_hclk_fuses(db, tilemap, wire, side) elif typ in ["CLKDIV", "CLKDIV2"]: hclk_attrs = set_hclk_attrs(db, parms, num, typ, cellname) bits = get_shortval_fuses(db, tiledata.ttyp, hclk_attrs, "HCLK") + for r, c in bits: + tile[r][c] = 1 elif typ == 'DQCE': # Himbaechel only pipre = re.compile(r"X(\d+)Y(\d+)/([\w_]+)/([\w_]+)") @@ -2693,6 +2739,17 @@ def secure_long_wires(db, tilemap, row, col, src, dest): for row, col in bits: tile[row][col] = 1 +# hclk interbank requires to set some non-route fuses +def do_hclk_banks(db, row, col, src, dest): + res = set() + if dest in {'HCLK_BANK_OUT0', 'HCLK_BANK_OUT1'}: + fin_attrs = set() + add_attr_val(db, 'HCLK', fin_attrs, attrids.hclk_attrids[f'BRGMUX{dest[-1]}_BRGOUT'], attrids.hclk_attrvals['ENABLE']) + + ttyp = db.grid[row][col].ttyp + if 'HCLK' in db.shortval[ttyp]: + res = get_shortval_fuses(db, ttyp, fin_attrs, "HCLK") + return res def route(db, tilemap, pips): for row, col, src, dest in pips: @@ -2704,6 +2761,7 @@ def route(db, tilemap, pips): bits = tiledata.clock_pips[dest][src] elif is_himbaechel and (row - 1, col - 1) in db.hclk_pips and dest in db.hclk_pips[row - 1, col - 1]: bits = db.hclk_pips[row - 1, col - 1][dest][src] + bits.update(do_hclk_banks(db, row - 1, col - 1, src, dest)) else: bits = tiledata.pips[dest][src] except KeyError: diff --git a/apycula/wirenames.py b/apycula/wirenames.py index 5e1fc8b..9480282 100644 --- a/apycula/wirenames.py +++ b/apycula/wirenames.py @@ -119,6 +119,18 @@ }) clknames.update({n: f"UNK{n}" for n in range(210, 261)}) + +# HCLK->clock network +# Each HCLK can connect to other HCLKs through two MUXes in the clock system. +# Here we assign numbers to these MUXes and their inputs - two per HCLK +clknames.update({ + 1000: 'HCLKMUX0', 1001: 'HCLKMUX1', + 1002: 'HCLK0_BANK_OUT0', 1003: 'HCLK0_BANK_OUT1', + 1004: 'HCLK1_BANK_OUT0', 1005: 'HCLK1_BANK_OUT1', + 1006: 'HCLK2_BANK_OUT0', 1007: 'HCLK2_BANK_OUT1', + 1008: 'HCLK3_BANK_OUT0', 1009: 'HCLK3_BANK_OUT1', +}) + clknumbers = {v: k for k, v in clknames.items()} # hclk @@ -126,12 +138,12 @@ hclknames.update({n: f"HCLK_UNK{n}" for n in range(26)}) # inputs hclknames.update({ - 2: 'HCLK_IN0', 3: 'HCLK_IN1', 4: 'HCLK_IN2', 5: 'HCLK_IN3' + 2: 'HCLK_IN0', 3: 'HCLK_IN1', 4: 'HCLK_IN2', 5: 'HCLK_IN3', 8: 'HCLK_BANK_IN0', 9: 'HCLK_BANK_IN1' }) # HCLK section inputs hclknames.update({ - 10: 'HCLK0_SECT0_IN', 11: 'HCLK0_SECT1_IN', 12: 'HCLK1_SECT0_IN', 13: 'HCLK1_SECT1_IN' + 6: 'HCLK_BANK_OUT0', 7: 'HCLK_BANK_OUT1', 10: 'HCLK0_SECT0_IN', 11: 'HCLK0_SECT1_IN', 12: 'HCLK1_SECT0_IN', 13: 'HCLK1_SECT1_IN' }) # Bypass connections from HCLK_IN to HCLK_OUT diff --git a/examples/himbaechel/Makefile.himbaechel b/examples/himbaechel/Makefile.himbaechel index eef31be..13c03ad 100644 --- a/examples/himbaechel/Makefile.himbaechel +++ b/examples/himbaechel/Makefile.himbaechel @@ -6,7 +6,7 @@ NEXTPNR ?= nextpnr-himbaechel all: \ blinky-tangnano20k.fs shift-tangnano20k.fs blinky-tbuf-tangnano20k.fs blinky-oddr-tangnano20k.fs \ blinky-osc-tangnano20k.fs tlvds-tangnano20k.fs elvds-tangnano20k.fs oddr-tlvds-tangnano20k.fs \ - blinky-clkdiv-tangnano20k.fs dvi-example-tangnano20k.fs\ + blinky-clkdiv-tangnano20k.fs dvi-example-tangnano20k.fs blinky-clkdiv-dhcen-tangnano20k.fs \ oddr-elvds-tangnano20k.fs pll-nanolcd-tangnano20k.fs attosoc-tangnano20k.fs \ oser4-tangnano20k.fs ovideo-tangnano20k.fs oser8-tangnano20k.fs oser10-tangnano20k.fs \ ides4-tangnano20k.fs ivideo-tangnano20k.fs ides8-tangnano20k.fs ides10-tangnano20k.fs \ @@ -21,7 +21,7 @@ all: \ \ blinky-primer20k.fs shift-primer20k.fs blinky-tbuf-primer20k.fs blinky-oddr-primer20k.fs \ blinky-osc-primer20k.fs tlvds-primer20k.fs elvds-primer20k.fs oddr-tlvds-primer20k.fs \ - blinky-clkdiv-primer20k.fs dvi-example-primer20k.fs\ + blinky-clkdiv-primer20k.fs dvi-example-primer20k.fs blinky-clkdiv-dhcen-primer20k.fs \ oddr-elvds-primer20k.fs pll-nanolcd-primer20k.fs attosoc-primer20k.fs \ oser4-primer20k.fs ovideo-primer20k.fs oser8-primer20k.fs oser10-primer20k.fs \ ides4-primer20k.fs ivideo-primer20k.fs ides8-primer20k.fs ides10-primer20k.fs \ diff --git a/examples/himbaechel/blinky-clkdiv-dhcen.v b/examples/himbaechel/blinky-clkdiv-dhcen.v new file mode 100644 index 0000000..82df47b --- /dev/null +++ b/examples/himbaechel/blinky-clkdiv-dhcen.v @@ -0,0 +1,83 @@ +module top ( + input clk, + input key_i, + output [`LEDS_NR-1:0] led +); + +/* Expected Result: + - 1 or 2 LEDs blinking, depending on your board. + - The `faster` LED is associated with the input clock. + - The `slower` LED is associated with a divided clock. + - On boards with multiple CLKDIVs, the slower LED's blink rate changes as it cycles through CLKDIVs + configured with different DIV_MODES. + - If your board has only one LED, it should blink with the divided clock. + - Holding the appropriate button should stop the blinking. +*/ + +localparam /*string*/ DIV_MODE_2 = "2"; +localparam /*string*/ DIV_MODE_35 = "3.5"; +localparam /*string*/ DIV_MODE_4 = "4"; +localparam /*string*/ DIV_MODE_5 = "5"; + + +wire key = key_i ^ `INV_BTN; + +reg [25:0] ctr_q; +wire [25:0] ctr_d; +// localparam NUM_HCLKi=NUM_HCLK; + +wire [`NUM_HCLK-1:0] hclk_counts; +reg [$clog2(`NUM_HCLK)-1:0] curr_hclk_idx; +wire curr_hclk; +reg [30:0] sup_count; + + +wire managed_clk; +DHCEN dhcen( + .CLKIN(clk), + .CE(key), + .CLKOUT(managed_clk) +); + +genvar i; +generate + for (i=0; i < `NUM_HCLK; i=i+1) begin:hcount + localparam /*string*/ div_mode =(i % 4 == 0) ? DIV_MODE_5 : + (i % 4 == 1) ? DIV_MODE_4 : + (i % 4 == 2) ? DIV_MODE_35 : + DIV_MODE_2; + + wire div2_out; + wire o_clk; + + CLKDIV2 my_div2 ( + .RESETN(1'b1), + .HCLKIN(managed_clk), + .CLKOUT(div2_out) + ); + + CLKDIV #(.DIV_MODE(div_mode)) my_div ( + .RESETN(1'b1), + .HCLKIN(div2_out), + .CLKOUT(o_clk) + ); + + reg [23:0] count; + always @(posedge o_clk)begin + count <= count + 1'b1; + end + assign hclk_counts[i] = count[23]; + end +endgenerate + +always @(posedge clk) begin + sup_count <= sup_count + 1'b1; + curr_hclk_idx <= curr_hclk_idx + sup_count[29]; + if (curr_hclk_idx == `NUM_HCLK-1) + curr_hclk_idx <= 0; +end + +assign curr_hclk = hclk_counts[curr_hclk_idx]; +assign led = {curr_hclk, sup_count[23]}; + +endmodule