Skip to content

Commit 158f3e2

Browse files
authored
Add oscillator to chipdb (#97)
* Add oscillator to chipdb * Add packer for oscillator * Add blinky example using internal oscillator * Add unpack for oscillator
1 parent 74af186 commit 158f3e2

File tree

6 files changed

+125
-19
lines changed

6 files changed

+125
-19
lines changed

apycula/chipdb.py

+48-6
Original file line numberDiff line numberDiff line change
@@ -156,10 +156,7 @@ def add_alu_mode(base_mode, modes, lut, new_alu_mode, new_mode_bits):
156156

157157
# also make ALUs and shadow RAM
158158
def fse_luts(fse, ttyp):
159-
try:
160-
data = fse[ttyp]['shortval'][5]
161-
except KeyError:
162-
return {}
159+
data = fse[ttyp]['shortval'][5]
163160

164161
luts = {}
165162
for lutn, bit, *fuses in data:
@@ -263,6 +260,48 @@ def fse_luts(fse, ttyp):
263260
}
264261
return luts
265262

263+
def fse_osc(device, fse, ttyp):
264+
osc = {}
265+
266+
if device in {'GW1N-4', 'GW1N-9', 'GW1N-9C'}:
267+
bel = osc.setdefault(f"OSC", Bel())
268+
elif device in {'GW1NZ-1', 'GW1NS-4'}:
269+
bel = osc.setdefault(f"OSCZ", Bel())
270+
elif device == 'GW1NS-2':
271+
bel = osc.setdefault(f"OSCF", Bel())
272+
elif device == 'GW1N-1':
273+
bel = osc.setdefault(f"OSCH", Bel())
274+
else:
275+
raise Exception(f"Oscillator not yet supported on {device}")
276+
277+
bel.portmap = {}
278+
279+
if device in {'GW1N-1', 'GW1N-4', 'GW1N-9', 'GW1N-9C', 'GW1NS-2', 'GW1NS-4'}:
280+
bel.portmap['OSCOUT'] = "Q4"
281+
elif device == 'GW1NZ-1':
282+
bel.portmap['OSCOUT'] = "OF3"
283+
284+
if device == 'GW1NS-2':
285+
bel.portmap['OSCEN'] = "B3"
286+
elif device == 'GW1NS-4':
287+
bel.portmap['OSCEN'] = "D6"
288+
elif device == 'GW1NZ-1':
289+
bel.portmap['OSCEN'] = "A6"
290+
291+
data = fse[ttyp]['shortval'][51]
292+
293+
for i in range(64):
294+
bel.modes.setdefault(i+1, set())
295+
296+
for key0, key1, *fuses in data:
297+
if key0 <= 64 and key1 == 0:
298+
mode = bel.modes[key0]
299+
for f in (f for f in fuses if f != -1):
300+
coord = fuse.fuse_lookup(fse, ttyp, f)
301+
mode.update({coord})
302+
303+
return osc
304+
266305
# XXX This is not a nice way, I will replace it with automatic creation of banks
267306
# in the very near future.
268307
def set_banks(device, db):
@@ -295,7 +334,7 @@ def set_banks(device, db):
295334
db.grid[h][w].bels.setdefault('BANK2', Bel())
296335
db.grid[h][0].bels.setdefault('BANK3', Bel())
297336

298-
def from_fse(fse):
337+
def from_fse(device, fse):
299338
dev = Device()
300339
ttypes = {t for row in fse['header']['grid'][61] for t in row}
301340
tiles = {}
@@ -305,7 +344,10 @@ def from_fse(fse):
305344
tile = Tile(w, h)
306345
tile.pips = fse_pips(fse, ttyp, 2, wirenames)
307346
tile.clock_pips = fse_pips(fse, ttyp, 38, clknames)
308-
tile.bels = fse_luts(fse, ttyp)
347+
if 5 in fse[ttyp]['shortval']:
348+
tile.bels = fse_luts(fse, ttyp)
349+
if 51 in fse[ttyp]['shortval']:
350+
tile.bels = fse_osc(device, fse, ttyp)
309351
tiles[ttyp] = tile
310352

311353
dev.grid = [[tiles[ttyp] for ttyp in row] for row in fse['header']['grid'][61]]

apycula/gowin_pack.py

+10-1
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ def sanitize_name(name):
2828

