Skip to content

Commit

Permalink
Merge pull request YosysHQ#241 from yrabbit/pll-pads
Browse files Browse the repository at this point in the history
Add PLL pads.
  • Loading branch information
yrabbit authored May 3, 2024
2 parents 91807b0 + 94b85ed commit 14efe42
Show file tree
Hide file tree
Showing 5 changed files with 138 additions and 2 deletions.
71 changes: 71 additions & 0 deletions apycula/chipdb.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,9 @@ class Device:
bottom_io: Tuple[str, str, List[Tuple[str, str]]] = field(default_factory = tuple)
# simplified IO rows
simplio_rows: Set[int] = field(default_factory = set)
# which PLL does this pad belong to. {IOLOC: (row, col, type, bel_name)}
# type = {'CLKIN_T', 'CLKIN_C', 'FB_T', 'FB_C'}
pad_pll: Dict[str, Tuple[int, int, str, str]] = field(default_factory = dict)
# tile types by func. The same ttyp number can correspond to different
# functional blocks on different chips. For example 86 is the PLL head ttyp
# for GW2A-18 and the same number is used in GW1N-1 where it has nothing to
Expand Down Expand Up @@ -3002,4 +3005,72 @@ def loc2bank(db, row, col):
bank = db.pin_bank[name + 'B']
return bank

# assign pads with plls
# for now use static table and store the bel name although it is always PLL without a number
# theoretically, we can determine which PLL pad belongs to from the list of
# functions, but for them we will have to write a special parser since the
# format is very diverse (example: RPLL1_T_IN, RPLL_C_IN, TPLL_T_IN2). And we
# will still need a table with the coordinates of the PLL itself.
_pll_pads = {
'GW1N-1': { 'IOR5A' : (0, 17, 'CLKIN_T', 'PLL'),
'IOR5B' : (0, 17, 'CLKIN_C', 'PLL'),
'IOR4A' : (0, 17, 'FB_T', 'PLL'),
'IOR4B' : (0, 17, 'FB_C', 'PLL') },
'GW1NZ-1': { 'IOR5A' : (0, 17, 'CLKIN_T', 'PLL'),
'IOR5B' : (0, 17, 'CLKIN_C', 'PLL') },
'GW1N-4': { 'IOL3A' : (0, 9, 'CLKIN_T', 'PLL'),
'IOL3B' : (0, 9, 'CLKIN_C', 'PLL'),
'IOL4A' : (0, 9, 'FB_T', 'PLL'),
'IOL4B' : (0, 9, 'FB_C', 'PLL'),
'IOR3A' : (0, 27, 'CLKIN_T', 'PLL'),
'IOR3B' : (0, 27, 'CLKIN_C', 'PLL'),
'IOR4A' : (0, 27, 'FB_T', 'PLL'),
'IOR4B' : (0, 27, 'FB_C', 'PLL'), },
'GW1NS-4': { 'IOR2A' : (0, 36, 'CLKIN_T', 'PLL'),
'IOR2B' : (0, 36, 'CLKIN_C', 'PLL'),
'IOT13A' : (0, 27, 'CLKIN_T', 'PLL'),
'IOT13B' : (0, 27, 'CLKIN_C', 'PLL'), },
'GW1N-9': { 'IOL5A' : (9, 0, 'CLKIN_T', 'PLL'),
'IOL5B' : (9, 0, 'CLKIN_C', 'PLL'),
'IOR5A' : (9, 46, 'CLKIN_T', 'PLL'),
'IOR5B' : (9, 46, 'CLKIN_C', 'PLL'),
'IOR6A' : (9, 46, 'FB_T', 'PLL'),
'IOR6B' : (9, 46, 'FB_C', 'PLL'), },
'GW1N-9C': { 'IOL5A' : (9, 0, 'CLKIN_T', 'PLL'),
'IOL5B' : (9, 0, 'CLKIN_C', 'PLL'),
'IOR5A' : (9, 46, 'CLKIN_T', 'PLL'),
'IOR5B' : (9, 46, 'CLKIN_C', 'PLL'),
'IOR6A' : (9, 46, 'FB_T', 'PLL'),
'IOR6B' : (9, 46, 'FB_C', 'PLL'), },
'GW1N-9C': { 'IOL5A' : (9, 0, 'CLKIN_T', 'PLL'),
'IOL5B' : (9, 0, 'CLKIN_C', 'PLL'),
'IOR5A' : (9, 46, 'CLKIN_T', 'PLL'),
'IOR5B' : (9, 46, 'CLKIN_C', 'PLL'),
'IOR6A' : (9, 46, 'FB_T', 'PLL'),
'IOR6B' : (9, 46, 'FB_C', 'PLL'), },
'GW2A-18': { 'IOL7A' : (9, 0, 'CLKIN_T', 'PLL'),
'IOL45A' : (45, 0, 'CLKIN_T', 'PLL'),
'IOL47A' : (45, 0, 'FB_T', 'PLL'),
'IOL47B' : (45, 0, 'FB_C', 'PLL'),
'IOR45A' : (45, 0, 'CLKIN_T', 'PLL'), },
'GW2A-18C': { 'IOR7A' : (9, 55, 'CLKIN_T', 'PLL'),
'IOR7B' : (9, 55, 'CLKIN_C', 'PLL'),
'IOR8A' : (9, 55, 'FB_T', 'PLL'),
'IOR8B' : (9, 55, 'FN_C', 'PLL'),
'IOL7A' : (9, 0, 'CLKIN_T', 'PLL'),
'IOL7B' : (9, 0, 'CLKIN_C', 'PLL'),
'IOL45A' : (45, 0, 'CLKIN_T', 'PLL'),
'IOL45B' : (45, 0, 'CLKIN_C', 'PLL'),
'IOL47A' : (45, 0, 'FB_T', 'PLL'),
'IOL47B' : (45, 0, 'FB_C', 'PLL'),
'IOR45A' : (45, 55, 'CLKIN_T', 'PLL'),
'IOR45B' : (45, 55, 'CLKIN_C', 'PLL'),
'IOR47A' : (45, 55, 'FB_T', 'PLL'),
'IOR47B' : (45, 55, 'FB_C', 'PLL'), },
}
def pll_pads(dev, device, pad_locs):
if device not in _pll_pads:
return
for loc, pll_data in _pll_pads[device].items():
dev.pad_pll[loc] = pll_data

