Skip to content

Commit 4f87247

Browse files
authored
Merge pull request #261 from yrabbit/dhcen-ctl
Add DHCEN primitive.
2 parents b2a84bd + af2975e commit 4f87247

File tree

6 files changed

+251
-7
lines changed

6 files changed

+251
-7
lines changed

apycula/attrids.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1210,7 +1210,7 @@
12101210
'DIVCIBRST2': 1,
12111211
'DIVCIBRST3': 2,
12121212
'DIV2': 3,
1213-
'DIVCIBRST0': 4,
1213+
'DIVCIBRST0': 4,
12141214
'DIVCIBRST1': 5,
12151215
'DIVCIBRST4': 6,
12161216
'DIVCIBRST5': 7,

apycula/chipdb.py

+91
Original file line numberDiff line numberDiff line change
@@ -1186,12 +1186,19 @@ def fse_create_hclk_nodes(dev, device, fse, dat: Datfile):
11861186
row, col = hclk_loc
11871187
ttyp = fse['header']['grid'][61][row][col]
11881188
dev.hclk_pips[(row, col)] = fse_pips(fse, ttyp, table = 48, wn = hclknames)
1189+
for dst in dev.hclk_pips[(row, col)].keys():
1190+
# from HCLK to interbank MUX
1191+
if dst in {'HCLK_BANK_OUT0', 'HCLK_BANK_OUT1'}:
1192+
add_node(dev, f'HCLK{"TBLR".index(side)}_BANK_OUT{dst[-1]}', "GLOBAL_CLK", row, col, dst)
11891193
# connect local wires like PCLKT0 etc to the global nodes
11901194
for srcs in dev.hclk_pips[(row, col)].values():
11911195
for src in srcs.keys():
11921196
for pfx in _global_wire_prefixes:
11931197
if src.startswith(pfx):
11941198
add_node(dev, src, "HCLK", row, col, src)
1199+
# from interbank MUX to HCLK
1200+
if src in {'HCLK_BANK_IN0', 'HCLK_BANK_IN1'}:
1201+
add_node(dev, f'HCLKMUX{src[-1]}', "GLOBAL_CLK", row, col, src)
11951202
# strange GW1N-9C input-input aliases
11961203
for i in {0, 2}:
11971204
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):
12361243
if src.startswith('HCLK'):
12371244
hclks[src].add((row, col, src))
12381245

