Skip to content

Commit

Permalink
Merge branch 'master' into iem-w
Browse files Browse the repository at this point in the history
  • Loading branch information
yrabbit committed Dec 11, 2024
2 parents d9f3f78 + 456c609 commit 10f243e
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 57 deletions.
4 changes: 2 additions & 2 deletions apycula/gowin_pack.py
Original file line number Diff line number Diff line change
Expand Up @@ -271,8 +271,8 @@ def infovaluemap(infovalue, start=2):
"GW1N-9": (400, 500, 3.125, 1000, 400),
"GW1N-9C": (400, 600, 3.125, 1200, 400),
"GW1NS-2": (400, 500, 3.125, 1200, 400),
"GW2A-18": (400, 600, 3.125, 1200, 400), # XXX check it
"GW2A-18C": (400, 600, 3.125, 1200, 400), # XXX check it
"GW2A-18": (500, 625, 3.90625, 1250, 500),
"GW2A-18C": (500, 625, 3.90625, 1250, 500),
}
# input params are calculated as described in GOWIN doc (UG286-1.7E_Gowin Clock User Guide)
# fref = fclkin / idiv
Expand Down
81 changes: 42 additions & 39 deletions apycula/gowin_pll.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
# pll tool to find best match for the target frequency
# calculations based on: https://github.com/juj/gowin_fpga_code_generators/blob/main/pll_calculator.html
# limits from: http://cdn.gowinsemi.com.cn/DS117E.pdf, http://cdn.gowinsemi.com.cn/DS861E.pdf
#
# limits from:
# - http://cdn.gowinsemi.com.cn/DS117E.pdf,
# - http://cdn.gowinsemi.com.cn/DS861E.pdf,
# - https://cdn.gowinsemi.com.cn/DS226E.pdf

import sys
import re
import argparse
import re
import sys


def main():
Expand All @@ -16,7 +18,9 @@ def main():
parser.add_argument(
"-o", "--output-freq-mhz", help="PLL Output Frequency", type=float, default=108
)
parser.add_argument("-d", "--device", help="Device", type=str, default="GW1NR-9 C6/I5")
parser.add_argument(
"-d", "--device", help="Device", type=str, default="GW1NR-9 C6/I5"
)
parser.add_argument(
"-f",
"--filename",
Expand Down Expand Up @@ -218,11 +222,11 @@ def main():
"comment": "untested",
"pll_name": "rPLL",
"pfd_min": 3,
"pfd_max": 400,
"vco_min": 400,
"vco_max": 1000,
"clkout_min": 3.125,
"clkout_max": 500,
"pfd_max": 500,
"vco_min": 500,
"vco_max": 1250,
"clkout_min": 3.90625,
"clkout_max": 625,
},
}

Expand Down Expand Up @@ -273,38 +277,37 @@ def main():
extra_options = ".VREN(1'b1),"

