Skip to content

Commit

Permalink
Merge pull request #277 from yrabbit/userflash-0
Browse files Browse the repository at this point in the history
Implement the UserFlash primitives.
  • Loading branch information
yrabbit authored Sep 11, 2024
2 parents 741818e + b758d37 commit b2a84bd
Show file tree
Hide file tree
Showing 33 changed files with 1,614 additions and 26 deletions.
117 changes: 117 additions & 0 deletions apycula/chipdb.py
Original file line number Diff line number Diff line change
Expand Up @@ -1832,6 +1832,122 @@ def fse_create_bandgap(dev, device):
dev.extra_func.setdefault((10, 18), {}).update(
{'bandgap': {'wire': 'C1'}})

def fse_create_userflash(dev, device, dat):
# dat[‘UfbIns’] and dat[‘UfbOuts’].
# The outputs are exactly 32 by the number of bits and they are always
# present, their positions correspond to bit indices - checked by
# selectively connecting the outputs to LEDs.
# The inputs depend on the Flash type - different types have different
# inputs, e.g. XY or RCP addressing is used etc. During experimental
# generation of images with input to button connection some inputs
# description could not be found in the table, such inputs will be
# specified here rigidly.
# Flash types (see UG295-1.4.3E_Gowin User Flash User Guide.pdf)
_flash_type = {'GW1N-1': 'FLASH96K',
'GW1NZ-1': 'FLASH64KZ',
'GW1N-4': 'FLASH256K', 'GW1NS-4': 'FLASH256K',
'GW1N-9': 'FLASH608K', 'GW1N-9C': 'FLASH608K'}
if device not in _flash_type:
return
flash_type = _flash_type[device]
ins_type = 'XY'
if flash_type == 'FLASH96K':
ins_type = 'RC'

# userflash has neither its own cell type nor fuses, so it is logical to make it extra func.
# use X0Y0 cell for convenience - a significant part of UserFlash pins are
# located there, it saves from creating unnecessary nodes
row, col = (0, 0)
dev.extra_func.setdefault((row, col), {}).update(
{'userflash': {'type': flash_type}})
extra_func = dev.extra_func[(row, col)]['userflash']


def make_port(r, c, wire, port, wire_type, pins):
if r == -1 or c == -1:
return
bel = Bel()
wire = wirenames[wire]
bel.portmap[port] = wire
if r - 1 != row or c - 1 != col :
create_port_wire(dev, row, col, r - row - 1, c - col - 1, bel, 'USERFLASH', port, wire, wire_type)
pins[port] = bel.portmap[port]

# outputs
outs = extra_func.setdefault('outs', {})
for i, desc in enumerate(dat.compat_dict['UfbOuts']):
port = f'DOUT{i}'
r, c, wire = desc
make_port(r, c, wire, port, 'FLASH_OUT', outs)

# inputs
ins = extra_func.setdefault('ins', {})
# DIN first - we know there they are
for i, desc in enumerate(dat.compat_dict['UfbIns'][58:]):
port = f'DIN{i}'
r, c, wire = desc
make_port(r, c, wire, port, 'FLASH_IN', ins)