1246+
# DHCEN (as I imagine) is an additional control input of the HCLK input
1247+
# multiplexer. We have four input multiplexers - HCLK_IN0, HCLK_IN1, HCLK_IN2,
1248+
# HCLK_IN3 (GW1N-9C with its additional four multiplexers stands separately,
1249+
# but we will deal with it later) and two interbank inputs.
1250+
# Creating images using IDE where we use the maximum allowable number of DHCEN,
1251+
# the CE port of which is connected to the IO ports, then we trace the route
1252+
# from IO to the final wire, which will be the CE port of the DHCEN primitive.
1253+
# We are not interested in the CLKIN and CLKOUT ports because we are supposed
1254+
# to simply disable/enable one of the input multiplexers.
1255+
# Let's summarize the experimental data in a table.
1256+
# There are 4 multiplexers and interbank inputs on each side of the chip
1257+
# (sides: Right Bottom Left Top).
1258+
_dhcen_ce = {
1259+
'GW1N-1':
1260+
{'B' : [(10, 19, 'D5'), (10, 19, 'D3'), (10, 19, 'D4'), (10, 19, 'D2'), (10, 0, 'C0'), (10, 0, 'C1')]},
1261+
'GW1NZ-1':
1262+
{'R' : [( 0, 19, 'A2'), ( 0, 19, 'A4'), ( 0, 19, 'A3'), ( 0, 19, 'A5'), ( 0, 18, 'C6'), ( 0, 18, 'C7')],
1263+
'T' : [(10, 19, 'A2'), (10, 19, 'A4'), (10, 19, 'A3'), (10, 19, 'A5'), (10, 19, 'C6'), (10, 19, 'C7')]},
1264+
'GW1NS-2':
1265+
{'R' : [(10, 19, 'A4'), (10, 19, 'A6'), (10, 19, 'A5'), (10, 19, 'A7'), (10, 19, 'C4'), (10, 19, 'C5')],
1266+
'B' : [(11, 19, 'A4'), (11, 19, 'A6'), (11, 19, 'A5'), (11, 19, 'A7'), (11, 19, 'C4'), (11, 19, 'C5')],
1267+
'L' : [( 9, 0, 'A0'), ( 9, 0, 'A2'), ( 9, 0, 'A1'), ( 9, 0, 'A3'), ( 9, 0, 'C0'), ( 9, 0, 'C1')],
1268+
'T' : [( 0, 19, 'D5'), ( 0, 19, 'D3'), ( 0, 19, 'D4'), ( 0, 19, 'D2'), ( 0, 0, 'B1'), ( 0, 0, 'B0')]},
1269+
'GW1N-4':
1270+
{'R' : [(18, 37, 'C6'), (18, 37, 'D7'), (18, 37, 'C7'), (18, 37, 'D6'), ( 0, 37, 'D7'), ( 0, 37, 'D6')],
1271+
'B' : [(19, 37, 'A2'), (19, 37, 'A4'), (19, 37, 'A3'), (19, 37, 'A5'), (19, 0, 'B2'), (19, 0, 'B3')],
1272+
'L' : [(18, 0, 'C6'), (18, 0, 'D7'), (18, 0, 'C7'), (18, 0, 'D6'), (19, 0, 'A4'), ( 0, 0, 'B1')]},
1273+
'GW1NS-4':
1274+
{'R' : [(18, 37, 'C6'), (18, 37, 'D7'), (18, 37, 'C7'), (18, 37, 'D6'), ( 0, 37, 'D7'), ( 0, 37, 'D6')],
1275+
'B' : [(19, 37, 'A2'), (19, 37, 'A4'), (19, 37, 'A3'), (19, 37, 'A5'), (19, 0, 'B2'), (19, 0, 'B3')],
1276+
'T' : [( 1, 0, 'B6'), ( 1, 0, 'A0'), ( 1, 0, 'B7'), ( 1, 0, 'A1'), ( 1, 0, 'C4'), ( 1, 0, 'C3')]},
1277+
'GW1N-9':
1278+
{'R' : [(18, 46, 'C6'), (18, 46, 'D7'), (18, 46, 'C7'), (18, 46, 'D6'), (18, 46, 'B6'), (18, 46, 'B7')],
1279+
'B' : [(28, 46, 'A2'), (28, 46, 'A4'), (28, 46, 'A3'), (28, 46, 'A5'), (28, 0, 'B2'), (28, 0, 'B3')],
1280+
'L' : [(18, 0, 'C6'), (18, 0, 'D7'), (18, 0, 'C7'), (18, 0, 'D6'), (18, 0, 'B6'), (18, 0, 'B7')],
1281+
'T' : [( 9, 0, 'C6'), ( 9, 0, 'D7'), ( 9, 0, 'C7'), ( 9, 0, 'D6'), ( 9, 0, 'B6'), ( 9, 0, 'B7')]},
1282+
'GW1N-9C':
1283+
{'R' : [(18, 46, 'C6'), (18, 46, 'D7'), (18, 46, 'C7'), (18, 46, 'D6'), (18, 46, 'B6'), (18, 46, 'B7')],
1284+
'B' : [(28, 46, 'A2'), (28, 46, 'A4'), (28, 46, 'A3'), (28, 46, 'A5'), (28, 0, 'B2'), (28, 0, 'B3')],
1285+
'L' : [(18, 0, 'C6'), (18, 0, 'D7'), (18, 0, 'C7'), (18, 0, 'D6'), (18, 0, 'B6'), (18, 0, 'B7')],
1286+
'T' : [( 9, 0, 'C6'), ( 9, 0, 'D7'), ( 9, 0, 'C7'), ( 9, 0, 'D6'), ( 9, 0, 'B6'), ( 9, 0, 'B7')]},
1287+
'GW2A-18':
1288+
{'R' : [(27, 55, 'A2'), (27, 55, 'A3'), (27, 55, 'D2'), (27, 55, 'D3'), (27, 55, 'D0'), (27, 55, 'D1')],
1289+
'B' : [(54, 27, 'A2'), (54, 27, 'A3'), (54, 27, 'D2'), (54, 27, 'D3'), (54, 27, 'D0'), (54, 27, 'D1')],
1290+
'L' : [(27, 0, 'A2'), (27, 0, 'A3'), (27, 0, 'D2'), (27, 0, 'D3'), (27, 0, 'D0'), (27, 0, 'D1')],
1291+
'T' : [( 0, 27, 'A2'), ( 0, 27, 'A3'), ( 0, 27, 'D2'), ( 0, 27, 'D3'), ( 0,27, 'D0'), ( 0, 27, 'D1')]},
1292+
'GW2A-18C':
1293+
{'R' : [(27, 55, 'A2'), (27, 55, 'A3'), (27, 55, 'D2'), (27, 55, 'D3'), (27, 55, 'D0'), (27, 55, 'D1')],
1294+
'B' : [(54, 27, 'A2'), (54, 27, 'A3'), (54, 27, 'D2'), (54, 27, 'D3'), (54, 27, 'D0'), (54, 27, 'D1')],
1295+
'L' : [(27, 0, 'A2'), (27, 0, 'A3'), (27, 0, 'D2'), (27, 0, 'D3'), (27, 0, 'D0'), (27, 0, 'D1')],
1296+
'T' : [( 0, 27, 'A2'), ( 0, 27, 'A3'), ( 0, 27, 'D2'), ( 0, 27, 'D3'), ( 0,27, 'D0'), ( 0, 27, 'D1')]},
1297+
}
1298+
def fse_create_dhcen(dev, device, fse, dat: Datfile):
1299+
if device not in _dhcen_ce:
1300+
print(f'No DHCEN for {device} for now.')
1301+
return
1302+
for side, ces in _dhcen_ce[device].items():
1303+
for idx, ce_wire in enumerate(ces):
1304+
row, col, wire = ce_wire
1305+
extra = dev.extra_func.setdefault((row, col), {})
1306+
dhcen = extra.setdefault('dhcen', [])
1307+
# use db.hclk_pips in order to find HCLK_IN cells
1308+
for hclk_loc in _hclk_to_fclk[device][side]['hclk']:
1309+
if idx < 4:
1310+
hclk_name = f'HCLK_IN{idx}'
1311+
else:
1312+
hclk_name = f'HCLK_BANK_OUT{idx - 4}'
1313+
if hclk_name in dev.hclk_pips[hclk_loc]:
1314+
hclkin = {'pip' : [f'X{hclk_loc[1]}Y{hclk_loc[0]}', hclk_name, next(iter(dev.hclk_pips[hclk_loc][hclk_name].keys())), side]}
1315+
1316+
hclkin.update({ 'ce' : wire})
1317+
dhcen.append(hclkin)
1318+
1319+
12391320
_pll_loc = {
12401321
'GW1N-1':
12411322
{'TRPLL0CLK0': (0, 17, 'F4'), 'TRPLL0CLK1': (0, 17, 'F5'),
@@ -1488,6 +1569,7 @@ def fse_create_clocks(dev, device, dat: Datfile, fse):
14881569

14891570

14901571
spines = {f'SPINE{i}' for i in range(32)}
1572+
hclk_srcs = {f'HCLK{i}_BANK_OUT{j}' for i in range(4) for j in range(2)}
14911573
dcs_inputs = {f'P{i}{j}{k}' for i in range(1, 5) for j in range(6, 8) for k in "ABCD"}
14921574
for row, rd in enumerate(dev.grid):
14931575
for col, rc in enumerate(rd):
@@ -1499,6 +1581,12 @@ def fse_create_clocks(dev, device, dat: Datfile, fse):
14991581
add_node(dev, dest, "GLOBAL_CLK", row, col, dest)
15001582
for src in { wire for wire in srcs.keys() if wire not in {'VCC', 'VSS'}}:
15011583
add_node(dev, src, "GLOBAL_CLK", row, col, src)
1584+
elif dest in {'HCLKMUX0', 'HCLKMUX1'}:
1585+
# this interbank communication between HCLKs
1586+
add_node(dev, dest, "GLOBAL_CLK", row, col, dest)
1587+
for src in {wire for wire in srcs.keys() if wire in hclk_srcs}:
1588+
add_node(dev, src, "GLOBAL_CLK", row, col, src)
1589+
15021590
# GBx0 <- GBOx
15031591
for spine_pair in range(4): # GB00/GB40, GB10/GB50, GB20/GB60, GB30/GB70
15041592
tap_start = _clock_data[device]['tap_start'][0]
@@ -2088,6 +2176,7 @@ def from_fse(device, fse, dat: Datfile):
20882176
fse_create_bandgap(dev, device)
20892177
fse_create_userflash(dev, device, dat)
20902178
fse_create_logic2clk(dev, device, dat)
2179+
fse_create_dhcen(dev, device, fse, dat)
20912180
disable_plls(dev, device)
20922181
sync_extra_func(dev)
20932182
set_chip_flags(dev, device);
@@ -3487,6 +3576,8 @@ def fse_wire_delays(db):
34873576
db.wire_delay[clknames[i]] = "CENT_SPINE_PCLK"
34883577
for i in range(129, 153): # clock inputs (logic->clock)
34893578
db.wire_delay[clknames[i]] = "CENT_SPINE_PCLK"
3579+
for i in range(1000, 1010): # HCLK
3580+
db.wire_delay[clknames[i]] = "X0" # XXX
34903581

34913582
# assign pads with plls
34923583
# for now use static table and store the bel name although it is always PLL without a number

apycula/gowin_pack.py

+60-2
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,7 @@ def get_bits(init_data):
185185
def get_bels(data):
186186
later = []
187187
if is_himbaechel:
188-
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*)")
188+
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*)")
189189
else:
190190
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*)")
191191