5 changes: 5 additions & 0 deletions apycula/pindef.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,11 @@ def get_clock_locs(device, package):
return [(pin['NAME'], *pin['CFG'].split('/')) for pin in df
if 'CFG' in pin.keys() and pin['CFG'].startswith("GCLK")]

def get_pll_pads_locs(device, package):
df = get_package(device, package, True)
return [(pin['NAME'], *pin['CFG'].split('/')) for pin in df
if 'CFG' in pin.keys() and 'PLL' in pin['CFG']]

# { name : (is_diff, is_true_lvds, is_positive)}
def get_diff_cap_info(device, package, special_pins=False):
df = get_package(device, package, special_pins)
Expand Down
5 changes: 4 additions & 1 deletion apycula/tiled_fuzzer.py
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@ def fse_iob(fse, db, pin_locations, diff_cap_info, locations):
bel.is_diff = is_diff
bel.is_true_lvds = is_true_lvds
bel.is_diff_p = is_positive
print(f"type:{ttyp} [{row}][{col}], IOB{bel_name[-1]}, diff:{is_diff}, true lvds:{is_true_lvds}, p:{is_positive}")
#print(f"type:{ttyp} [{row}][{col}], IOB{bel_name[-1]}, diff:{is_diff}, true lvds:{is_true_lvds}, p:{is_positive}")
for ttyp, bels in iob_bels.items():
for row, col in locations[ttyp]:
db.grid[row][col].bels.update(iob_bels[ttyp])
Expand Down Expand Up @@ -262,6 +262,9 @@ def fse_iob(fse, db, pin_locations, diff_cap_info, locations):
diff_cap_info = pindef.get_diff_cap_info(device, params['package'], True)
fse_iob(fse, db, pin_locations, diff_cap_info, locations);

pad_locs = pindef.get_pll_pads_locs(device, params['package'])
chipdb.pll_pads(db, device, pad_locs)

chipdb.dat_portmap(dat, db, device)

# XXX GW1NR-9 has interesting IOBA pins on the bottom side
Expand Down
2 changes: 1 addition & 1 deletion examples/himbaechel/Makefile.himbaechel
Original file line number Diff line number Diff line change
Expand Up @@ -291,7 +291,7 @@ bsram-%-tangnano1k-synth.json: pll/GW1NZ-1-dyn.vh %-image-rom.v %-video-ram.v %.
%-tangnano4k-synth.json: %.v
$(YOSYS) -D LEDS_NR=6 -D OSC_TYPE_OSCZ -D INV_BTN=0 -D FORCE_BRAM -D CPU_FREQ=27 -D BAUD_RATE=115200 -p "read_verilog $^; synth_gowin -json $@"

blinky-pll-tangnano4k-synth.json: pll/GW1NS-4-dyn.vh blinky-pll-vr.v
%-pll-tangnano4k-synth.json: pll/GW1NS-4-dyn.vh %-pll-vr.v
$(YOSYS) -D INV_BTN=0 -D LEDS_NR=6 -p "read_verilog $^; synth_gowin -json $@"

# ============================================================
Expand Down
57 changes: 57 additions & 0 deletions examples/himbaechel/dual-pll-vr.v
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
`default_nettype none
`include "pll/pllvr.v"
// Two PLLs, one dynamic - frequencies are switched by pressing key2
// / press key2
// led[0] - pin 34 - 58.5MHz / 90MHz
// led[1] - pin 35 - LOCK PLL_0
// led[2] - pin 29 - 464KHz / 714KHz
//
// led[3] - pin 30 - 90MHz
// led[4] - pin 31 - LOCK PLL_1
// led[5] - pin 32 - 714KHz
module top(input wire clk, output wire [5:0]led, input wire key_i);
wire gnd;
assign gnd = 1'b0;
wire dummy;
reg [5:0] fdiv;
reg [5:0] idiv;
reg [5:0] odiv;
Gowin_PLLVR rpll_0(
.clkout(led[0]),
.clkin(clk),
.lock_o(led[1]),
.reset(gnd),
.reset_p(gnd),
.clkfb(gnd),
.clkoutd_o(led[2]),
.fdiv(fdiv),
.idiv(idiv),
.odiv(6'b111100) // 8
);

Gowin_PLLVR rpll_1(
.clkout(led[3]),
.clkin(clk),
.lock_o(led[4]),
.reset(gnd),
.reset_p(gnd),
.clkfb(gnd),
.clkoutd_o(led[5]),
.fdiv(~6'd9),
.idiv(~6'd2),
.odiv(6'b111100) // 8
);

// dynamic
always @ (posedge clk) begin
if (key_i) begin
fdiv <= ~6'd12;
idiv <= ~6'd5;
odiv <= 6'b111000; // 16
end else begin
fdiv <= ~6'd9;
idiv <= ~6'd2;
odiv <= ~6'b111100; // 8
end
end
endmodule

0 comments on commit 14efe42

Please sign in to comment.