2929
def get_bels(data):
3030
later = []
31-
belre = re.compile(r"R(\d+)C(\d+)_(?:GSR|SLICE|IOB|MUX2_LUT5|MUX2_LUT6|MUX2_LUT7|MUX2_LUT8|ODDR)(\w)")
31+
belre = re.compile(r"R(\d+)C(\d+)_(?:GSR|SLICE|IOB|MUX2_LUT5|MUX2_LUT6|MUX2_LUT7|MUX2_LUT8|ODDR|OSC[ZFH]?)(\w*)")
3232
for cellname, cell in data['modules']['top']['cells'].items():
3333
bel = cell['attributes']['NEXTPNR_BEL']
3434
if bel in {"VCC", "GND"}: continue
@@ -91,6 +91,15 @@ def place(db, tilemap, bels, cst, args):
9191
tile = tilemap[(row-1, col-1)]
9292
if typ == "GSR":
9393
pass
94+
if typ in {'OSC', 'OSCZ', 'OSCF', 'OSCH'}:
95+
divisor = int(parms['FREQ_DIV'], 2)
96+
if divisor % 2 == 1:
97+
raise Exception(f"Divisor of {typ} must be even")
98+
divisor //= 2
99+
if divisor in tiledata.bels[typ].modes:
100+
bits = tiledata.bels[typ].modes[divisor]
101+
for r, c in bits:
102+
tile[r][c] = 1
94103
if typ == "SLICE":
95104
lutmap = tiledata.bels[f'LUT{num}'].flags
96105

apycula/gowin_unpack.py

+11-2
Original file line numberDiff line numberDiff line change
@@ -268,7 +268,7 @@ def tile2verilog(dbrow, dbcol, bels, pips, clock_pips, mod, cst, db):
268268
mod.wires.update({srcg, destg})
269269
mod.assigns.append((destg, srcg))
270270

271-
belre = re.compile(r"(IOB|LUT|DFF|BANK|CFG|ALU|RAM16|ODDR)(\w*)")
271+
belre = re.compile(r"(IOB|LUT|DFF|BANK|CFG|ALU|RAM16|ODDR|OSC[ZFH]?)(\w*)")
272272
if have_iologic(bels):
273273
bels_items = move_iologic(bels)
274274
else:
@@ -341,7 +341,16 @@ def tile2verilog(dbrow, dbcol, bels, pips, clock_pips, mod, cst, db):
341341
ram16.portmap['DO'] = [f"R{row}C{col}_F{x}" for x in range(4)]
342342
mod.wires.update(chain.from_iterable([x if isinstance(x, list) else [x] for x in ram16.portmap.values()]))
343343
mod.primitives[name] = ram16
344-
344+
elif typ in {"OSC", "OSCZ", "OSCF", "OSCH"}:
345+
name = f"R{row}C{col}_{typ}"
346+
osc = codegen.Primitive(typ, name)
347+
divisor, = flags
348+
osc.params["FREQ_DIV"] = f"{divisor*2}"
349+
portmap = db.grid[dbrow][dbcol].bels[bel].portmap
350+
for port, wname in portmap.items():
351+
osc.portmap[port] = f"R{row}C{col}_{wname}"
352+
mod.wires.update(osc.portmap.values())
353+
mod.primitives[name] = osc
345354
elif typ == "DFF":
346355
#print(flags)
347356
kind, = flags # DFF only have one flag

apycula/tiled_fuzzer.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -917,7 +917,7 @@ def run_pnr(mod, constr, config):
917917
with open(f"{gowinhome}/IDE/share/device/{device}/{device}.tm", 'rb') as f:
918918
tm = tm_h4x.read_tm(f, device)
919919

920-
db = chipdb.from_fse(fse)
920+
db = chipdb.from_fse(device, fse)
921921
chipdb.set_banks(device, db)
922922
db.timing = tm
923923
db.packages, db.pinout, db.pin_bank = chipdb.json_pinout(device)

examples/Makefile

+15-9
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,10 @@ all: attosoc-tec0117.fs nanolcd-tangnano.fs blinky-tec0117.fs blinky-runber.fs \
1010
tlvds-oddr-tangnano4k.fs tlvds-oddr-tangnano9k.fs tlvds-oddr-tec0117.fs \
1111
blinky-oddr-tec0117.fs blinky-oddr-runber.fs \
1212
blinky-oddr-tangnano.fs blinky-oddr-honeycomb.fs \
13-
blinky-oddr-tangnano4k.fs blinky-oddr-tangnano9k.fs
13+
blinky-oddr-tangnano4k.fs blinky-oddr-tangnano9k.fs \
14+
blinky-osc-tec0117.fs blinky-osc-runber.fs blinky-osc-tangnano.fs \
15+
blinky-osc-honeycomb.fs blinky-osc-default-flags-tangnano.fs \
16+
blinky-osc-tangnano9k.fs blinky-osc-tangnano1k.fs blinky-osc-tangnano4k.fs
1417

