mirror of https://github.com/lnis-uofu/SOFA.git
Merge pull request #44 from LNIS-Projects/xt_dev
Upgraded Caravel Wrapper Generator
This commit is contained in:
commit
b0b5b0b325
|
@ -33,10 +33,10 @@
|
|||
</g>
|
||||
</marker>
|
||||
</defs>
|
||||
<metadata> Produced by OmniGraffle 7.18\n2020-11-21 01:05:14 +0000</metadata>
|
||||
<g id="switch" fill="none" stroke="none" stroke-opacity="1" stroke-dasharray="none" fill-opacity="1">
|
||||
<title>switch</title>
|
||||
<g id="switch_base">
|
||||
<metadata> Produced by OmniGraffle 7.18\n2020-11-29 03:10:55 +0000</metadata>
|
||||
<g id="v1_0" fill="none" stroke="none" stroke-opacity="1" stroke-dasharray="none" fill-opacity="1">
|
||||
<title>v1.0</title>
|
||||
<g id="v1_0_base">
|
||||
<title>base</title>
|
||||
<g id="Graphic_535">
|
||||
<text transform="translate(120.79736 899.1797)" fill="black">
|
||||
|
@ -319,7 +319,7 @@
|
|||
</g>
|
||||
<g id="Graphic_538">
|
||||
<text transform="translate(761.1309 905.7734)" fill="black">
|
||||
<tspan font-family="Times" font-size="16" font-weight="400" fill="black" x="0" y="15">IO_ISOL_N -> Caravel GPIO[1]</tspan>
|
||||
<tspan font-family="Times" font-size="16" font-weight="400" fill="black" x="0" y="15">IO_ISOL_N <- Caravel GPIO[1]</tspan>
|
||||
<tspan font-family="Times" font-size="16" font-weight="400" fill="black" x="12.445312" y="34">TEST_EN <- Caravel GPIO[0]</tspan>
|
||||
</text>
|
||||
</g>
|
||||
|
|
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 25 KiB |
|
@ -0,0 +1,10 @@
|
|||
# Skywater PDK
|
||||
This directory contains the HDL netlists and code generator for FPGA fabrics.
|
||||
|
||||
- **caravel_fpga_wrapper_hd.v**: The wrapper for FPGA fabric to interface the Caravel SoC, which is technology mapped to the Skywater 130nm Foundry High-Density Standard Cell Library. **This file is automatically generated by a Python script**
|
||||
- **caravel_defines.v**: The parameters required for Caravel wrapper HDL codes
|
||||
- **caravel_fpga_wrapper_hd_template.v**: The template HDL codes for the wrapper
|
||||
- **digital_io_hd.v**: the I/O cell used by High-density FPGA, which is technology mapped to the Skywater 130nm Foundry High-Density Standard Cell Library.
|
||||
- **sky130_fd_sc_hd_wrapper.v**: Wrapper codes for the standard cells from the Skywater 130nm Foundry High-Density Standard Cell Library
|
||||
- **skywater_function_verification.v**: Include pre-processing flags to enable functional verification for FPGAs
|
||||
- **wrapper_lines_generator.py**: Python script to generate the wrapper *caravel\_fpga\_wrapper\_hd.v*
|
BIN
HDL/common/caravel_fpga_wrapper_hd.v (Stored with Git LFS)
BIN
HDL/common/caravel_fpga_wrapper_hd.v (Stored with Git LFS)
Binary file not shown.
BIN
HDL/common/caravel_fpga_wrapper_hd_template.v (Stored with Git LFS)
BIN
HDL/common/caravel_fpga_wrapper_hd_template.v (Stored with Git LFS)
Binary file not shown.
|
@ -0,0 +1,163 @@
|
|||
{
|
||||
"caravel_gpio_input_name": "io_in",
|
||||
"caravel_gpio_output_name": "io_out",
|
||||
"caravel_gpio_direction_name": "io_oeb",
|
||||
"caravel_logic_analyzer_input_name": "la_data_in",
|
||||
"caravel_logic_analyzer_output_name": "la_data_out",
|
||||
"caravel_logic_analyzer_direction_name": "la_oen",
|
||||
"caravel_wishbone_clock_input_name": "wbs_clk_i",
|
||||
"caravel_wishbone_reset_input_name": "wbs_rst_i",
|
||||
"caravel_wishbone_ack_output_name": "wbs_ack_o",
|
||||
"caravel_wishbone_cyc_input_name": "wbs_cyc_i",
|
||||
"caravel_wishbone_stb_input_name": "wbs_stb_i",
|
||||
"caravel_wishbone_we_input_name": "wbs_we_i",
|
||||
"caravel_wishbone_sel_input_name": "wbs_sel_i",
|
||||
"caravel_wishbone_address_input_name": "wbs_adr_i",
|
||||
"caravel_wishbone_data_input_name": "wbs_dat_i",
|
||||
"caravel_wishbone_data_output_name": "wbs_dat_o",
|
||||
"fpga_gpio_input_name": "gfpga_pad_EMBEDDED_IO_HD_SOC_IN",
|
||||
"fpga_gpio_output_name": "gfpga_pad_EMBEDDED_IO_HD_SOC_OUT",
|
||||
"fpga_gpio_direction_name": "gfpga_pad_EMBEDDED_IO_HD_SOC_DIR",
|
||||
"mode_switch_pin_name": "wb_la_switch",
|
||||
"inverted_mode_switch_pin_name": "wb_la_switch_b",
|
||||
"pins": [
|
||||
{
|
||||
"fpga_pin_type": "io",
|
||||
"fpga_pin_index": "0:11",
|
||||
"caravel_pin_type": ["gpio"],
|
||||
"caravel_pin_index": ["24:13"]
|
||||
},
|
||||
{
|
||||
"fpga_pin_type": "ccff_head",
|
||||
"fpga_pin_index": "0:0",
|
||||
"caravel_pin_type": ["input"],
|
||||
"caravel_pin_index": ["12:12"]
|
||||
},
|
||||
{
|
||||
"fpga_pin_type": "sc_tail",
|
||||
"fpga_pin_index": "0:0",
|
||||
"caravel_pin_type": ["output"],
|
||||
"caravel_pin_index": ["11:11"]
|
||||
},
|
||||
{
|
||||
"fpga_pin_type": "io",
|
||||
"fpga_pin_index": "12:20",
|
||||
"caravel_pin_type": ["gpio"],
|
||||
"caravel_pin_index": ["10:2"]
|
||||
},
|
||||
{
|
||||
"fpga_pin_type": "io_isol_n",
|
||||
"fpga_pin_index": "0:0",
|
||||
"caravel_pin_type": ["input"],
|
||||
"caravel_pin_index": ["1:1"]
|
||||
},
|
||||
{
|
||||
"fpga_pin_type": "test_en",
|
||||
"fpga_pin_index": "0:0",
|
||||
"caravel_pin_type": ["input"],
|
||||
"caravel_pin_index": ["0:0"]
|
||||
},
|
||||
{
|
||||
"fpga_pin_type": "io",
|
||||
"fpga_pin_index": "21:23",
|
||||
"caravel_pin_type": ["logic_analyzer_io"],
|
||||
"caravel_pin_index": ["127:125"]
|
||||
},
|
||||
{
|
||||
"fpga_pin_type": "io",
|
||||
"fpga_pin_index": "24:29",
|
||||
"caravel_pin_type": ["logic_analyzer_io"],
|
||||
"caravel_pin_index": ["124:119"]
|
||||
},
|
||||
{
|
||||
"fpga_pin_type": "io",
|
||||
"fpga_pin_index": "30:61",
|
||||
"caravel_pin_type": ["logic_analyzer_io", "wishbone_data_output"],
|
||||
"caravel_pin_index": ["118:87", "0:31"]
|
||||
},
|
||||
{
|
||||
"fpga_pin_type": "io",
|
||||
"fpga_pin_index": "62:93",
|
||||
"caravel_pin_type": ["logic_analyzer_io", "wishbone_data_input"],
|
||||
"caravel_pin_index": ["86:55", "0:31"]
|
||||
},
|
||||
{
|
||||
"fpga_pin_type": "io",
|
||||
"fpga_pin_index": "94:125",
|
||||
"caravel_pin_type": ["logic_analyzer_io", "wishbone_address_input"],
|
||||
"caravel_pin_index": ["54:23", "0:31"]
|
||||
},
|
||||
{
|
||||
"fpga_pin_type": "io",
|
||||
"fpga_pin_index": "126:129",
|
||||
"caravel_pin_type": ["logic_analyzer_io", "wishbone_sel_input"],
|
||||
"caravel_pin_index": ["22:19", "0:3"]
|
||||
},
|
||||
{
|
||||
"fpga_pin_type": "io",
|
||||
"fpga_pin_index": "130:130",
|
||||
"caravel_pin_type": ["logic_analyzer_io", "wishbone_we_input"],
|
||||
"caravel_pin_index": ["18:18", "0:0"]
|
||||
},
|
||||
{
|
||||
"fpga_pin_type": "io",
|
||||
"fpga_pin_index": "131:131",
|
||||
"caravel_pin_type": ["logic_analyzer_io", "wishbone_stb_input"],
|
||||
"caravel_pin_index": ["17:17", "0:0"]
|
||||
},
|
||||
{
|
||||
"fpga_pin_type": "io",
|
||||
"fpga_pin_index": "132:132",
|
||||
"caravel_pin_type": ["logic_analyzer_io", "wishbone_cyc_input"],
|
||||
"caravel_pin_index": ["16:16", "0:0"]
|
||||
},
|
||||
{
|
||||
"fpga_pin_type": "io",
|
||||
"fpga_pin_index": "133:133",
|
||||
"caravel_pin_type": ["logic_analyzer_io", "wishbone_ack_output"],
|
||||
"caravel_pin_index": ["15:15", "0:0"]
|
||||
},
|
||||
{
|
||||
"fpga_pin_type": "io",
|
||||
"fpga_pin_index": "134:134",
|
||||
"caravel_pin_type": ["logic_analyzer_io", "wishbone_reset_input"],
|
||||
"caravel_pin_index": ["14:14", "0:0"]
|
||||
},
|
||||
{
|
||||
"fpga_pin_type": "io",
|
||||
"fpga_pin_index": "135:135",
|
||||
"caravel_pin_type": ["logic_analyzer_io", "wishbone_clock_input"],
|
||||
"caravel_pin_index": ["13:13", "0:0"]
|
||||
},
|
||||
{
|
||||
"fpga_pin_type": "prog_clk",
|
||||
"fpga_pin_index": "0:0",
|
||||
"caravel_pin_type": ["input"],
|
||||
"caravel_pin_index": ["37:37"]
|
||||
},
|
||||
{
|
||||
"fpga_pin_type": "clk",
|
||||
"fpga_pin_index": "0:0",
|
||||
"caravel_pin_type": ["input"],
|
||||
"caravel_pin_index": ["36:36"]
|
||||
},
|
||||
{
|
||||
"fpga_pin_type": "sc_tail",
|
||||
"fpga_pin_index": "0:0",
|
||||
"caravel_pin_type": ["output"],
|
||||
"caravel_pin_index": ["35:35"]
|
||||
},
|
||||
{
|
||||
"fpga_pin_type": "io",
|
||||
"fpga_pin_index": "136:143",
|
||||
"caravel_pin_type": ["gpio"],
|
||||
"caravel_pin_index": ["34:27"]
|
||||
},
|
||||
{
|
||||
"fpga_pin_type": "sc_head",
|
||||
"fpga_pin_index": "0:0",
|
||||
"caravel_pin_type": ["input"],
|
||||
"caravel_pin_index": ["26:26"]
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,175 @@
|
|||
{
|
||||
"caravel_gpio_input_name": "io_in",
|
||||
"caravel_gpio_output_name": "io_out",
|
||||
"caravel_gpio_direction_name": "io_oeb",
|
||||
"caravel_logic_analyzer_input_name": "la_data_in",
|
||||
"caravel_logic_analyzer_output_name": "la_data_out",
|
||||
"caravel_logic_analyzer_direction_name": "la_oen",
|
||||
"caravel_wishbone_clock_input_name": "wbs_clk_i",
|
||||
"caravel_wishbone_reset_input_name": "wbs_rst_i",
|
||||
"caravel_wishbone_ack_output_name": "wbs_ack_o",
|
||||
"caravel_wishbone_cyc_input_name": "wbs_cyc_i",
|
||||
"caravel_wishbone_stb_input_name": "wbs_stb_i",
|
||||
"caravel_wishbone_we_input_name": "wbs_we_i",
|
||||
"caravel_wishbone_sel_input_name": "wbs_sel_i",
|
||||
"caravel_wishbone_address_input_name": "wbs_adr_i",
|
||||
"caravel_wishbone_data_input_name": "wbs_dat_i",
|
||||
"caravel_wishbone_data_output_name": "wbs_dat_o",
|
||||
"fpga_gpio_input_name": "gfpga_pad_EMBEDDED_IO_HD_SOC_IN",
|
||||
"fpga_gpio_output_name": "gfpga_pad_EMBEDDED_IO_HD_SOC_OUT",
|
||||
"fpga_gpio_direction_name": "gfpga_pad_EMBEDDED_IO_HD_SOC_DIR",
|
||||
"mode_switch_pin_name": "wb_la_switch",
|
||||
"inverted_mode_switch_pin_name": "wb_la_switch_b",
|
||||
"pins": [
|
||||
{
|
||||
"fpga_pin_type": "io",
|
||||
"fpga_pin_index": "0:11",
|
||||
"caravel_pin_type": ["gpio"],
|
||||
"caravel_pin_index": ["24:13"]
|
||||
},
|
||||
{
|
||||
"fpga_pin_type": "ccff_head",
|
||||
"fpga_pin_index": "0:0",
|
||||
"caravel_pin_type": ["input"],
|
||||
"caravel_pin_index": ["12:12"]
|
||||
},
|
||||
{
|
||||
"fpga_pin_type": "sc_tail",
|
||||
"fpga_pin_index": "0:0",
|
||||
"caravel_pin_type": ["output"],
|
||||
"caravel_pin_index": ["11:11"]
|
||||
},
|
||||
{
|
||||
"fpga_pin_type": "io",
|
||||
"fpga_pin_index": "12:18",
|
||||
"caravel_pin_type": ["gpio"],
|
||||
"caravel_pin_index": ["10:4"]
|
||||
},
|
||||
{
|
||||
"fpga_pin_type": "prog_reset",
|
||||
"fpga_pin_index": "0:0",
|
||||
"caravel_pin_type": ["input"],
|
||||
"caravel_pin_index": ["3:3"]
|
||||
},
|
||||
{
|
||||
"fpga_pin_type": "reset",
|
||||
"fpga_pin_index": "0:0",
|
||||
"caravel_pin_type": ["input"],
|
||||
"caravel_pin_index": ["2:2"]
|
||||
},
|
||||
{
|
||||
"fpga_pin_type": "io_isol_n",
|
||||
"fpga_pin_index": "0:0",
|
||||
"caravel_pin_type": ["input"],
|
||||
"caravel_pin_index": ["1:1"]
|
||||
},
|
||||
{
|
||||
"fpga_pin_type": "test_en",
|
||||
"fpga_pin_index": "0:0",
|
||||
"caravel_pin_type": ["input"],
|
||||
"caravel_pin_index": ["0:0"]
|
||||
},
|
||||
{
|
||||
"fpga_pin_type": "io",
|
||||
"fpga_pin_index": "19:23",
|
||||
"caravel_pin_type": ["logic_analyzer_io"],
|
||||
"caravel_pin_index": ["127:123"]
|
||||
},
|
||||
{
|
||||
"fpga_pin_type": "io",
|
||||
"fpga_pin_index": "24:29",
|
||||
"caravel_pin_type": ["logic_analyzer_io"],
|
||||
"caravel_pin_index": ["122:117"]
|
||||
},
|
||||
{
|
||||
"fpga_pin_type": "io",
|
||||
"fpga_pin_index": "30:61",
|
||||
"caravel_pin_type": ["logic_analyzer_io", "wishbone_data_output"],
|
||||
"caravel_pin_index": ["116:85", "0:31"]
|
||||
},
|
||||
{
|
||||
"fpga_pin_type": "io",
|
||||
"fpga_pin_index": "62:93",
|
||||
"caravel_pin_type": ["logic_analyzer_io", "wishbone_data_input"],
|
||||
"caravel_pin_index": ["84:53", "0:31"]
|
||||
},
|
||||
{
|
||||
"fpga_pin_type": "io",
|
||||
"fpga_pin_index": "94:125",
|
||||
"caravel_pin_type": ["logic_analyzer_io", "wishbone_address_input"],
|
||||
"caravel_pin_index": ["52:21", "0:31"]
|
||||
},
|
||||
{
|
||||
"fpga_pin_type": "io",
|
||||
"fpga_pin_index": "126:129",
|
||||
"caravel_pin_type": ["logic_analyzer_io", "wishbone_sel_input"],
|
||||
"caravel_pin_index": ["20:17", "0:3"]
|
||||
},
|
||||
{
|
||||
"fpga_pin_type": "io",
|
||||
"fpga_pin_index": "130:130",
|
||||
"caravel_pin_type": ["logic_analyzer_io", "wishbone_we_input"],
|
||||
"caravel_pin_index": ["16:16", "0:0"]
|
||||
},
|
||||
{
|
||||
"fpga_pin_type": "io",
|
||||
"fpga_pin_index": "131:131",
|
||||
"caravel_pin_type": ["logic_analyzer_io", "wishbone_stb_input"],
|
||||
"caravel_pin_index": ["15:15", "0:0"]
|
||||
},
|
||||
{
|
||||
"fpga_pin_type": "io",
|
||||
"fpga_pin_index": "132:132",
|
||||
"caravel_pin_type": ["logic_analyzer_io", "wishbone_cyc_input"],
|
||||
"caravel_pin_index": ["14:14", "0:0"]
|
||||
},
|
||||
{
|
||||
"fpga_pin_type": "io",
|
||||
"fpga_pin_index": "133:133",
|
||||
"caravel_pin_type": ["logic_analyzer_io", "wishbone_ack_output"],
|
||||
"caravel_pin_index": ["13:13", "0:0"]
|
||||
},
|
||||
{
|
||||
"fpga_pin_type": "io",
|
||||
"fpga_pin_index": "134:134",
|
||||
"caravel_pin_type": ["logic_analyzer_io", "wishbone_reset_input"],
|
||||
"caravel_pin_index": ["12:12", "0:0"]
|
||||
},
|
||||
{
|
||||
"fpga_pin_type": "io",
|
||||
"fpga_pin_index": "135:135",
|
||||
"caravel_pin_type": ["logic_analyzer_io", "wishbone_clock_input"],
|
||||
"caravel_pin_index": ["11:11", "0:0"]
|
||||
},
|
||||
{
|
||||
"fpga_pin_type": "prog_clk",
|
||||
"fpga_pin_index": "0:0",
|
||||
"caravel_pin_type": ["input"],
|
||||
"caravel_pin_index": ["37:37"]
|
||||
},
|
||||
{
|
||||
"fpga_pin_type": "clk",
|
||||
"fpga_pin_index": "0:0",
|
||||
"caravel_pin_type": ["input"],
|
||||
"caravel_pin_index": ["36:36"]
|
||||
},
|
||||
{
|
||||
"fpga_pin_type": "sc_tail",
|
||||
"fpga_pin_index": "0:0",
|
||||
"caravel_pin_type": ["output"],
|
||||
"caravel_pin_index": ["35:35"]
|
||||
},
|
||||
{
|
||||
"fpga_pin_type": "io",
|
||||
"fpga_pin_index": "136:143",
|
||||
"caravel_pin_type": ["gpio"],
|
||||
"caravel_pin_index": ["34:27"]
|
||||
},
|
||||
{
|
||||
"fpga_pin_type": "sc_head",
|
||||
"fpga_pin_index": "0:0",
|
||||
"caravel_pin_type": ["input"],
|
||||
"caravel_pin_index": ["26:26"]
|
||||
}
|
||||
]
|
||||
}
|
|
@ -12,6 +12,7 @@ import shutil
|
|||
import re
|
||||
import argparse
|
||||
import logging
|
||||
import json
|
||||
|
||||
#####################################################################
|
||||
# Initialize logger
|
||||
|
@ -26,111 +27,214 @@ parser = argparse.ArgumentParser(
|
|||
description='Generator for technology-mapped wrapper')
|
||||
parser.add_argument('--template_netlist', default='caravel_fpga_wrapper_hd_template.v',
|
||||
help='Specify template verilog netlist')
|
||||
parser.add_argument('--pin_assignment_file', required=True,
|
||||
help='Specify the json file constaining pin assignment information')
|
||||
parser.add_argument('--output_verilog', default='caravel_fpga_wrapper_hd.v',
|
||||
help='Specify output verilog file path')
|
||||
args = parser.parse_args()
|
||||
|
||||
#####################################################################
|
||||
# Define Wishbone interface pin sequence
|
||||
# The list start from left-side of the wrapper to the right side
|
||||
# Target FPGA gpio start from 135, 134 ...
|
||||
# Check options:
|
||||
# - Input json file must be valid
|
||||
# Otherwise, error out
|
||||
#####################################################################
|
||||
wishbone_pins = ['wb_clk_i', 'wb_rst_i',
|
||||
'wbs_ack_o', 'wbs_cyc_i',
|
||||
'wbs_stb_i', 'wbs_we_i']
|
||||
|
||||
wishbone_pins.extend([f"wbs_sel_i[{i}]" for i in range(4)])
|
||||
wishbone_pins.extend([f"wbs_adr_i[{i}]" for i in range(32)])
|
||||
wishbone_pins.extend([f"wbs_dat_i[{i}]" for i in range(32)])
|
||||
wishbone_pins.extend([f"wbs_dat_o[{i}]" for i in range(32)])
|
||||
if not isfile(args.pin_assignment_file):
|
||||
logging.error("Invalid pin assignment file: " + args.pin_assignment_file + "\nFile does not exist!\n")
|
||||
exit(1)
|
||||
|
||||
#####################################################################
|
||||
# Define Logic Analyzer interface pin sequence
|
||||
# The list start from left-side of the wrapper to the right side
|
||||
# Target FPGA gpio start from 135, 134 ...
|
||||
# Parse the json file
|
||||
#####################################################################
|
||||
logic_analyzer_pins = []
|
||||
for ipin in range(13, 128):
|
||||
logic_analyzer_pins.append(["la_data_in[" + str(ipin) + "]",
|
||||
"la_data_out[" + str(ipin) + "]", "la_oen[" + str(ipin) + "]"])
|
||||
json_file = open(args.pin_assignment_file, "r")
|
||||
pin_data = json.load(json_file)
|
||||
|
||||
#####################################################################
|
||||
# A function to parse pin range from json data
|
||||
# JSON pin range format is LSB:MSB
|
||||
# Return pin range format is [LSB, MSB] as a list
|
||||
#####################################################################
|
||||
def parse_json_pin_range(json_range) :
|
||||
pin_range_str = json_range.split(':')
|
||||
assert(2 == len(pin_range_str))
|
||||
# If the range is in decend order, we will decrease the MSB by 1
|
||||
if (int(pin_range_str[0]) > int(pin_range_str[1])) :
|
||||
return range(int(pin_range_str[0]), int(pin_range_str[1]) - 1, -1)
|
||||
# If the range is in acend order, we will increase the MSB by 1
|
||||
return range(int(pin_range_str[0]), int(pin_range_str[1]) + 1)
|
||||
|
||||
#####################################################################
|
||||
# Generate wrapper lines
|
||||
#####################################################################
|
||||
netlist_lines = []
|
||||
num_wishbone_pins = len(wishbone_pins)
|
||||
num_logic_analyzer_pins = len(logic_analyzer_pins)
|
||||
num_gpio_pins = 135 - 21 + 1
|
||||
|
||||
print("Number of Wishbone pins: " + str(num_wishbone_pins))
|
||||
print("Number of logic analyzer pins: " + str(num_logic_analyzer_pins))
|
||||
print("Number of gpio pins: " + str(num_gpio_pins))
|
||||
# Walk through the array containing the pin information
|
||||
for pin_info in pin_data['pins']:
|
||||
# Deposit a tab to respect the HDL coding indent
|
||||
curr_line = ""
|
||||
# TODO: Check codes that ensure the pin index should match
|
||||
assert(0 < len(pin_info['caravel_pin_type']))
|
||||
assert(0 < len(pin_info['caravel_pin_index']))
|
||||
#
|
||||
# Branch on the types of connnections:
|
||||
# - FPGA I/O to Caravel GPIO
|
||||
if (("io" == pin_info['fpga_pin_type']) \
|
||||
and (1 == len(pin_info['caravel_pin_type'])) \
|
||||
and ("gpio" == pin_info['caravel_pin_type'][0])):
|
||||
# Should have only 1 port in caravel
|
||||
assert(1 == len(pin_info['caravel_pin_type']))
|
||||
assert(1 == len(pin_info['caravel_pin_index']))
|
||||
# Get pin range
|
||||
fpga_io_pin_range = parse_json_pin_range(pin_info['fpga_pin_index'])
|
||||
caravel_io_pin_range = parse_json_pin_range(pin_info['caravel_pin_index'][0])
|
||||
assert(len(list(fpga_io_pin_range)) == len(list(caravel_io_pin_range)))
|
||||
for indices in zip(list(fpga_io_pin_range), list(caravel_io_pin_range)) :
|
||||
# Connect all the input, output and direction port
|
||||
# FPGA input <- Caravel input
|
||||
curr_line = "assign " + pin_data['fpga_gpio_input_name'] + "[" + str(indices[0]) + "] = " \
|
||||
+ pin_data['caravel_gpio_input_name'] + "[" + str(indices[1]) + "];";
|
||||
netlist_lines.append(" " + curr_line + "\n")
|
||||
# FPGA output -> Caravel output
|
||||
curr_line = "assign " + pin_data['caravel_gpio_output_name'] + "[" + str(indices[1]) + "] = " \
|
||||
+ pin_data['fpga_gpio_output_name'] + "[" + str(indices[0]) + "];";
|
||||
netlist_lines.append(" " + curr_line + "\n")
|
||||
# FPGA direction -> Caravel direction
|
||||
curr_line = "assign " + pin_data['caravel_gpio_direction_name'] + "[" + str(indices[1]) + "] = " \
|
||||
+ pin_data['fpga_gpio_direction_name'] + "[" + str(indices[0]) + "];";
|
||||
netlist_lines.append(" " + curr_line + "\n")
|
||||
|
||||
assert num_wishbone_pins < num_logic_analyzer_pins
|
||||
assert num_logic_analyzer_pins == num_gpio_pins
|
||||
# - FPGA control input ports to Caravel GPIO
|
||||
if (("io" != pin_info['fpga_pin_type']) \
|
||||
and (1 == len(pin_info['caravel_pin_type'])) \
|
||||
and ("input" == pin_info['caravel_pin_type'][0])):
|
||||
# Should have only 1 port in caravel
|
||||
assert(1 == len(pin_info['caravel_pin_type']))
|
||||
assert(1 == len(pin_info['caravel_pin_index']))
|
||||
# Get pin range
|
||||
fpga_io_pin_range = parse_json_pin_range(pin_info['fpga_pin_index'])
|
||||
caravel_io_pin_range = parse_json_pin_range(pin_info['caravel_pin_index'][0])
|
||||
assert(len(list(fpga_io_pin_range)) == len(list(caravel_io_pin_range)))
|
||||
for indices in zip(list(fpga_io_pin_range), list(caravel_io_pin_range)) :
|
||||
# Connect the FPGA input port to the Caravel input
|
||||
curr_line = "assign " + pin_info['fpga_pin_type'] + "[" + str(indices[0]) + "] = " \
|
||||
+ pin_data['caravel_gpio_input_name'] + "[" + str(indices[1]) + "];";
|
||||
netlist_lines.append(" " + curr_line + "\n")
|
||||
# Tie Caravel output port to logic '0'
|
||||
curr_line = "assign " + pin_data['caravel_gpio_output_name'] + "[" + str(indices[1]) + "] = 1'b0;"
|
||||
netlist_lines.append(" " + curr_line + "\n")
|
||||
# Tie Caravel direction port to logic '1'
|
||||
curr_line = "assign " + pin_data['caravel_gpio_direction_name'] + "[" + str(indices[1]) + "] = 1'b1;"
|
||||
netlist_lines.append(" " + curr_line + "\n")
|
||||
|
||||
for ipin in range(0, num_gpio_pins):
|
||||
curr_line = ""
|
||||
if ((ipin < num_wishbone_pins) and (ipin < num_logic_analyzer_pins)):
|
||||
# If this is an input pin of wishbone interface, whose postfix is '_i', we use MUX
|
||||
# otherwise, this is an output pin, we just wire the input to logic analyzer
|
||||
if ((wishbone_pins[ipin].endswith("_i")) or (re.search(r'_i\[\d+\]$', wishbone_pins[ipin], re.M | re.I))):
|
||||
##############################################################
|
||||
# SOC INPUT will be directly driven by either
|
||||
# - the Wishbone input
|
||||
# or
|
||||
# - the logic analyzer input
|
||||
# through a multiplexer controlled by the signal 'wb_la_switch
|
||||
curr_line = " " + "sky130_fd_sc_hd__mux2_1 FPGA2SOC_IN_" + str(135 - ipin) + "_MUX (.S(wb_la_switch), .A1(" + str(
|
||||
wishbone_pins[ipin]) + "), .A0(" + str(logic_analyzer_pins[ipin][0]) + "), .X(gfpga_pad_EMBEDDED_IO_HD_SOC_IN[" + str(135 - ipin) + "]));"
|
||||
netlist_lines.append(curr_line + "\n")
|
||||
##############################################################
|
||||
# SOC OUTPUT will drive an output of logic analyzer
|
||||
# since this I/O is going to interface a Wishbone input only
|
||||
curr_line = " " + "assign " + \
|
||||
str(logic_analyzer_pins[ipin][1]) + \
|
||||
" = gfpga_pad_EMBEDDED_IO_HD_SOC_OUT[" + str(135 - ipin) + "];"
|
||||
netlist_lines.append(curr_line + "\n")
|
||||
elif ((wishbone_pins[ipin].endswith("_o")) or (re.search(r'_o\[\d+\]$', wishbone_pins[ipin], re.M | re.I))):
|
||||
##############################################################
|
||||
# SOC INPUT will be directly driven by logic analyzer
|
||||
# since this I/O is going to interface a Wishbone output only
|
||||
curr_line = " " + "assign gfpga_pad_EMBEDDED_IO_HD_SOC_IN[" + str(
|
||||
135 - ipin) + "] = " + str(logic_analyzer_pins[ipin][0]) + ";"
|
||||
netlist_lines.append(curr_line + "\n")
|
||||
##############################################################
|
||||
# SOC OUTPUT will drive the Wishbone output through a tri-state buffer
|
||||
# As the buffer is enabled by logic '0', we use the inverted 'wb_la_switch'
|
||||
curr_line = " " + "sky130_fd_sc_hd__ebufn_4 FPGA2SOC_OUT_" + str(135 - ipin) + "_DEMUX_WB (" + \
|
||||
".TE_B(wb_la_switch_b), " + \
|
||||
".A(" + "gfpga_pad_EMBEDDED_IO_HD_SOC_OUT[" + str(135 - ipin) + "]), " + \
|
||||
".Z(" + str(wishbone_pins[ipin]) + ")" + \
|
||||
");"
|
||||
netlist_lines.append(curr_line + "\n")
|
||||
##############################################################
|
||||
# SOC OUTPUT will also drive the Logic Analyzer output through a tri-state buffer
|
||||
# As the buffer is enabled by logic '0', we use the 'wb_la_switch'
|
||||
curr_line = " " + "sky130_fd_sc_hd__ebufn_4 FPGA2SOC_OUT_" + str(135 - ipin) + "_DEMUX_LA (" + \
|
||||
".TE_B(wb_la_switch), " + \
|
||||
".A(" + "gfpga_pad_EMBEDDED_IO_HD_SOC_OUT[" + str(135 - ipin) + "]), " + \
|
||||
".Z(" + str(logic_analyzer_pins[ipin][1]) + ")" + \
|
||||
");"
|
||||
netlist_lines.append(curr_line + "\n")
|
||||
# - FPGA control output ports to Caravel GPIO
|
||||
if (("io" != pin_info['fpga_pin_type']) \
|
||||
and (1 == len(pin_info['caravel_pin_type'])) \
|
||||
and ("output" == pin_info['caravel_pin_type'][0])):
|
||||
# Should have only 1 port in caravel
|
||||
assert(1 == len(pin_info['caravel_pin_type']))
|
||||
assert(1 == len(pin_info['caravel_pin_index']))
|
||||
# Get pin range
|
||||
fpga_io_pin_range = parse_json_pin_range(pin_info['fpga_pin_index'])
|
||||
caravel_io_pin_range = parse_json_pin_range(pin_info['caravel_pin_index'][0])
|
||||
assert(len(list(fpga_io_pin_range)) == len(list(caravel_io_pin_range)))
|
||||
for indices in zip(list(fpga_io_pin_range), list(caravel_io_pin_range)) :
|
||||
# Bypass the Caravel input
|
||||
# Connect Caravel output port to FPGA control output
|
||||
curr_line = "assign " + pin_data['caravel_gpio_output_name'] + "[" + str(indices[1]) + "] = " \
|
||||
+ pin_info['fpga_pin_type'] + "[" + str(indices[0]) + "];";
|
||||
netlist_lines.append(" " + curr_line + "\n")
|
||||
# Tie Caravel direction port to logic '0'
|
||||
curr_line = "assign " + pin_data['caravel_gpio_direction_name'] + "[" + str(indices[1]) + "] = 1'b0;"
|
||||
netlist_lines.append(" " + curr_line + "\n")
|
||||
|
||||
elif ((ipin >= num_wishbone_pins) and (ipin < num_logic_analyzer_pins)):
|
||||
# - FPGA I/O ports to Caravel logic analyzer I/O only
|
||||
if (("io" == pin_info['fpga_pin_type']) \
|
||||
and (1 == len(pin_info['caravel_pin_type'])) \
|
||||
and ("logic_analyzer_io" == pin_info['caravel_pin_type'][0])):
|
||||
# Should have only 1 port in caravel
|
||||
assert(1 == len(pin_info['caravel_pin_type']))
|
||||
assert(1 == len(pin_info['caravel_pin_index']))
|
||||
# Get pin range
|
||||
fpga_io_pin_range = parse_json_pin_range(pin_info['fpga_pin_index'])
|
||||
caravel_io_pin_range = parse_json_pin_range(pin_info['caravel_pin_index'][0])
|
||||
assert(len(list(fpga_io_pin_range)) == len(list(caravel_io_pin_range)))
|
||||
for indices in zip(list(fpga_io_pin_range), list(caravel_io_pin_range)) :
|
||||
##############################################################
|
||||
# SOC INPUT will be directly driven by logic analyzer
|
||||
# since this I/O is going to interface logic analyzer input only
|
||||
curr_line = "assign " + pin_data['fpga_gpio_input_name'] + "[" + str(indices[0]) + "] = " \
|
||||
+ pin_data['caravel_logic_analyzer_input_name'] + "[" + str(indices[1]) + "]" + ";"
|
||||
netlist_lines.append(" " + curr_line + "\n")
|
||||
##############################################################
|
||||
# SOC OUTPUT will directly drive logic analyzer
|
||||
# since this I/O is going to interface logic analyzer output only
|
||||
curr_line = "assign " + pin_data['caravel_logic_analyzer_output_name'] + "[" + str(indices[1]) + "]" \
|
||||
+ " = " + pin_data['fpga_gpio_output_name'] + "[" + str(indices[0]) + "];"
|
||||
netlist_lines.append(" " + curr_line + "\n")
|
||||
|
||||
# - FPGA I/O ports to Caravel logic analyzer I/O and Wishbone interface
|
||||
if (("io" == pin_info['fpga_pin_type']) \
|
||||
and (2 == len(pin_info['caravel_pin_type'])) \
|
||||
and ("logic_analyzer_io" == pin_info['caravel_pin_type'][0]) \
|
||||
and (pin_info['caravel_pin_type'][1].startswith("wishbone"))):
|
||||
# Should have only 2 port in caravel
|
||||
assert(2 == len(pin_info['caravel_pin_type']))
|
||||
assert(2 == len(pin_info['caravel_pin_index']))
|
||||
# Get pin range
|
||||
fpga_io_pin_range = parse_json_pin_range(pin_info['fpga_pin_index'])
|
||||
la_io_pin_range = parse_json_pin_range(pin_info['caravel_pin_index'][0])
|
||||
wb_io_pin_range = parse_json_pin_range(pin_info['caravel_pin_index'][1])
|
||||
assert(len(list(fpga_io_pin_range)) == len(list(la_io_pin_range)))
|
||||
assert(len(list(fpga_io_pin_range)) == len(list(wb_io_pin_range)))
|
||||
|
||||
# If this is an input pin of wishbone interface, whose postfix is '_i', we use MUX
|
||||
# otherwise, this is an output pin, we just wire the input to logic analyzer
|
||||
if (pin_info['caravel_pin_type'][1].endswith("_input")):
|
||||
for indices in zip(list(fpga_io_pin_range), list(la_io_pin_range), list(wb_io_pin_range)) :
|
||||
##############################################################
|
||||
# SOC INPUT will be directly driven by either
|
||||
# - the Wishbone input
|
||||
# or
|
||||
# - the logic analyzer input
|
||||
# through a multiplexer controlled by the signal 'wb_la_switch
|
||||
curr_line = "sky130_fd_sc_hd__mux2_1 FPGA2SOC_IN_" + str(indices[0]) + "_MUX (" \
|
||||
+ ".S(" + pin_data['mode_switch_pin_name'] + "), " \
|
||||
+ ".A1(" + pin_data['caravel_' + pin_info['caravel_pin_type'][1] + '_name'] + "[" + str(indices[2]) + "]), " \
|
||||
+ ".A0(" + pin_data['caravel_logic_analyzer_input_name'] + "[" + str(indices[1]) + "]), " \
|
||||
+ ".X(" + pin_data['fpga_gpio_input_name'] + "[" + str(indices[0]) + "])" \
|
||||
+ ");"
|
||||
netlist_lines.append(" " + curr_line + "\n")
|
||||
##############################################################
|
||||
# SOC OUTPUT will drive an output of logic analyzer
|
||||
# since this I/O is going to interface a Wishbone input only
|
||||
curr_line = "assign " + pin_data['caravel_logic_analyzer_output_name'] + "[" + str(indices[1]) + "]" \
|
||||
+ " = " + pin_data['fpga_gpio_output_name'] + "[" + str(indices[0]) + "];"
|
||||
netlist_lines.append(" " + curr_line + "\n")
|
||||
elif (pin_info['caravel_pin_type'][1].endswith("_output")):
|
||||
for indices in zip(list(fpga_io_pin_range), list(la_io_pin_range), list(wb_io_pin_range)) :
|
||||
##############################################################
|
||||
# SOC INPUT will be directly driven by logic analyzer
|
||||
# since this I/O is going to interface logic analyzer input only
|
||||
curr_line = " " + "assign gfpga_pad_EMBEDDED_IO_HD_SOC_IN[" + str(
|
||||
135 - ipin) + "] = " + str(logic_analyzer_pins[ipin][0]) + ";"
|
||||
netlist_lines.append(curr_line + "\n")
|
||||
# since this I/O is going to interface a Wishbone output only
|
||||
curr_line = "assign " + pin_data['fpga_gpio_input_name'] + "[" + str(indices[0]) + "] = " \
|
||||
+ pin_data['caravel_logic_analyzer_input_name'] + "[" + str(indices[1]) + "];"
|
||||
netlist_lines.append(" " + curr_line + "\n")
|
||||
##############################################################
|
||||
# SOC OUTPUT will directly drive logic analyzer
|
||||
# since this I/O is going to interface logic analyzer output only
|
||||
curr_line = " " + "assign " + \
|
||||
str(logic_analyzer_pins[ipin][1]) + \
|
||||
" = gfpga_pad_EMBEDDED_IO_HD_SOC_OUT[" + str(135 - ipin) + "];"
|
||||
netlist_lines.append(curr_line + "\n")
|
||||
# SOC OUTPUT will drive the Wishbone output through a tri-state buffer
|
||||
# As the buffer is enabled by logic '0', we use the inverted 'wb_la_switch'
|
||||
curr_line = "sky130_fd_sc_hd__ebufn_4 FPGA2SOC_OUT_" + str(indices[0]) + "_DEMUX_WB (" \
|
||||
+ ".TE_B(" + pin_data['inverted_mode_switch_pin_name'] + "), " \
|
||||
+ ".A(" + pin_data['fpga_gpio_output_name'] + "[" + str(indices[0]) + "]), " \
|
||||
+ ".Z(" + pin_data['caravel_' + pin_info['caravel_pin_type'][1] + '_name'] + "[" + str(indices[2]) + "])" \
|
||||
+ ");"
|
||||
netlist_lines.append(" " + curr_line + "\n")
|
||||
##############################################################
|
||||
# SOC OUTPUT will also drive the Logic Analyzer output through a tri-state buffer
|
||||
# As the buffer is enabled by logic '0', we use the 'wb_la_switch'
|
||||
curr_line = "sky130_fd_sc_hd__ebufn_4 FPGA2SOC_OUT_" + str(indices[0]) + "_DEMUX_LA (" \
|
||||
+ ".TE_B(" + pin_data['mode_switch_pin_name'] + "), " \
|
||||
+ ".A(" + pin_data['fpga_gpio_output_name'] + "[" + str(indices[0]) + "]), " \
|
||||
+ ".Z(" + pin_data['caravel_logic_analyzer_output_name'] + "[" + str(indices[1]) + "])" \
|
||||
+ ");"
|
||||
netlist_lines.append(" " + curr_line + "\n")
|
||||
|
||||
if isfile(args.output_verilog):
|
||||
os.remove(args.output_verilog)
|
||||
|
|
|
@ -49,7 +49,7 @@ logging.info("Found " + str(len(testbench_files)) + " testbenches")
|
|||
# Try to create the directory of Modelsim projects
|
||||
#####################################################################
|
||||
parent_dir_abspath = dirname(dirname(abspath(__file__)))
|
||||
msim_task_dir_abspath = abspath(parent_dir_abspath + args.task_name) + "/postpnr/verilog_testbench";
|
||||
msim_task_dir_abspath = abspath(parent_dir_abspath + "/" + args.task_name) + "/postpnr/verilog_testbench";
|
||||
os.makedirs(msim_task_dir_abspath, exist_ok=True)
|
||||
|
||||
#####################################################################
|
||||
|
|
Loading…
Reference in New Issue