Skip to content

Commit b2a84bd

Browse files
authored
Merge pull request #277 from yrabbit/userflash-0
Implement the UserFlash primitives.
2 parents 741818e + b758d37 commit b2a84bd

33 files changed

+1614
-26
lines changed

apycula/chipdb.py

+117
Original file line numberDiff line numberDiff line change
@@ -1832,6 +1832,122 @@ def fse_create_bandgap(dev, device):
18321832
dev.extra_func.setdefault((10, 18), {}).update(
18331833
{'bandgap': {'wire': 'C1'}})
18341834

1835+
def fse_create_userflash(dev, device, dat):
1836+
# dat[‘UfbIns’] and dat[‘UfbOuts’].
1837+
# The outputs are exactly 32 by the number of bits and they are always
1838+
# present, their positions correspond to bit indices - checked by
1839+
# selectively connecting the outputs to LEDs.
1840+
# The inputs depend on the Flash type - different types have different
1841+
# inputs, e.g. XY or RCP addressing is used etc. During experimental
1842+
# generation of images with input to button connection some inputs
1843+
# description could not be found in the table, such inputs will be
1844+
# specified here rigidly.
1845+
# Flash types (see UG295-1.4.3E_Gowin User Flash User Guide.pdf)
1846+
_flash_type = {'GW1N-1': 'FLASH96K',
1847+
'GW1NZ-1': 'FLASH64KZ',
1848+
'GW1N-4': 'FLASH256K', 'GW1NS-4': 'FLASH256K',
1849+
'GW1N-9': 'FLASH608K', 'GW1N-9C': 'FLASH608K'}
1850+
if device not in _flash_type:
1851+
return
1852+
flash_type = _flash_type[device]
1853+
ins_type = 'XY'
1854+
if flash_type == 'FLASH96K':
1855+
ins_type = 'RC'
1856+
1857+
# userflash has neither its own cell type nor fuses, so it is logical to make it extra func.
1858+
# use X0Y0 cell for convenience - a significant part of UserFlash pins are
1859+
# located there, it saves from creating unnecessary nodes
1860+
row, col = (0, 0)
1861+
dev.extra_func.setdefault((row, col), {}).update(
1862+
{'userflash': {'type': flash_type}})
1863+
extra_func = dev.extra_func[(row, col)]['userflash']
1864+
1865+
1866+
def make_port(r, c, wire, port, wire_type, pins):
1867+
if r == -1 or c == -1:
1868+
return
1869+
bel = Bel()
1870+
wire = wirenames[wire]
1871+
bel.portmap[port] = wire
1872+
if r - 1 != row or c - 1 != col :
1873+
create_port_wire(dev, row, col, r - row - 1, c - col - 1, bel, 'USERFLASH', port, wire, wire_type)
1874+
pins[port] = bel.portmap[port]
1875+
1876+
# outputs
1877+
outs = extra_func.setdefault('outs', {})
1878+
for i, desc in enumerate(dat.compat_dict['UfbOuts']):
1879+
port = f'DOUT{i}'
1880+
r, c, wire = desc
1881+
make_port(r, c, wire, port, 'FLASH_OUT', outs)
1882+
1883+
# inputs
1884+
ins = extra_func.setdefault('ins', {})
1885+
# DIN first - we know there they are
1886+
for i, desc in enumerate(dat.compat_dict['UfbIns'][58:]):
1887+
port = f'DIN{i}'
1888+
r, c, wire = desc
1889+
make_port(r, c, wire, port, 'FLASH_IN', ins)
1890+
1891+
if ins_type == 'RC':
1892+
for i, desc in enumerate(dat.compat_dict['UfbIns'][21:27]):
1893+
port = f'RA{i}'
1894+
r, c, wire = desc
1895+
make_port(r, c, wire, port, 'FLASH_IN', ins)
1896+
for i, desc in enumerate(dat.compat_dict['UfbIns'][27:33]):
1897+
port = f'CA{i}'
1898+
r, c, wire = desc
1899+
make_port(r, c, wire, port, 'FLASH_IN', ins)
1900+
for i, desc in enumerate(dat.compat_dict['UfbIns'][33:39]):
1901+
port = f'PA{i}'
1902+
r, c, wire = desc
1903+
make_port(r, c, wire, port, 'FLASH_IN', ins)
1904+
for i, desc in enumerate(dat.compat_dict['UfbIns'][39:43]):
1905+
port = f'MODE{i}'
1906+
r, c, wire = desc
1907+
make_port(r, c, wire, port, 'FLASH_IN', ins)
1908+
for i, desc in enumerate(dat.compat_dict['UfbIns'][43:45]):
1909+
port = f'SEQ{i}'
1910+
r, c, wire = desc
1911+
make_port(r, c, wire, port, 'FLASH_IN', ins)
1912+
for i, desc in enumerate(dat.compat_dict['UfbIns'][45:50]):
1913+
port = ['ACLK', 'PW', 'RESET', 'PE', 'OE'][i]
1914+
r, c, wire = desc
1915+
make_port(r, c, wire, port, 'FLASH_IN', ins)
1916+
for i, desc in enumerate(dat.compat_dict['UfbIns'][50:52]):
1917+
port = f'RMODE{i}'
1918+
r, c, wire = desc
1919+
make_port(r, c, wire, port, 'FLASH_IN', ins)
1920+
for i, desc in enumerate(dat.compat_dict['UfbIns'][52:54]):
1921+
port = f'WMODE{i}'
1922+
r, c, wire = desc
1923+
make_port(r, c, wire, port, 'FLASH_IN', ins)
1924+
for i, desc in enumerate(dat.compat_dict['UfbIns'][54:56]):
1925+
port = f'RBYTESEL{i}'
1926+
r, c, wire = desc
1927+
make_port(r, c, wire, port, 'FLASH_IN', ins)
1928+
for i, desc in enumerate(dat.compat_dict['UfbIns'][56:58]):
1929+
port = f'WBYTESEL{i}'
1930+
r, c, wire = desc
1931+
make_port(r, c, wire, port, 'FLASH_IN', ins)
1932+
else:
1933+
for i, desc in enumerate(dat.compat_dict['UfbIns'][:6]):
1934+
port = ['XE', 'YE', 'SE', 'PROG', 'ERASE', 'NVSTR'][i]
1935+
r, c, wire = desc
1936+
make_port(r, c, wire, port, 'FLASH_IN', ins)
1937+
for i, desc in enumerate(dat.compat_dict['UfbIns'][6:15]):
1938+
port = f'XADR{i}'
1939+
r, c, wire = desc
1940+
make_port(r, c, wire, port, 'FLASH_IN', ins)
1941+
for i, desc in enumerate(dat.compat_dict['UfbIns'][15:21]):
1942+
port = f'YADR{i}'
1943+
r, c, wire = desc
1944+
make_port(r, c, wire, port, 'FLASH_IN', ins)
1945+
1946+
# XXX INUSEN - is observed to be connected to the VSS when USERFLASH is used
1947+
if flash_type != 'FLASH64KZ':
1948+
ins['INUSEN'] = 'C0'
1949+
1950+
18351951
def fse_bram(fse, aux = False):
18361952
bels = {}
18371953
name = 'BSRAM'
@@ -1970,6 +2086,7 @@ def from_fse(device, fse, dat: Datfile):
19702086
fse_create_osc(dev, device, fse)
19712087
fse_create_gsr(dev, device)
19722088
fse_create_bandgap(dev, device)
2089+
fse_create_userflash(dev, device, dat)
19732090
fse_create_logic2clk(dev, device, dat)
19742091
disable_plls(dev, device)
19752092
sync_extra_func(dev)