@@ -1989,6 +1989,43 @@ def set_osc_attrs(db, typ, params):
19891989
add_attr_val(db, 'OSC', fin_attrs, attrids.osc_attrids[attr], val)
19901990
return fin_attrs
19911991

1992+
_wire2attr_val = {
1993+
'HCLK_IN0': ('HSB0MUX0_HSTOP', 'HCLKCIBSTOP0'),
1994+
'HCLK_IN1': ('HSB1MUX0_HSTOP', 'HCLKCIBSTOP2'),
1995+
'HCLK_IN2': ('HSB0MUX1_HSTOP', 'HCLKCIBSTOP1'),
1996+
'HCLK_IN3': ('HSB1MUX1_HSTOP', 'HCLKCIBSTOP3'),
1997+
'HCLK_BANK_OUT0': ('BRGMUX0_BRGSTOP', 'BRGCIBSTOP0'),
1998+
'HCLK_BANK_OUT1': ('BRGMUX1_BRGSTOP', 'BRGCIBSTOP1'),
1999+
}
2000+
def find_and_set_dhcen_hclk_fuses(db, tilemap, wire, side):
2001+
fin_attrs = set()
2002+
attr, attr_val = _wire2attr_val[wire]
2003+
val = attrids.hclk_attrvals[attr_val]
2004+
add_attr_val(db, 'HCLK', fin_attrs, attrids.hclk_attrids[attr], val)
2005+
2006+
def set_fuse():
2007+
ttyp = db.grid[row][col].ttyp
2008+
if 'HCLK' in db.shortval[ttyp]:
2009+
bits = get_shortval_fuses(db, ttyp, fin_attrs, "HCLK")
2010+
tile = tilemap[row, col]
2011+
for r, c in bits:
2012+
tile[r][c] = 1
2013+
2014+
if side in "TB":
2015+
if side == 'T':
2016+
row = 0
2017+
else:
2018+
row = db.rows - 1
2019+
for col in range(db.cols):
2020+
set_fuse()
2021+
else:
2022+
if side == 'L':
2023+
col = 0
2024+
else:
2025+
col = db.cols - 1
2026+
for row in range(db.rows):
2027+
set_fuse()
2028+
19922029
def bin_str_to_dec(str_val):
19932030
bin_pattern = r'^[0,1]+'
19942031
bin_str = re.findall(bin_pattern, str_val)
@@ -2035,7 +2072,6 @@ def set_hclk_attrs(db, params, num, typ, cell_name):
20352072
add_attr_val(db, 'HCLK', fin_attrs, attrids.hclk_attrids[attr], val)
20362073
return fin_attrs
20372074