if ins_type == 'RC':
for i, desc in enumerate(dat.compat_dict['UfbIns'][21:27]):
port = f'RA{i}'
r, c, wire = desc
make_port(r, c, wire, port, 'FLASH_IN', ins)
for i, desc in enumerate(dat.compat_dict['UfbIns'][27:33]):
port = f'CA{i}'
r, c, wire = desc
make_port(r, c, wire, port, 'FLASH_IN', ins)
for i, desc in enumerate(dat.compat_dict['UfbIns'][33:39]):
port = f'PA{i}'
r, c, wire = desc
make_port(r, c, wire, port, 'FLASH_IN', ins)
for i, desc in enumerate(dat.compat_dict['UfbIns'][39:43]):
port = f'MODE{i}'
r, c, wire = desc
make_port(r, c, wire, port, 'FLASH_IN', ins)
for i, desc in enumerate(dat.compat_dict['UfbIns'][43:45]):
port = f'SEQ{i}'
r, c, wire = desc
make_port(r, c, wire, port, 'FLASH_IN', ins)
for i, desc in enumerate(dat.compat_dict['UfbIns'][45:50]):
port = ['ACLK', 'PW', 'RESET', 'PE', 'OE'][i]
r, c, wire = desc
make_port(r, c, wire, port, 'FLASH_IN', ins)
for i, desc in enumerate(dat.compat_dict['UfbIns'][50:52]):
port = f'RMODE{i}'
r, c, wire = desc
make_port(r, c, wire, port, 'FLASH_IN', ins)
for i, desc in enumerate(dat.compat_dict['UfbIns'][52:54]):
port = f'WMODE{i}'
r, c, wire = desc
make_port(r, c, wire, port, 'FLASH_IN', ins)
for i, desc in enumerate(dat.compat_dict['UfbIns'][54:56]):
port = f'RBYTESEL{i}'
r, c, wire = desc
make_port(r, c, wire, port, 'FLASH_IN', ins)
for i, desc in enumerate(dat.compat_dict['UfbIns'][56:58]):
port = f'WBYTESEL{i}'
r, c, wire = desc
make_port(r, c, wire, port, 'FLASH_IN', ins)
else:
for i, desc in enumerate(dat.compat_dict['UfbIns'][:6]):
port = ['XE', 'YE', 'SE', 'PROG', 'ERASE', 'NVSTR'][i]
r, c, wire = desc
make_port(r, c, wire, port, 'FLASH_IN', ins)
for i, desc in enumerate(dat.compat_dict['UfbIns'][6:15]):
port = f'XADR{i}'
r, c, wire = desc
make_port(r, c, wire, port, 'FLASH_IN', ins)
for i, desc in enumerate(dat.compat_dict['UfbIns'][15:21]):
port = f'YADR{i}'
r, c, wire = desc
make_port(r, c, wire, port, 'FLASH_IN', ins)

# XXX INUSEN - is observed to be connected to the VSS when USERFLASH is used
if flash_type != 'FLASH64KZ':
ins['INUSEN'] = 'C0'


def fse_bram(fse, aux = False):
bels = {}
name = 'BSRAM'
Expand Down Expand Up @@ -1970,6 +2086,7 @@ def from_fse(device, fse, dat: Datfile):
fse_create_osc(dev, device, fse)
fse_create_gsr(dev, device)
fse_create_bandgap(dev, device)
fse_create_userflash(dev, device, dat)
fse_create_logic2clk(dev, device, dat)
disable_plls(dev, device)
sync_extra_func(dev)
Expand Down
16 changes: 9 additions & 7 deletions apycula/gowin_pack.py
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ def get_bits(init_data):
def get_bels(data):
later = []
if is_himbaechel:
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*)")
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*)")
else:
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*)")

Expand Down Expand Up @@ -1996,13 +1996,13 @@ def bin_str_to_dec(str_val):
dec_num = int(bin_str[0], 2)
return str(dec_num)
return None



_hclk_default_params ={"GSREN": "false", "DIV_MODE":"2"}
def set_hclk_attrs(db, params, num, typ, cell_name):
name_pattern = r'^_HCLK([0,1])_SECT([0,1])$'
params = dict(params or _hclk_default_params)
params = dict(params or _hclk_default_params)
attrs = {}
pattern_match = re.findall(name_pattern, num)
if (not pattern_match):
Expand All @@ -2013,21 +2013,21 @@ def set_hclk_attrs(db, params, num, typ, cell_name):
if device in ["GW1N-1S","GW1N-2","GW1NR-2","GW1NS-4","GW1NS-4C","GW1NSR-4",\
"GW1NSR-4C","GW1NSER-4C","GW1N-9","GW1NR-9", "GW1N-9C","GW1NR-9C","GW1N-1P5"]:
valid_div_modes.append("8")