apycula/gowin_pack.py

+9-7
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)(\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)(\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

@@ -1996,13 +1996,13 @@ def bin_str_to_dec(str_val):
19961996
dec_num = int(bin_str[0], 2)
19971997
return str(dec_num)
19981998
return None
1999-
1999+
20002000

20012001

20022002
_hclk_default_params ={"GSREN": "false", "DIV_MODE":"2"}
20032003
def set_hclk_attrs(db, params, num, typ, cell_name):
20042004
name_pattern = r'^_HCLK([0,1])_SECT([0,1])$'
2005-
params = dict(params or _hclk_default_params)
2005+
params = dict(params or _hclk_default_params)
20062006
attrs = {}
20072007
pattern_match = re.findall(name_pattern, num)
20082008
if (not pattern_match):
@@ -2013,21 +2013,21 @@ def set_hclk_attrs(db, params, num, typ, cell_name):
20132013
if device in ["GW1N-1S","GW1N-2","GW1NR-2","GW1NS-4","GW1NS-4C","GW1NSR-4",\
20142014
"GW1NSR-4C","GW1NSER-4C","GW1N-9","GW1NR-9", "GW1N-9C","GW1NR-9C","GW1N-1P5"]:
20152015
valid_div_modes.append("8")
2016-
2016+
20172017
if (params["DIV_MODE"]) not in valid_div_modes:
20182018
bin_match = bin_str_to_dec(params["DIV_MODE"])
20192019
if bin_match is None or bin_match not in valid_div_modes:
20202020
raise Exception(f"Invalid DIV_MODE {bin_match or params['DIV_MODE']} for CLKDIV {cell_name} on device {device}")
20212021
params["DIV_MODE"] = str(bin_match[0])
20222022

2023-
2023+
20242024
if (typ == "CLKDIV2"):
20252025
attrs[f"BK{section_idx}MUX{hclk_idx}_OUTSEL"] = "DIV2"
20262026
elif (typ == "CLKDIV"):
2027-
attrs[f"HCLKDIV{hclk_idx}_DIV"] = params["DIV_MODE"]
2027+
attrs[f"HCLKDIV{hclk_idx}_DIV"] = params["DIV_MODE"]
20282028
if (section_idx == '1'):
20292029
attrs[f"HCLKDCS{hclk_idx}_SEL"] = f"HCLKBK{section_idx}{hclk_idx}"
2030-
2030+
20312031
fin_attrs = set()
20322032
for attr, val in attrs.items():
20332033
if isinstance(val, str):
@@ -2313,6 +2313,8 @@ def place(db, tilemap, bels, cst, args):
23132313
pass
23142314
elif typ == "BANDGAP":
23152315
pass
2316+
elif typ.startswith("FLASH"):
2317+
pass
23162318
elif typ.startswith('MUX2_'):
23172319
pass
23182320
elif typ == "BUFS":

examples/himbaechel/Makefile.himbaechel

+4-3
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ all: \
4949
bsram-pROM-tangnano1k.fs bsram-SDPB-tangnano1k.fs bsram-DPB16-tangnano1k.fs \
5050
bsram-SP-tangnano1k.fs bsram-pROMX9-tangnano1k.fs bsram-SDPX9B-tangnano1k.fs \
5151
bsram-SPX9-tangnano1k.fs bsram-DPX9B18-tangnano1k.fs \
52-
dqce-tangnano1k.fs dcs-tangnano1k.fs \
52+
dqce-tangnano1k.fs dcs-tangnano1k.fs userflash-tangnano1k.fs \
5353
\
5454
blinky-tangnano4k.fs shift-tangnano4k.fs blinky-tbuf-tangnano4k.fs blinky-oddr-tangnano4k.fs \
5555
blinky-osc-tangnano4k.fs tlvds-tangnano4k.fs elvds-tangnano4k.fs oddr-tlvds-tangnano4k.fs \
@@ -78,7 +78,7 @@ all: \
7878
dsp-mult36x36-tangnano9k.fs dsp-padd9-tangnano9k.fs dsp-padd18-tangnano9k.fs \
7979
dsp-mult9x9-tangnano9k.fs dsp-alu54d-tangnano9k.fs dsp-multalu18x18-tangnano9k.fs \
8080
dsp-multalu36x18-tangnano9k.fs dsp-multaddalu18x18-tangnano9k.fs \
81-
dqce-tangnano9k.fs dcs-tangnano9k.fs \
81+
dqce-tangnano9k.fs dcs-tangnano9k.fs femto-riscv-userflash-tangnano9k.fs \
8282
\
8383
blinky-szfpga.fs shift-szfpga.fs blinky-tbuf-szfpga.fs blinky-oddr-szfpga.fs \
8484
blinky-osc-szfpga.fs tlvds-szfpga.fs elvds-szfpga.fs oddr-tlvds-szfpga.fs \
@@ -314,6 +314,7 @@ bsram-%-tangnano1k-synth.json: pll/GW1NZ-1-dyn.vh %-image-rom.v %-video-ram.v %.
314314
%-pll-tangnano4k-synth.json: pll/GW1NS-4-dyn.vh %-pll-vr.v
315315
$(YOSYS) -D INV_BTN=0 -D LEDS_NR=6 -p "read_verilog $^; synth_gowin -json $@"
316316

317+
317318
# ============================================================
318319
# Tangnano9k (GW1N-9C)
319320
%-tangnano9k.fs: %-tangnano9k.json
@@ -323,7 +324,7 @@ bsram-%-tangnano1k-synth.json: pll/GW1NZ-1-dyn.vh %-image-rom.v %-video-ram.v %.
323324
$(NEXTPNR) --json $< --write $@ --device GW1NR-LV9QN88PC6/I5 --vopt family=GW1N-9C --vopt cst=tangnano9k.cst
324325

325326
%-tangnano9k-synth.json: %.v
326-
$(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 $@"
327+
$(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 -D HAS_FLASH608K -p "read_verilog $^; synth_gowin -json $@"
327328

328329
pll-nanolcd-tangnano9k-synth.json: pll/GW1N-9C-dyn.vh pll-nanolcd/TOP.v pll-nanolcd/VGAMod.v
329330
$(YOSYS) -D INV_BTN=0 -p "read_verilog $^; synth_gowin -json $@"

examples/himbaechel/dsp-alu54d.v

+1-1
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,6 @@ ALU54D alu2(
9696
defparam alu2.ALU_RESET_MODE="SYNC";
9797
endmodule
9898

99-
`define FIRMWARE "riscv-dsp-firmware/alu54d.hex"
99+
`define FIRMWARE "riscv-firmware/alu54d.hex"
100100
`include "dsp-riscv.v"
101101

examples/himbaechel/dsp-mult18x18.v

+1-1
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,6 @@ defparam mult_4.SOA_REG=1'b0;
143143
defparam mult_4.MULT_RESET_MODE="SYNC";
144144
endmodule
145145

146-
`define FIRMWARE "riscv-dsp-firmware/mult18x18.hex"
146+
`define FIRMWARE "riscv-firmware/mult18x18.hex"
147147
`include "dsp-riscv.v"
148148

examples/himbaechel/dsp-mult36x36.v

+1-1
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,6 @@ module idsp(input wire clk, input wire reset,
4949
defparam mu_1.MULT_RESET_MODE="SYNC";
5050
endmodule
5151

52-
`define FIRMWARE "riscv-dsp-firmware/mult36x36.hex"
52+
`define FIRMWARE "riscv-firmware/mult36x36.hex"
5353
`include "dsp-riscv.v"
5454

examples/himbaechel/dsp-mult9x9.v

+1-1
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,6 @@ defparam mult_4.SOA_REG=1'b0;
146146
defparam mult_4.MULT_RESET_MODE="SYNC";
147147
endmodule
148148

149-
`define FIRMWARE "riscv-dsp-firmware/mult9x9.hex"
149+
`define FIRMWARE "riscv-firmware/mult9x9.hex"
150150
`include "dsp-riscv.v"
151151

examples/himbaechel/dsp-multaddalu18x18.v

+1-1
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,6 @@ module idsp(input wire clk, input wire reset,
186186
defparam multaddalu_3.MULTADDALU18X18_MODE=2;
187187
endmodule
188188

189-
`define FIRMWARE "riscv-dsp-firmware/multaddalu18x18.hex"
189+
`define FIRMWARE "riscv-firmware/multaddalu18x18.hex"
190190
`include "dsp-riscv.v"
191191

examples/himbaechel/dsp-multalu18x18.v

+1-1
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,6 @@ module idsp(input wire clk, input wire reset,
177177
defparam multalu_4.MULTALU18X18_MODE=2;
178178
endmodule
179179

180-
`define FIRMWARE "riscv-dsp-firmware/multalu18x18.hex"
180+
`define FIRMWARE "riscv-firmware/multalu18x18.hex"
181181
`include "dsp-riscv.v"
182182

examples/himbaechel/dsp-multalu36x18.v

+1-1
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,6 @@ module idsp(input wire clk, input wire reset,
152152
defparam multalu_4.MULTALU36X18_MODE=0;
153153
endmodule
154154

155-
`define FIRMWARE "riscv-dsp-firmware/multalu36x18.hex"
155+
`define FIRMWARE "riscv-firmware/multalu36x18.hex"
156156
`include "dsp-riscv.v"
157157

examples/himbaechel/dsp-padd18.v

+1-1
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,6 @@ module idsp(input wire clk, input wire reset,
119119
defparam padd18_4.PADD_RESET_MODE="SYNC";
120120
endmodule
121121

122-
`define FIRMWARE "riscv-dsp-firmware/padd18.hex"
122+
`define FIRMWARE "riscv-firmware/padd18.hex"
123123
`include "dsp-riscv.v"
124124

examples/himbaechel/dsp-padd9.v

+1-1
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,6 @@ module idsp(input wire clk, input wire reset,
121121
defparam padd_4.PADD_RESET_MODE="SYNC";
122122
endmodule
123123

124-
`define FIRMWARE "riscv-dsp-firmware/padd9.hex"
124+
`define FIRMWARE "riscv-firmware/padd9.hex"
125125
`include "dsp-riscv.v"
126126

0 commit comments

Comments
 (0)