2038-
20392075
_iologic_default_attrs = {
20402076
'DUMMY': {},
20412077
'IOLOGIC': {},
@@ -2502,9 +2538,19 @@ def place(db, tilemap, bels, cst, args):
25022538
cfg_tile = tilemap[(0, 37)]
25032539
for r, c in bits:
25042540
cfg_tile[r][c] = 1
2541+
elif typ == "DHCEN":
2542+
if 'DHCEN_USED' not in attrs:
2543+
continue
2544+
# DHCEN as such is just a control wire and does not have a fuse
2545+
# itself, but HCLK has fuses that allow this control. Here we look
2546+
# for the corresponding HCLK and set its fuses.
2547+
_, wire, _, side = db.extra_func[row - 1, col -1]['dhcen'][int(num)]['pip']
2548+
hclk_attrs = find_and_set_dhcen_hclk_fuses(db, tilemap, wire, side)
25052549
elif typ in ["CLKDIV", "CLKDIV2"]:
25062550
hclk_attrs = set_hclk_attrs(db, parms, num, typ, cellname)
25072551
bits = get_shortval_fuses(db, tiledata.ttyp, hclk_attrs, "HCLK")
2552+
for r, c in bits:
2553+
tile[r][c] = 1
25082554
elif typ == 'DQCE':
25092555
# Himbaechel only
25102556
pipre = re.compile(r"X(\d+)Y(\d+)/([\w_]+)/([\w_]+)")
@@ -2693,6 +2739,17 @@ def secure_long_wires(db, tilemap, row, col, src, dest):
26932739
for row, col in bits:
26942740
tile[row][col] = 1
26952741

2742+
# hclk interbank requires to set some non-route fuses
2743+
def do_hclk_banks(db, row, col, src, dest):
2744+
res = set()
2745+
if dest in {'HCLK_BANK_OUT0', 'HCLK_BANK_OUT1'}:
2746+
fin_attrs = set()
2747+
add_attr_val(db, 'HCLK', fin_attrs, attrids.hclk_attrids[f'BRGMUX{dest[-1]}_BRGOUT'], attrids.hclk_attrvals['ENABLE'])
2748+
2749+
ttyp = db.grid[row][col].ttyp
2750+
if 'HCLK' in db.shortval[ttyp]:
2751+
res = get_shortval_fuses(db, ttyp, fin_attrs, "HCLK")
2752+
return res
26962753

26972754
def route(db, tilemap, pips):
26982755
for row, col, src, dest in pips:
@@ -2704,6 +2761,7 @@ def route(db, tilemap, pips):
27042761
bits = tiledata.clock_pips[dest][src]
27052762
elif is_himbaechel and (row - 1, col - 1) in db.hclk_pips and dest in db.hclk_pips[row - 1, col - 1]:
27062763
bits = db.hclk_pips[row - 1, col - 1][dest][src]
2764+
bits.update(do_hclk_banks(db, row - 1, col - 1, src, dest))
27072765
else:
27082766
bits = tiledata.pips[dest][src]
27092767
except KeyError:

apycula/wirenames.py

+14-2
Original file line numberDiff line numberDiff line change
@@ -119,19 +119,31 @@
119119
})
120120