if (params["DIV_MODE"]) not in valid_div_modes:
bin_match = bin_str_to_dec(params["DIV_MODE"])
if bin_match is None or bin_match not in valid_div_modes:
raise Exception(f"Invalid DIV_MODE {bin_match or params['DIV_MODE']} for CLKDIV {cell_name} on device {device}")
params["DIV_MODE"] = str(bin_match[0])


if (typ == "CLKDIV2"):
attrs[f"BK{section_idx}MUX{hclk_idx}_OUTSEL"] = "DIV2"
elif (typ == "CLKDIV"):
attrs[f"HCLKDIV{hclk_idx}_DIV"] = params["DIV_MODE"]
attrs[f"HCLKDIV{hclk_idx}_DIV"] = params["DIV_MODE"]
if (section_idx == '1'):
attrs[f"HCLKDCS{hclk_idx}_SEL"] = f"HCLKBK{section_idx}{hclk_idx}"

fin_attrs = set()
for attr, val in attrs.items():
if isinstance(val, str):
Expand Down Expand Up @@ -2313,6 +2313,8 @@ def place(db, tilemap, bels, cst, args):
pass
elif typ == "BANDGAP":
pass
elif typ.startswith("FLASH"):
pass
elif typ.startswith('MUX2_'):
pass
elif typ == "BUFS":
Expand Down
7 changes: 4 additions & 3 deletions examples/himbaechel/Makefile.himbaechel
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ all: \
bsram-pROM-tangnano1k.fs bsram-SDPB-tangnano1k.fs bsram-DPB16-tangnano1k.fs \
bsram-SP-tangnano1k.fs bsram-pROMX9-tangnano1k.fs bsram-SDPX9B-tangnano1k.fs \
bsram-SPX9-tangnano1k.fs bsram-DPX9B18-tangnano1k.fs \
dqce-tangnano1k.fs dcs-tangnano1k.fs \
dqce-tangnano1k.fs dcs-tangnano1k.fs userflash-tangnano1k.fs \
\
blinky-tangnano4k.fs shift-tangnano4k.fs blinky-tbuf-tangnano4k.fs blinky-oddr-tangnano4k.fs \
blinky-osc-tangnano4k.fs tlvds-tangnano4k.fs elvds-tangnano4k.fs oddr-tlvds-tangnano4k.fs \
Expand Down Expand Up @@ -78,7 +78,7 @@ all: \
dsp-mult36x36-tangnano9k.fs dsp-padd9-tangnano9k.fs dsp-padd18-tangnano9k.fs \
dsp-mult9x9-tangnano9k.fs dsp-alu54d-tangnano9k.fs dsp-multalu18x18-tangnano9k.fs \
dsp-multalu36x18-tangnano9k.fs dsp-multaddalu18x18-tangnano9k.fs \
dqce-tangnano9k.fs dcs-tangnano9k.fs \
dqce-tangnano9k.fs dcs-tangnano9k.fs femto-riscv-userflash-tangnano9k.fs \
\
blinky-szfpga.fs shift-szfpga.fs blinky-tbuf-szfpga.fs blinky-oddr-szfpga.fs \
blinky-osc-szfpga.fs tlvds-szfpga.fs elvds-szfpga.fs oddr-tlvds-szfpga.fs \
Expand Down Expand Up @@ -314,6 +314,7 @@ bsram-%-tangnano1k-synth.json: pll/GW1NZ-1-dyn.vh %-image-rom.v %-video-ram.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 $@"


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

%-tangnano9k-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 -D HAS_FLASH608K -p "read_verilog $^; synth_gowin -json $@"