1518
unpacked: attosoc-tec0117-unpacked.v nanolcd-tangnano-unpacked.v blinky-tec0117-unpacked.v blinky-runber-unpacked.v \
1619
blinky-tangnano-unpacked.v blinky-honeycomb-unpacked.v shift-tec0117-unpacked.v shift-runber-unpacked.v \
@@ -22,7 +25,10 @@ unpacked: attosoc-tec0117-unpacked.v nanolcd-tangnano-unpacked.v blinky-tec0117-
2225
blinky-oddr-tec0117-unpacked.v blinky-oddr-runber-unpacked.v \
2326
blinky-oddr-tangnano-unpacked.v blinky-oddr-honeycomb-unpacked.v \
2427
blinky-oddr-tangnano-unpacked.v blinky-oddr-honeycomb-unpacked.v \
25-
blinky-oddr-tangnano4k-unpacked.v blinky-oddr-tangnano9k-unpacked.v
28+
blinky-oddr-tangnano4k-unpacked.v blinky-oddr-tangnano9k-unpacked.v \
29+
blinky-osc-tec0117-unpacked.v blinky-osc-runber-unpacked.v blinky-osc-tangnano-unpacked.v \
30+
blinky-osc-honeycomb-unpacked.v blinky-osc-default-flags-tangnano-unpacked.v \
31+
blinky-osc-tangnano9k-unpacked.v blinky-osc-tangnano1k-unpacked.v blinky-osc-tangnano4k-unpacked.v
2632

2733
clean:
2834
rm -f *.json *.fs *-unpacked.v
@@ -91,25 +97,25 @@ nanolcd-tangnano-synth.json: nanolcd/TOP.v nanolcd/VGAMod.v
9197
$(YOSYS) -p "read_verilog $^; synth_gowin -json $@"
9298

9399
%-tec0117-synth.json: %.v
94-
$(YOSYS) -D LEDS_NR=8 -p "read_verilog $^; synth_gowin -json $@"
100+
$(YOSYS) -D LEDS_NR=8 -D OSC_TYPE_OSC -p "read_verilog $^; synth_gowin -json $@"
95101

96102
%-runber-synth.json: %.v
97-
$(YOSYS) -D LEDS_NR=8 -p "read_verilog $^; synth_gowin -json $@"
103+
$(YOSYS) -D LEDS_NR=8 -D OSC_TYPE_OSC -p "read_verilog $^; synth_gowin -json $@"
98104

99105
%-tangnano-synth.json: %.v
100-
$(YOSYS) -D LEDS_NR=3 -p "read_verilog $^; synth_gowin -json $@"
106+
$(YOSYS) -D LEDS_NR=3 -D OSC_TYPE_OSCH -p "read_verilog $^; synth_gowin -json $@"
101107

102108
%-tangnano1k-synth.json: %.v
103-
$(YOSYS) -D LEDS_NR=3 -p "read_verilog $^; synth_gowin -json $@"
109+
$(YOSYS) -D LEDS_NR=3 -D OSC_TYPE_OSCZ -p "read_verilog $^; synth_gowin -json $@"
104110

105111
%-tangnano4k-synth.json: %.v
106-
$(YOSYS) -D LEDS_NR=6 -p "read_verilog $^; synth_gowin -json $@"
112+
$(YOSYS) -D LEDS_NR=6 -D OSC_TYPE_OSCZ -p "read_verilog $^; synth_gowin -json $@"
107113

108114
%-tangnano9k-synth.json: %.v
109-
$(YOSYS) -D LEDS_NR=6 -p "read_verilog $^; synth_gowin -json $@"
115+
$(YOSYS) -D LEDS_NR=6 -D OSC_TYPE_OSC -p "read_verilog $^; synth_gowin -json $@"
110116

111117
%-honeycomb-synth.json: %.v
112-
$(YOSYS) -D LEDS_NR=3 -p "read_verilog $^; synth_gowin -json $@"
118+
$(YOSYS) -D LEDS_NR=3 -D OSC_TYPE_OSCF -p "read_verilog $^; synth_gowin -json $@"
113119

114120
%-honeycomb-prog: %-honeycomb.fs
115121
openFPGALoader -b honeycomb $^

examples/blinky-osc.v

+40
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
module top (
2+
output [`LEDS_NR-1:0] led
3+
);
4+
5+
wire clk;
6+
7+
`ifdef OSC_TYPE_OSC
8+
OSC osc(
9+
.OSCOUT(clk)
10+
);
11+
`elsif OSC_TYPE_OSCZ
12+
OSCZ osc(
13+
.OSCEN(1'b1),
14+
.OSCOUT(clk)
15+
);
16+
`elsif OSC_TYPE_OSCF
17+
OSCF osc(
18+
.OSCEN(1'b1),
19+
.OSCOUT(clk),
20+
.OSCOUT30M()
21+
);
22+
`elsif OSC_TYPE_OSCH
23+
OSCH osc(
24+
.OSCOUT(clk)
25+
);
26+
`endif
27+
defparam osc.FREQ_DIV=128;
28+
29+
reg [25:0] ctr_q;
30+
wire [25:0] ctr_d;
31+
32+
// Sequential code (flip-flop)
33+
always @(posedge clk)
34+
ctr_q <= ctr_d;
35+
36+
// Combinational code (boolean logic)
37+
assign ctr_d = ctr_q + 1'b1;
38+
assign led = ctr_q[25:25-(`LEDS_NR - 1)];
39+
40+
endmodule

0 commit comments

Comments
 (0)