pll_v = f"""/**
* PLL configuration
*
* This Verilog module was generated automatically
* using the gowin-pll tool.
* Use at your own risk.
*
* Target-Device: {device_name}
* Given input frequency: {args.input_freq_mhz:0.3f} MHz
* Requested output frequency: {args.output_freq_mhz:0.3f} MHz
* Achieved output frequency: {setup['CLKOUT']:0.3f} MHz
*/
module {args.module_name}(
input clock_in,
output clock_out,
output locked
);
* PLL configuration
*
* This Verilog module was generated automatically
* using the gowin-pll tool.
* Use at your own risk.
*
* Target-Device: {device_name}
* Given input frequency: {args.input_freq_mhz:0.3f} MHz
* Requested output frequency: {args.output_freq_mhz:0.3f} MHz
* Achieved output frequency: {setup['CLKOUT']:0.3f} MHz
*/
{limits['pll_name']} #(
.FCLKIN("{args.input_freq_mhz}"),
.IDIV_SEL({setup['IDIV_SEL']}), // -> PFD = {setup['PFD']} MHz (range: {limits['pfd_min']}-{limits['pfd_max']} MHz)
.FBDIV_SEL({setup['FBDIV_SEL']}), // -> CLKOUT = {setup['CLKOUT']} MHz (range: {limits['vco_min']}-{limits['clkout_max']} MHz)
.ODIV_SEL({setup['ODIV_SEL']}) // -> VCO = {setup['VCO']} MHz (range: {limits['clkout_max']}-{limits['vco_max']} MHz)
) pll (.CLKOUTP(), .CLKOUTD(), .CLKOUTD3(), .RESET(1'b0), .RESET_P(1'b0), .CLKFB(1'b0), .FBDSEL(6'b0), .IDSEL(6'b0), .ODSEL(6'b0), .PSDA(4'b0), .DUTYDA(4'b0), .FDLY(4'b0), {extra_options}
.CLKIN(clock_in), // {args.input_freq_mhz} MHz
.CLKOUT(clock_out), // {setup['CLKOUT']} MHz
.LOCK(locked)
);
module {args.module_name}(
input clock_in,
output clock_out,
output locked
);
endmodule
{limits['pll_name']} #(
.FCLKIN("{args.input_freq_mhz}"),
.IDIV_SEL({setup['IDIV_SEL']}), // -> PFD = {setup['PFD']} MHz (range: {limits['pfd_min']}-{limits['pfd_max']} MHz)
.FBDIV_SEL({setup['FBDIV_SEL']}), // -> CLKOUT = {setup['CLKOUT']} MHz (range: {limits['clkout_min']}-{limits['clkout_max']} MHz)
.ODIV_SEL({setup['ODIV_SEL']}) // -> VCO = {setup['VCO']} MHz (range: {limits['vco_min']}-{limits['vco_max']} MHz)
) pll (.CLKOUTP(), .CLKOUTD(), .CLKOUTD3(), .RESET(1'b0), .RESET_P(1'b0), .CLKFB(1'b0), .FBDSEL(6'b0), .IDSEL(6'b0), .ODSEL(6'b0), .PSDA(4'b0), .DUTYDA(4'b0), .FDLY(4'b0), {extra_options}
.CLKIN(clock_in), // {args.input_freq_mhz} MHz
.CLKOUT(clock_out), // {setup['CLKOUT']} MHz
.LOCK(locked)
);
"""
endmodule
"""
if args.filename:
open(args.filename, "w").write(pll_v)
else:
Expand Down
20 changes: 10 additions & 10 deletions examples/himbaechel/Makefile.himbaechel
Original file line number Diff line number Diff line change
Expand Up @@ -233,19 +233,19 @@ clean:
$(NEXTPNR) --json $< --write $@ --device GW2AR-LV18QN88C8/I7 --vopt family=GW2A-18C --vopt cst=tangnano20k.cst

%-tangnano20k-synth.json: %.v
$(YOSYS) -D LEDS_NR=6 -D OSC_TYPE_OSC -D INV_BTN=1 -D CPU_FREQ=27 -D BAUD_RATE=115200 -D NUM_HCLK=5 -p "read_verilog $^; synth_gowin -json $@"
$(YOSYS) -D LEDS_NR=6 -D OSC_TYPE_OSC -D INV_BTN=1 -D CPU_FREQ=27 -D BAUD_RATE=115200 -D NUM_HCLK=5 -p "read_verilog $^; synth_gowin -json $@ -family gw2a"

pll-nanolcd-tangnano20k-synth.json: pll/GW2A-18-dyn.vh pll-nanolcd/TOP.v pll-nanolcd/VGAMod.v
$(YOSYS) -D INV_BTN=1 -p "read_verilog $^; synth_gowin -json $@"
$(YOSYS) -D INV_BTN=1 -p "read_verilog $^; synth_gowin -json $@ -family gw2a"

bsram-%-tangnano20k-synth.json: pll/GW2A-18-dyn.vh %-image-rom.v %-video-ram.v %.v
$(YOSYS) -D INV_BTN=1 -p "read_verilog $^; synth_gowin -json $@"
$(YOSYS) -D INV_BTN=1 -p "read_verilog $^; synth_gowin -json $@ -family gw2a"

attosoc-tangnano20k-synth.json: attosoc/attosoc.v attosoc/picorv32.v
$(YOSYS) -D INV_BTN=1 -p "read_verilog $^; synth_gowin -json $@"
$(YOSYS) -D INV_BTN=1 -p "read_verilog $^; synth_gowin -json $@ -family gw2a"

dvi-example-tangnano20k-synth.json: DVI/dvi-example.v DVI/pll480.v DVI/tmds-channel.v
$(YOSYS) -D INV_BTN=1 -D IS_ELVDS=0 -p "read_verilog -sv $^; synth_gowin -json $@"
$(YOSYS) -D INV_BTN=1 -D IS_ELVDS=0 -p "read_verilog -sv $^; synth_gowin -json $@ -family gw2a"

# ============================================================
# TangPrimer20k
Expand All @@ -256,19 +256,19 @@ dvi-example-tangnano20k-synth.json: DVI/dvi-example.v DVI/pll480.v DVI/tmds-chan
$(NEXTPNR) --json $< --write $@ --device GW2A-LV18PG256C8/I7 --vopt family=GW2A-18 --vopt cst=primer20k.cst

%-primer20k-synth.json: %.v
$(YOSYS) -D LEDS_NR=6 -D OSC_TYPE_OSC -D INV_BTN=0 -D CPU_FREQ=27 -D BAUD_RATE=115200 -D NUM_HCLK=5 -p "read_verilog $^; synth_gowin -json $@"
$(YOSYS) -D LEDS_NR=6 -D OSC_TYPE_OSC -D INV_BTN=0 -D CPU_FREQ=27 -D BAUD_RATE=115200 -D NUM_HCLK=5 -p "read_verilog $^; synth_gowin -json $@ -family gw2a"

pll-nanolcd-primer20k-synth.json: pll/GW2A-18-dyn.vh pll-nanolcd/TOP.v pll-nanolcd/VGAMod.v
$(YOSYS) -D INV_BTN=0 -p "read_verilog $^; synth_gowin -json $@"
$(YOSYS) -D INV_BTN=0 -p "read_verilog $^; synth_gowin -json $@ -family gw2a"

bsram-%-primer20k-synth.json: pll/GW2A-18-dyn.vh %-image-rom.v %-video-ram.v %.v
$(YOSYS) -D INV_BTN=0 -p "read_verilog $^; synth_gowin -json $@"
$(YOSYS) -D INV_BTN=0 -p "read_verilog $^; synth_gowin -json $@ -family gw2a"

attosoc-%-synth.json: attosoc/attosoc.v attosoc/picorv32.v
$(YOSYS) -D INV_BTN=0 -p "read_verilog $^; synth_gowin -json $@"
$(YOSYS) -D INV_BTN=0 -p "read_verilog $^; synth_gowin -json $@ -family gw2a"

dvi-example-primer20k-synth.json: DVI/dvi-example.v DVI/pll480.v DVI/tmds-channel.v
$(YOSYS) -D INV_BTN=0 -D IS_ELVDS=0 -p "read_verilog -sv $^; synth_gowin -json $@"
$(YOSYS) -D INV_BTN=0 -D IS_ELVDS=0 -p "read_verilog -sv $^; synth_gowin -json $@ -family gw2a"

# ============================================================
# Tangnano (GW1N-1)
Expand Down
10 changes: 4 additions & 6 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,10 @@

<img src="apicula.svg" width="250" />

Documentation and open source tools for the Gowin FPGA bitstream format.
Open source tools and [Documentation](https://github.com/YosysHQ/apicula/wiki) for the Gowin FPGA bitstream format.

Project Apicula uses a combination of fuzzing and parsing of the vendor data files to provide Python tools for generating bitstreams.

This project is supported by our generous sponsors. Have a look at our [contributors](https://github.com/YosysHQ/apicula/graphs/contributors) and sponsor them with via the various platforms linked on our [github](https://github.com/YosysHQ/apicula).

## Getting Started

Install the latest git [yosys](https://github.com/yosyshq/yosys#setup), [nextpnr-himbaechel](https://github.com/YosysHQ/nextpnr#gowin), [openFPGALoader](https://github.com/trabucayre/openFPGALoader), and Python 3.8 or higher. [Yowasp](http://yowasp.org/) versions of Yosys and Nextpnr are also supported.
Expand All @@ -18,13 +16,13 @@ Currently supported boards are
* Sipeed Tang Nano 1K: GW1NZ-LV1QN48C6/I5
* Sipeed Tang Nano 4K: GW1NSR-LV4CQN48PC7/I6
* Sipeed Tang Nano 9K: GW1NR-LV9QN88PC6/I5 [^1]
* Sipeed Tang Nano 20K: GW2AR-LV18QN88C8/I7
* Sipeed Tang Primer 20K: GW2A-LV18PG256C8/I7
* Sipeed Tang Nano 20K: GW2AR-LV18QN88C8/I7 [^1]
* Sipeed Tang Primer 20K: GW2A-LV18PG256C8/I7 [^1]
* Seeed RUNBER: GW1N-UV4LQ144C6/I5
* @Disasm honeycomb: GW1NS-UX2CQN48C5/I4
* szfpga: GW1NR-LV9LQ144PC6/I5

[^1]: `C` devices require passing the `--family` flag as well as `--device` to Nextpnr, and stating the family in place of device when passing `-d` to `gowin_pack` because the C isn't part of the device ID but only present in the date code. Check `examples/Makefile` for the correct command.
[^1]: `C` devices require passing the `--family` flag as well as `--device` to Nextpnr, and stating the family in place of device when passing `-d` to `gowin_pack` because the C isn't part of the device ID but only present in the date code. Check `examples/himbaechel/Makefile` for the correct command.

Install the tools with pip.

Expand Down

0 comments on commit 10f243e

Please sign in to comment.