pll-nanolcd-tangnano9k-synth.json: pll/GW1N-9C-dyn.vh pll-nanolcd/TOP.v pll-nanolcd/VGAMod.v
$(YOSYS) -D INV_BTN=0 -p "read_verilog $^; synth_gowin -json $@"
Expand Down
2 changes: 1 addition & 1 deletion examples/himbaechel/dsp-alu54d.v
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,6 @@ ALU54D alu2(
defparam alu2.ALU_RESET_MODE="SYNC";
endmodule

`define FIRMWARE "riscv-dsp-firmware/alu54d.hex"
`define FIRMWARE "riscv-firmware/alu54d.hex"
`include "dsp-riscv.v"

2 changes: 1 addition & 1 deletion examples/himbaechel/dsp-mult18x18.v
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,6 @@ defparam mult_4.SOA_REG=1'b0;
defparam mult_4.MULT_RESET_MODE="SYNC";
endmodule

`define FIRMWARE "riscv-dsp-firmware/mult18x18.hex"
`define FIRMWARE "riscv-firmware/mult18x18.hex"
`include "dsp-riscv.v"

2 changes: 1 addition & 1 deletion examples/himbaechel/dsp-mult36x36.v
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,6 @@ module idsp(input wire clk, input wire reset,
defparam mu_1.MULT_RESET_MODE="SYNC";
endmodule

`define FIRMWARE "riscv-dsp-firmware/mult36x36.hex"
`define FIRMWARE "riscv-firmware/mult36x36.hex"
`include "dsp-riscv.v"

2 changes: 1 addition & 1 deletion examples/himbaechel/dsp-mult9x9.v
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,6 @@ defparam mult_4.SOA_REG=1'b0;
defparam mult_4.MULT_RESET_MODE="SYNC";
endmodule

`define FIRMWARE "riscv-dsp-firmware/mult9x9.hex"
`define FIRMWARE "riscv-firmware/mult9x9.hex"
`include "dsp-riscv.v"

2 changes: 1 addition & 1 deletion examples/himbaechel/dsp-multaddalu18x18.v
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,6 @@ module idsp(input wire clk, input wire reset,
defparam multaddalu_3.MULTADDALU18X18_MODE=2;
endmodule

`define FIRMWARE "riscv-dsp-firmware/multaddalu18x18.hex"
`define FIRMWARE "riscv-firmware/multaddalu18x18.hex"
`include "dsp-riscv.v"

2 changes: 1 addition & 1 deletion examples/himbaechel/dsp-multalu18x18.v
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,6 @@ module idsp(input wire clk, input wire reset,
defparam multalu_4.MULTALU18X18_MODE=2;
endmodule

`define FIRMWARE "riscv-dsp-firmware/multalu18x18.hex"
`define FIRMWARE "riscv-firmware/multalu18x18.hex"
`include "dsp-riscv.v"

2 changes: 1 addition & 1 deletion examples/himbaechel/dsp-multalu36x18.v
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,6 @@ module idsp(input wire clk, input wire reset,
defparam multalu_4.MULTALU36X18_MODE=0;
endmodule

`define FIRMWARE "riscv-dsp-firmware/multalu36x18.hex"
`define FIRMWARE "riscv-firmware/multalu36x18.hex"
`include "dsp-riscv.v"

2 changes: 1 addition & 1 deletion examples/himbaechel/dsp-padd18.v
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,6 @@ module idsp(input wire clk, input wire reset,
defparam padd18_4.PADD_RESET_MODE="SYNC";
endmodule

`define FIRMWARE "riscv-dsp-firmware/padd18.hex"
`define FIRMWARE "riscv-firmware/padd18.hex"
`include "dsp-riscv.v"

2 changes: 1 addition & 1 deletion examples/himbaechel/dsp-padd9.v
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,6 @@ module idsp(input wire clk, input wire reset,
defparam padd_4.PADD_RESET_MODE="SYNC";
endmodule

`define FIRMWARE "riscv-dsp-firmware/padd9.hex"
`define FIRMWARE "riscv-firmware/padd9.hex"
`include "dsp-riscv.v"

Loading

0 comments on commit b2a84bd

Please sign in to comment.