121121
clknames.update({n: f"UNK{n}" for n in range(210, 261)})
122+
123+
# HCLK->clock network
124+
# Each HCLK can connect to other HCLKs through two MUXes in the clock system.
125+
# Here we assign numbers to these MUXes and their inputs - two per HCLK
126+
clknames.update({
127+
1000: 'HCLKMUX0', 1001: 'HCLKMUX1',
128+
1002: 'HCLK0_BANK_OUT0', 1003: 'HCLK0_BANK_OUT1',
129+
1004: 'HCLK1_BANK_OUT0', 1005: 'HCLK1_BANK_OUT1',
130+
1006: 'HCLK2_BANK_OUT0', 1007: 'HCLK2_BANK_OUT1',
131+
1008: 'HCLK3_BANK_OUT0', 1009: 'HCLK3_BANK_OUT1',
132+
})
133+
122134
clknumbers = {v: k for k, v in clknames.items()}
123135

124136
# hclk
125137
hclknames = clknames.copy()
126138
hclknames.update({n: f"HCLK_UNK{n}" for n in range(26)})
127139
# inputs
128140
hclknames.update({
129-
2: 'HCLK_IN0', 3: 'HCLK_IN1', 4: 'HCLK_IN2', 5: 'HCLK_IN3'
141+
2: 'HCLK_IN0', 3: 'HCLK_IN1', 4: 'HCLK_IN2', 5: 'HCLK_IN3', 8: 'HCLK_BANK_IN0', 9: 'HCLK_BANK_IN1'
130142
})
131143

132144
# HCLK section inputs
133145
hclknames.update({
134-
10: 'HCLK0_SECT0_IN', 11: 'HCLK0_SECT1_IN', 12: 'HCLK1_SECT0_IN', 13: 'HCLK1_SECT1_IN'
146+
6: 'HCLK_BANK_OUT0', 7: 'HCLK_BANK_OUT1', 10: 'HCLK0_SECT0_IN', 11: 'HCLK0_SECT1_IN', 12: 'HCLK1_SECT0_IN', 13: 'HCLK1_SECT1_IN'
135147
})
136148

137149
# Bypass connections from HCLK_IN to HCLK_OUT

examples/himbaechel/Makefile.himbaechel

+2-2
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ NEXTPNR ?= nextpnr-himbaechel
66
all: \
77
blinky-tangnano20k.fs shift-tangnano20k.fs blinky-tbuf-tangnano20k.fs blinky-oddr-tangnano20k.fs \
88
blinky-osc-tangnano20k.fs tlvds-tangnano20k.fs elvds-tangnano20k.fs oddr-tlvds-tangnano20k.fs \
9-
blinky-clkdiv-tangnano20k.fs dvi-example-tangnano20k.fs\
9+
blinky-clkdiv-tangnano20k.fs dvi-example-tangnano20k.fs blinky-clkdiv-dhcen-tangnano20k.fs \
1010
oddr-elvds-tangnano20k.fs pll-nanolcd-tangnano20k.fs attosoc-tangnano20k.fs \
1111
oser4-tangnano20k.fs ovideo-tangnano20k.fs oser8-tangnano20k.fs oser10-tangnano20k.fs \
1212
ides4-tangnano20k.fs ivideo-tangnano20k.fs ides8-tangnano20k.fs ides10-tangnano20k.fs \
@@ -21,7 +21,7 @@ all: \
2121
\
2222
blinky-primer20k.fs shift-primer20k.fs blinky-tbuf-primer20k.fs blinky-oddr-primer20k.fs \
2323
blinky-osc-primer20k.fs tlvds-primer20k.fs elvds-primer20k.fs oddr-tlvds-primer20k.fs \
24-
blinky-clkdiv-primer20k.fs dvi-example-primer20k.fs\
24+
blinky-clkdiv-primer20k.fs dvi-example-primer20k.fs blinky-clkdiv-dhcen-primer20k.fs \
2525
oddr-elvds-primer20k.fs pll-nanolcd-primer20k.fs attosoc-primer20k.fs \
2626
oser4-primer20k.fs ovideo-primer20k.fs oser8-primer20k.fs oser10-primer20k.fs \
2727
ides4-primer20k.fs ivideo-primer20k.fs ides8-primer20k.fs ides10-primer20k.fs \
+83
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
module top (
2+
input clk,
3+
input key_i,
4+
output [`LEDS_NR-1:0] led
5+
);
6+
7+
/* Expected Result:
8+
- 1 or 2 LEDs blinking, depending on your board.
9+
- The `faster` LED is associated with the input clock.
10+
- The `slower` LED is associated with a divided clock.
11+
- On boards with multiple CLKDIVs, the slower LED's blink rate changes as it cycles through CLKDIVs
12+
configured with different DIV_MODES.
13+
- If your board has only one LED, it should blink with the divided clock.
14+
- Holding the appropriate button should stop the blinking.
15+
*/
16+
17+
localparam /*string*/ DIV_MODE_2 = "2";
18+
localparam /*string*/ DIV_MODE_35 = "3.5";
19+
localparam /*string*/ DIV_MODE_4 = "4";
20+
localparam /*string*/ DIV_MODE_5 = "5";
21+
22+
23+
wire key = key_i ^ `INV_BTN;
24+
25+
reg [25:0] ctr_q;
26+
wire [25:0] ctr_d;
27+
// localparam NUM_HCLKi=NUM_HCLK;
28+
29+
wire [`NUM_HCLK-1:0] hclk_counts;
30+
reg [$clog2(`NUM_HCLK)-1:0] curr_hclk_idx;
31+
wire curr_hclk;
32+
reg [30:0] sup_count;
33+
34+
35+
wire managed_clk;
36+
DHCEN dhcen(
37+
.CLKIN(clk),
38+
.CE(key),
39+
.CLKOUT(managed_clk)
40+
);
41+
42+
genvar i;
43+
generate
44+
for (i=0; i < `NUM_HCLK; i=i+1) begin:hcount
45+
localparam /*string*/ div_mode =(i % 4 == 0) ? DIV_MODE_5 :
46+
(i % 4 == 1) ? DIV_MODE_4 :
47+
(i % 4 == 2) ? DIV_MODE_35 :
48+
DIV_MODE_2;
49+
50+
wire div2_out;
51+
wire o_clk;
52+
53+
CLKDIV2 my_div2 (
54+
.RESETN(1'b1),
55+
.HCLKIN(managed_clk),
56+
.CLKOUT(div2_out)
57+
);
58+
59+
CLKDIV #(.DIV_MODE(div_mode)) my_div (
60+
.RESETN(1'b1),
61+
.HCLKIN(div2_out),
62+
.CLKOUT(o_clk)
63+
);
64+
65+
reg [23:0] count;
66+
always @(posedge o_clk)begin
67+
count <= count + 1'b1;
68+
end
69+
assign hclk_counts[i] = count[23];
70+
end
71+
endgenerate
72+
73+
always @(posedge clk) begin
74+
sup_count <= sup_count + 1'b1;
75+
curr_hclk_idx <= curr_hclk_idx + sup_count[29];
76+
if (curr_hclk_idx == `NUM_HCLK-1)
77+
curr_hclk_idx <= 0;
78+
end
79+
80+
assign curr_hclk = hclk_counts[curr_hclk_idx];
81+
assign led = {curr_hclk, sup_count[23]};
82+
83+
endmodule

0 commit comments

Comments
 (0)