Compare commits

..

8 Commits
v1.0.0 ... main

Author SHA1 Message Date
5ff92a05c1 admin (#15)
Reviewed-on: #15
Co-authored-by: Erik Örtenberg <erik.ortenberg@gmail.com>
Co-committed-by: Erik Örtenberg <erik.ortenberg@gmail.com>
2025-03-14 11:24:01 +01:00
1668e6df6c removed Gantry from this repo and moved into https://git.kryddan.xyz/kryddan/gantry 2025-03-14 11:12:32 +01:00
feb0cc49e6 refined auto detection of library and std for commands 2025-03-14 11:12:30 +01:00
092ae03bdd Added project files to automate library imports 2025-03-14 11:12:12 +01:00
f5efaf300e made dockerized ghdl work with multiple directories 2025-03-14 11:10:55 +01:00
b550740738 added remove functionality of libraries 2025-03-14 11:10:55 +01:00
07576d14a4 added more helper functions 2025-03-14 11:10:55 +01:00
2f77dba953 added basic functionality for project files 2025-03-14 11:10:55 +01:00
25 changed files with 715 additions and 1266 deletions

2
.gitignore vendored
View File

@ -1,4 +1,2 @@
**/wave **/wave
**/work **/work
**/syn
scripts/ghdl

View File

@ -2,8 +2,8 @@
This repository is the public part of the thesis work created by Adam Magnusson and Erik Örtenberg at Chalmers Univerity of Technology. The work contained wihtin this repo details how a network interface will work, mostly built in VHDL. This repository is the public part of the thesis work created by Adam Magnusson and Erik Örtenberg at Chalmers Univerity of Technology. The work contained wihtin this repo details how a network interface will work, mostly built in VHDL.
# Tool instructions # Tool instructions
Read the README.md in `./scripts` Building is facilitated by [Gantry](https://git.kryddan.xyz/kryddan/gantry). A dockerized version of GHDL is available in `scripts`
# Build instructions # Build instructions
TBW Enter `src/ganimede` and run `gantry elab ganimede_toplevel rtl` to build. Run `gantry run ganimede_toplevel_tb tb` to simulate and view wave forms of the project.

View File

@ -1,6 +0,0 @@
# Installation
* Run `python -m venv .`
* Run `./bin/pip install -r requirements.txt`
# Running
* `./bin/python gantry.py --help` documents how it works

View File

@ -1,68 +0,0 @@
import os
from re import split
import subprocess
def getCfFileId(std: str):
return "08" if std == "08" else "93" ## Weird behaviour from GHDL, but all vhdl versions besides 08 have [...]93.cf
def ghdlEnvExists(std, lib):
## Check if work exists
try:
os.lstat("work")
except:
return False
## Check that work is writable
if not os.access("work", os.W_OK):
print("work is write-protected, please acquire correct permissions")
return False
cfFileExists = False
filesInWork = os.listdir("work")
cfFileId = getCfFileId(std)
for file in filesInWork:
if ".cf" in file and lib in file and cfFileId in file:
cfFileExists = True
if not cfFileExists:
return False
## Nothing bad, continue
return True
def createBuildEnv(std: str, lib: str):
if ghdlEnvExists(std=std, lib=lib):
print("Build environment already exists, exiting...")
return -1
## Create build env
print("Initializing GHDL project in current directory...")
os.makedirs("work",exist_ok=True)
addAllVHDLFiles(std=std, lib=lib, init=True)
return 0
def addAllVHDLFiles(std: str, lib: str, init=False):
## Ensure everything is ready for adding files
## (init exception to avoid one if-case in ghdlEnvExists)
if not ghdlEnvExists(std=std, lib=lib) and not init:
return -1
vhdlFiles = []
currentlyAdded = []
cfFileId = getCfFileId(std)
## Find already present files
if not init:
cfFileName = list(filter(lambda x: ".cf" in x and lib in x and cfFileId in x, os.listdir("work")))[0]
cfFilePath = os.path.join("work",cfFileName)
currentlyAdded = getCurrentlyAddedFiles(cfFilePath)
## Add files not added
for file in os.listdir():
if ".vhd" in file and file not in currentlyAdded:
vhdlFiles.append(file)
if len(vhdlFiles) > 0:
print(f"Detected new files. Adding {vhdlFiles}")
command = ["ghdl", "-i", "--workdir=work", f"--work={lib}", f"--std={std}"] + vhdlFiles
subprocess.run(command)
return 0
def getCurrentlyAddedFiles(cfFilePath:str):
f = open(cfFilePath,"r")
lines = f.readlines()
f.close()
fileLines = filter(lambda x: "file" in x, lines)
files = map(lambda x: split("\" \"",x)[1], fileLines)
return list(files)

View File

@ -1,4 +0,0 @@
* GHDL = 4.1.0
* Python >= 3.0.0
* gtkwave >= v3.3.120

View File

@ -1,39 +0,0 @@
import os
import subprocess
import build_env
from typing import List
def generateIncludesForGHDL(includes: List[str]):
cmd = []
for inc in includes:
cmd.append(f"-P{inc}/work")
return cmd
def elabDesign(topDef: str, arch: str, lib: str, std: str, includes: List[str]):
## Add all source files present in pwd
if build_env.addAllVHDLFiles(std, lib) == -1:
print("Adding files failed. GHDL Build environment may be broken...")
return -1
incs = generateIncludesForGHDL(includes)
command = [
"ghdl", "-m", "--workdir=work", f"--work={lib}", f"--std={std}"] + incs + ["-o", f"work/{topDef}-{arch}", f"work.{topDef}", f"{arch}"]
subprocess.run(command)
def runDesign(topDef: str, arch: str, lib: str, std: str, includes):
## elaborate first, then run
if elabDesign(topDef, arch, lib, std, includes) == -1:
print("Elaboration failed...")
return -1
os.makedirs("wave",exist_ok=True)
wavePath = "wave"
incs = generateIncludesForGHDL(includes)
command = [ ## may add -v for verbose
"ghdl", "--elab-run", f"--workdir=work", f"--work={lib}", f"--std={std}"] + incs + ["-o", f"work/{topDef}-{arch}", f"{topDef}", f"{arch}",
f"--wave=wave/{topDef}-{arch}.ghw" ##, "--read-wave-opt=<See"
]
subprocess.run(command)
command = [
"gtkwave", f"{topDef}-{arch}.ghw", "--rcvar",
"do_initial_zoom_fit yes"]
subprocess.run(command, cwd=wavePath)

View File

@ -1,87 +0,0 @@
import typer
import elab as elaborate
import build_env
from typing import List, Optional
from typing_extensions import Annotated
import subprocess
gantry_install_path = "/home/thesis2/exjobb-public/scripts"
app = typer.Typer()
software = typer.Typer()
hardware = typer.Typer()
app.add_typer(software, name="sim", help="GHDL simulator command group")
app.add_typer(hardware, name="syn", help="Synthesis and deployment command group")
def complete_vhdl_ver():
return ["87", "93", "93c", "00", "02", "08"]
@software.command(help="Initializes the GHDL build environment in a library named \"work\". Adds all files ending in \".vhd\" to the project")
def init(
std: Annotated[str, typer.Option(help="Which VHDL standard to use. 87, 93, 93c, 00, 02 or 08", autocompletion=complete_vhdl_ver)] = "93c",
library: Annotated[str, typer.Option("--library", "-l", help="Library to compile from")] = "defaultLib",
):
return build_env.createBuildEnv(std, library)
@software.command(help="Runs analysis and elaboration on the provided top definition and architecture using GHDL. Automatically adds new files not present in the project")
def elab(
topdef: Annotated[str, typer.Argument(help="Top Definition entity to synthesize")] = "",
arch: Annotated[str, typer.Argument(help="Architecture to synthesize within the top definition provided")] = "",
library: Annotated[str, typer.Option("--library", "-l", help="Library to compile from")] = "defaultLib",
includes: Annotated[Optional[List[str]], typer.Option("--include", "-i", help="Which libraries to include in compile")] = None,
std: Annotated[str, typer.Option(help="Which VHDL standard to use. 87, 93, 93c, 00, 02 or 08", autocompletion=complete_vhdl_ver)] = "93c"
):
print(f"Elaborating {topdef} with arch {arch} in library {library}. VHDL {std}.")
if includes is not None:
print(f"Including libraries: {includes}")
else:
includes = []
return elaborate.elabDesign(topdef, arch, library, std, includes)
@software.command(help="Simulates elaborated design in GHDL and views waves in gtkwave. Automatically runs `gantry elab` on the same top def and arch.")
def run(
topdef: Annotated[str, typer.Argument(help="Top Definition entity to synthesize")] = "",
arch: Annotated[str, typer.Argument(help="Architecture to synthesize within the top definition provided")] = "",
library: Annotated[str, typer.Option("--library", "-l", help="Library to compile from")] = "defaultLib",
includes: Annotated[Optional[List[str]], typer.Option("--include", "-i", help="Which libraries to include in compile")] = None,
std: Annotated[str, typer.Option(help="Which VHDL standard to use. 87, 93, 93c, 00, 02 or 08", autocompletion=complete_vhdl_ver)] = "93c"
):
print(f"Running (and synthesizing if needed) {topdef} with arch {arch} in library {library}. VHDL {std}")
if includes is not None:
print(f"Including libraries: {includes}")
else:
includes = []
return elaborate.runDesign(topdef, arch, library, std, includes)
@hardware.command(help="Synthesizes the provided top level design using NXPython. Make sure you run this with NXPython.")
def synth(
topdef: Annotated[str, typer.Argument(help="Top Definition entity to synthesize")] = "",
library: Annotated[str, typer.Option("--library", "-l", help="Library to compile from, defaults to \"work\"")] = "defaultLib"
):
proc = subprocess.run(["source_and_run.sh", f"{gantry_install_path}/nxp_script.py", "synthDesign", library, topdef])
@hardware.command(help="Places the provided top level design using NXPython. Make sure you run this with NXPython.")
def place(
topdef: Annotated[str, typer.Argument(help="Top Definition entity to synthesize")] = "",
library: Annotated[str, typer.Option("--library", "-l", help="Library to compile from, defaults to \"work\"")] = "defaultLib"
):
proc = subprocess.run(["source_and_run.sh", f"{gantry_install_path}/nxp_script.py", "placeDesign", library, topdef])
@hardware.command(help="Routes the provided top level design using NXPython. Make sure you run this with NXPython.")
def route(
topdef: Annotated[str, typer.Argument(help="Top Definition entity to synthesize")] = "",
library: Annotated[str, typer.Option("--library", "-l", help="Library to compile from, defaults to \"work\"")] = "defaultLib"
):
proc = subprocess.run(["source_and_run.sh", f"{gantry_install_path}/nxp_script.py", "routeDesign", library, topdef])
@hardware.command(help="")
def build():
print("Build!")
if __name__ == "__main__":
app()

6
scripts/ghdl Executable file
View File

@ -0,0 +1,6 @@
#!/bin/bash
VARS="$@"
COMMAND="ghdl $VARS"
PROJ_HOME=/home/thesis1/repos/exjobb-public
RELPATH=$(realpath -m --relative-to="$PROJ_HOME" .)
docker run -it -v "$PROJ_HOME"/src:/src -w /"$RELPATH" ghdl/ghdl:5.0.0-dev-gcc-ubuntu-24.04 bash -c "$COMMAND"

View File

@ -1,9 +0,0 @@
#!/bin/bash
PWD=$(pwd)
ESCAPED_PWD=$(printf '%s\n' "$PWD" | sed -e 's/[\/&]/\\&/g')
echo $ESCAPED_PWD
sed -i "0,/gantry_install_path =\"\"/s/gantry_install_path = \"\"/gantry_install_path = \"$ESCAPED_PWD\"/" gantry.py
printf "#!/bin/bash \n$PWD/bin/python3 $PWD/gantry.py \$@" > "$PWD/gantry"
chmod +x "$PWD/gantry"

View File

@ -1,81 +0,0 @@
import os
import subprocess
import build_env
import sys
import traceback
from nxpython import *
artifact_path = ""
# Evaluate whether we want the user to provide a selection of files
def makeProject(library: str, project_name: str, path):
# Create an Impulse project and add all VHDL files to it
print(path)
#Createproject enters the implicitly created directory
print(f"Creating project \'{project_name}\'\n")
getProject().setTopCellName(library, project_name)
getProject().setVariantName("NG-MEDIUM", "LGA-625")
getProject().addParameters({})
print(path)
listed = list(os.listdir(path))
files = list(filter(lambda x: ".vhdl" in x or ".vhd" in x or ".v\0" in x, listed)) # Find VHDL and Verilog files
files = list(map(lambda x: os.path.join(path, x), files))
print(f"Adding the following files to project: {files}\n")
getProject().addFiles(files)
print("Saving project")
getProject().save(os.path.join(artifact_path, project_name + ".nym"))
return 0
# Do we want the user to specify how far they want to progress wach step? What does the number mean?
def synthDesign(library: str, project_name: str, path):
# Synthesize the design of the project of the provided `project_name`
print("Starting synthesis\n")
try:
nymFile = os.path.join(artifact_path, project_name + ".nym")
os.lstat(nymFile)
getProject().loadNative(nymFile)
except:
print("No existing project found, creating new project\n")
makeProject(library, project_name, path)
getProject().loadNative(os.path.join(artifact_path, project_name + ".nym"))
getProject().progress("Synthesize", 3)
getProject().save(os.path.join(artifact_path, project_name + "-synth.nym"))
return 0
def placeDesign(library: str, project_name: str, path):
# Place the given design. Will use a previously synthesized project if available, otherwise one will be created.
print("Starting place\n")
try:
nymFile = os.path.join(artifact_path, project_name + "-synth.nym")
os.lstat(nymFile)
getProject().load(nymFile)
except:
print("No existing synthesis found, entering synthesis stage\n")
synthDesign(library, project_name, path)
getProject().load(os.path.join(artifact_path, project_name + "-synth.nym"))
getProject().progress("Place", 5)
getProject().save(os.path.join(artifact_path, project_name + "-place.nym"))
def routeDesign(library: str, project_name: str, path):
# Route the given design. Will use a previously placed project if available, otherwise one will be created.
print("Starting route\n")
try:
nymFile = os.path.join(artifact_path, project_name + "-place.nym")
os.lstat(nymFile)
getProject().load(nymFile)
except:
print("No existing place found, entering place stage\n")
placeDesign(library, project_name, path)
getProject().load(os.path.join(artifact_path, project_name + "-place.nym"))
getProject().progress("Route", 3)
getProject().save(os.path.join(artifact_path, project_name + "-route.nym"))
if __name__ == "__main__":
path = os.getcwd()
artifact_path = os.path.join(path, "syn")
print(f"Calling {sys.argv[1]}() with arguments {sys.argv[2]}, {sys.argv[3]}")
createProject(artifact_path)
globals()[sys.argv[1]](sys.argv[2], sys.argv[3], path)
getProject().createAnalyzer()
getProject().getAnalyzer().launch(conditions="worstcase", maximumSlack=0, searchPathsLimit=10, synthesisMode=False)

View File

@ -1,14 +0,0 @@
attrs==21.4.0
click==8.0.4
commonmark==0.9.1
dataclasses==0.8
importlib-metadata==4.8.3
markdown-it-py==2.0.1
mdurl==0.1.0
Pygments==2.14.0
rich==12.6.0
shellingham==1.4.0
type-extensions==0.1.2
typer==0.10.0
typing_extensions==4.1.1
zipp==3.6.0

6
scripts/source_and_run.sh Executable file
View File

@ -0,0 +1,6 @@
#!/bin/bash
source /gsl/cad/modules/init/bash
module add /gsl/cad/modules/modulefiles/nanoxplore/nxdesignsuite/24.3.0.0
nxpython $@

1
src/.gitignore vendored
View File

@ -1 +0,0 @@
**/grlib*/**

View File

@ -3,8 +3,8 @@ use IEEE.std_logic_1164.all;
use IEEE.NUMERIC_STD.all; use IEEE.NUMERIC_STD.all;
library ganimede; library ganimede;
use ganimede.io_types.all; use ganimede.io_types.all;
library gan_socbridge; library socbridge;
use gan_socbridge.socbridge_driver_pkg.all; use socbridge.socbridge_driver_tb_pkg.all;
library controller; library controller;
entity control_socbridge_tb is entity control_socbridge_tb is
@ -23,8 +23,8 @@ architecture tb of control_socbridge_tb is
control => (others => '0') control => (others => '0')
); );
signal socbridge_driver_to_ext : socbridge_driver_to_ext_t; signal socbridge_driver_to_ext : socbridge_driver_to_ext_t;
signal socbridge_driver_to_ip : socbridge_driver_to_ip_t; signal socbridge_driver_to_buffer : socbridge_driver_to_buffer_t;
signal ip_to_socbridge_driver : ip_to_socbridge_driver_t := ( signal buffer_to_socbridge_driver : buffer_to_socbridge_driver_t := (
payload => (others => '0'), payload => (others => '0'),
write_enable_out => '0', write_enable_out => '0',
is_full_in => '0' is_full_in => '0'
@ -35,9 +35,9 @@ architecture tb of control_socbridge_tb is
seq_mem_access_count => 0, seq_mem_access_count => 0,
cmd => "00" cmd => "00"
); );
signal drivers_to_controller: drivers_to_controller_t := (socbridge => (is_active => '0')); signal socbridge_driver_to_controller: socbridge_driver_to_controller_t := (is_active => '0');
signal controller_to_cpu: controller_to_cpu_t; signal controller_to_cpu: controller_to_cpu_t;
signal controller_to_drivers: controller_to_drivers_t; signal controller_to_socbridge_driver: controller_to_socbridge_driver_t;
signal curr_word : std_logic_vector(ext_to_socbridge_driver.payload'length - 1 downto 0); signal curr_word : std_logic_vector(ext_to_socbridge_driver.payload'length - 1 downto 0);
signal expected_out : std_logic_vector(socbridge_driver_to_ext.payload'length - 1 downto 0); signal expected_out : std_logic_vector(socbridge_driver_to_ext.payload'length - 1 downto 0);
@ -80,12 +80,12 @@ begin
port map( port map(
clk => clk, clk => clk,
rst => rst, rst => rst,
controller_to_socbridge_driver => controller_to_drivers.socbridge, controller_to_socbridge_driver => controller_to_socbridge_driver,
socbridge_driver_to_controller => drivers_to_controller.socbridge, socbridge_driver_to_controller => socbridge_driver_to_controller,
ext_to_socbridge_driver => ext_to_socbridge_driver, ext_to_socbridge_driver => ext_to_socbridge_driver,
socbridge_driver_to_ext => socbridge_driver_to_ext, socbridge_driver_to_ext => socbridge_driver_to_ext,
ip_to_socbridge_driver => ip_to_socbridge_driver, buffer_to_socbridge_driver => buffer_to_socbridge_driver,
socbridge_driver_to_ip => socbridge_driver_to_ip socbridge_driver_to_buffer => socbridge_driver_to_buffer
); );
controller_unit_inst: entity controller.control_unit controller_unit_inst: entity controller.control_unit
@ -94,8 +94,8 @@ begin
rst => rst, rst => rst,
cpu_to_controller => cpu_to_controller, cpu_to_controller => cpu_to_controller,
controller_to_cpu => controller_to_cpu, controller_to_cpu => controller_to_cpu,
drivers_to_controller => drivers_to_controller, socbridge_driver_to_controller => socbridge_driver_to_controller,
controller_to_drivers => controller_to_drivers controller_to_socbridge_driver => controller_to_socbridge_driver
); );
ext_to_socbridge_driver.control(1) <= clk; ext_to_socbridge_driver.control(1) <= clk;
@ -121,21 +121,21 @@ begin
rst <= '0'; rst <= '0';
cpu_to_controller.address <= x"FA0FA0FA"; cpu_to_controller.address <= x"FA0FA0FA";
cpu_to_controller.cmd <= "01"; cpu_to_controller.cmd <= "01";
wait until drivers_to_controller.socbridge.is_active = '1'; wait until socbridge_driver_to_controller.is_active = '1';
report "Task received in driver, awaiting completion..."; report "Task received in driver, awaiting completion...";
cpu_to_controller.address <= (others => '0'); cpu_to_controller.address <= (others => '0');
cpu_to_controller.cmd <= "00"; cpu_to_controller.cmd <= "00";
wait until drivers_to_controller.socbridge.is_active = '0'; wait until socbridge_driver_to_controller.is_active = '0';
wait for CLK_PERIOD; wait for CLK_PERIOD;
report "Task completed in driver, sending next task..."; report "Task completed in driver, sending next task...";
cpu_to_controller.address <= x"FA0FA0FA"; cpu_to_controller.address <= x"FA0FA0FA";
cpu_to_controller.cmd <= "10"; cpu_to_controller.cmd <= "10";
wait for CLK_PERIOD; wait for CLK_PERIOD;
wait until drivers_to_controller.socbridge.is_active = '1'; wait until socbridge_driver_to_controller.is_active = '1';
report "Task received in driver, awaiting completion..."; report "Task received in driver, awaiting completion...";
cpu_to_controller.address <= (others => '0'); cpu_to_controller.address <= (others => '0');
cpu_to_controller.cmd <= "00"; cpu_to_controller.cmd <= "00";
wait until drivers_to_controller.socbridge.is_active = '0'; wait until socbridge_driver_to_controller.is_active = '0';
wait for CLK_PERIOD; wait for CLK_PERIOD;
report "Task completed in driver, ending simulation stimulus"; report "Task completed in driver, ending simulation stimulus";
cpu_to_controller.address <= (others => '0'); cpu_to_controller.address <= (others => '0');
@ -197,19 +197,19 @@ begin
internal_stimulus: process internal_stimulus: process
variable input : positive := 1; variable input : positive := 1;
begin begin
ip_to_socbridge_driver.is_full_in <= '0'; buffer_to_socbridge_driver.is_full_in <= '0';
ip_to_socbridge_driver.write_enable_out <= '0'; buffer_to_socbridge_driver.write_enable_out <= '0';
wait for 3 * CLK_PERIOD; wait for 3 * CLK_PERIOD;
-- stimulus goes here -- stimulus goes here
ip_to_socbridge_driver.write_enable_out <= '1'; buffer_to_socbridge_driver.write_enable_out <= '1';
ip_to_socbridge_driver.payload <= std_logic_vector(to_unsigned(input, ip_to_socbridge_driver.payload'length)); buffer_to_socbridge_driver.payload <= std_logic_vector(to_unsigned(input, buffer_to_socbridge_driver.payload'length));
input := input + 1 mod 256; input := input + 1 mod 256;
wait until rising_edge(clk) and socbridge_driver_to_ip.is_full_out = '0'; wait until rising_edge(clk) and socbridge_driver_to_buffer.is_full_out = '0';
wait until falling_edge(clk); wait until falling_edge(clk);
for x in 0 to 1000 loop for x in 0 to 1000 loop
ip_to_socbridge_driver.payload <= std_logic_vector(to_unsigned(input, ip_to_socbridge_driver.payload'length)); buffer_to_socbridge_driver.payload <= std_logic_vector(to_unsigned(input, buffer_to_socbridge_driver.payload'length));
input := input + 1 mod 256; input := input + 1 mod 256;
wait until rising_edge(clk) and socbridge_driver_to_ip.is_full_out = '0'; wait until rising_edge(clk) and socbridge_driver_to_buffer.is_full_out = '0';
wait until falling_edge(clk); wait until falling_edge(clk);
end loop; end loop;
wait; wait;

View File

@ -7,11 +7,11 @@ use ganimede.io_types.all;
entity control_unit is entity control_unit is
port ( port (
clk, rst : in std_logic; clk, rst : in std_logic;
cpu_to_controller : in cpu_to_controller_t; cpu_to_controller : in cpu_to_controller_t;
controller_to_cpu : out controller_to_cpu_t; controller_to_cpu : out controller_to_cpu_t;
drivers_to_controller : in drivers_to_controller_t; socbridge_driver_to_controller : in socbridge_driver_to_controller_t;
controller_to_drivers : out controller_to_drivers_t controller_to_socbridge_driver : out controller_to_socbridge_driver_t
); );
end entity control_unit; end entity control_unit;
@ -31,17 +31,17 @@ architecture behave of control_unit is
begin begin
comb_proc: process(cpu_to_controller, drivers_to_controller, state) comb_proc: process(cpu_to_controller, socbridge_driver_to_controller, state)
begin begin
ored := '0'; ored := '0';
ready_reduction: for i in 0 to number_of_drivers - 1 loop ready_reduction: for i in 0 to number_of_drivers - 1 loop
ored := ored or drivers_to_controller.socbridge.is_active; ored := ored or socbridge_driver_to_controller.is_active;
end loop ready_reduction; end loop ready_reduction;
controller_to_drivers.socbridge.request <= state.curr_driver; controller_to_socbridge_driver.request <= state.curr_driver;
controller_to_drivers.socbridge.address <= state.address; controller_to_socbridge_driver.address <= state.address;
controller_to_drivers.socbridge.seq_mem_access_count <= state.seq_mem_access_count; controller_to_socbridge_driver.seq_mem_access_count <= state.seq_mem_access_count;
controller_to_cpu.ready <= state.ready; controller_to_cpu.ready <= state.ready;
controller_to_drivers.socbridge.instruction <= state.instruction; controller_to_socbridge_driver.instruction <= state.instruction;
end process comb_proc; end process comb_proc;
sync_proc: process(clk, state) sync_proc: process(clk, state)

View File

@ -19,9 +19,9 @@ architecture tb of control_unit_tb is
(others => '0'), (others => '0'),
0, 0,
"00"); "00");
signal drivers_to_controller: drivers_to_controller_t := (socbridge => (is_active => '0')); signal socbridge_driver_to_controller: socbridge_driver_to_controller_t := (is_active => '0');
signal controller_to_cpu: controller_to_cpu_t; signal controller_to_cpu: controller_to_cpu_t;
signal controller_to_drivers: controller_to_drivers_t; signal controller_to_socbridge_driver: controller_to_socbridge_driver_t;
signal current_driver : std_logic_vector(0 downto 0) := "0"; signal current_driver : std_logic_vector(0 downto 0) := "0";
shared variable word_counter: natural := 0; shared variable word_counter: natural := 0;
@ -42,8 +42,8 @@ begin
rst => reset, rst => reset,
cpu_to_controller => cpu_to_controller, cpu_to_controller => cpu_to_controller,
controller_to_cpu => controller_to_cpu, controller_to_cpu => controller_to_cpu,
drivers_to_controller => drivers_to_controller, socbridge_driver_to_controller => socbridge_driver_to_controller,
controller_to_drivers => controller_to_drivers controller_to_socbridge_driver => controller_to_socbridge_driver
); );
stimulus_proc: process stimulus_proc: process
@ -51,7 +51,7 @@ begin
wait for cycle; wait for cycle;
cpu_to_controller.driver_id <= "1"; cpu_to_controller.driver_id <= "1";
drivers_to_controller.socbridge.is_active <= '0'; socbridge_driver_to_controller.is_active <= '0';
cpu_to_controller.address <= x"F0F0F0F0"; cpu_to_controller.address <= x"F0F0F0F0";
cpu_to_controller.seq_mem_access_count <= 3; cpu_to_controller.seq_mem_access_count <= 3;
cpu_to_controller.cmd <= "01"; cpu_to_controller.cmd <= "01";
@ -65,7 +65,7 @@ begin
report "words remaining are " & integer'image(i); report "words remaining are " & integer'image(i);
end loop for_loop; end loop for_loop;
drivers_to_controller.socbridge.is_active <= '0'; socbridge_driver_to_controller.is_active <= '0';
report "Stim process done"; report "Stim process done";
wait; wait;
end process stimulus_proc; end process stimulus_proc;
@ -76,9 +76,9 @@ begin
wait for cycle; wait for cycle;
wait for cycle; wait for cycle;
assert controller_to_drivers.socbridge.request = '1' report "Incorrect driver_id from control_unit" severity error; assert controller_to_socbridge_driver.request = '1' report "Incorrect driver_id from control_unit" severity error;
assert controller_to_drivers.socbridge.address = x"F0F0F0F0" report "Incorrect address from control_unit" severity error; assert controller_to_socbridge_driver.address = x"F0F0F0F0" report "Incorrect address from control_unit" severity error;
assert controller_to_drivers.socbridge.instruction = WRITE report "Incorrect memory op from control_unit" severity error; assert controller_to_socbridge_driver.instruction = WRITE report "Incorrect memory op from control_unit" severity error;
wait for 5 * cycle; wait for 5 * cycle;
reset <= '1'; reset <= '1';

View File

@ -1 +0,0 @@
ganimede

View File

@ -1,28 +1,24 @@
library IEEE; library IEEE;
use IEEE.std_logic_1164.all; use IEEE.std_logic_1164.all;
library ganimede; library work;
use ganimede.io_types.all; use work.io_types.all;
library gan_socbridge;
use gan_socbridge.socbridge_driver_pkg.all;
library controller;
entity ganimede_toplevel is entity ganimede is
port ( port (
clk : in std_logic; clk : in std_logic;
rst : in std_logic; reset : in std_logic;
cpu_to_ganimede : in cpu_to_controller_t; ext_interface_in : in ext_interface_in_t;
ganimede_to_cpu : out controller_to_cpu_t; ext_interface_out : out ext_interface_out_t;
ext_to_ganimede : in ext_to_ganimede_t; int_interface_in : in int_interface_in_t;
ganimede_to_ext : out ganimede_to_ext_t; int_interface_out : out int_interface_out_t
ip_to_ganimede : in ip_to_ganimede_t;
ganimede_to_ip : out ganimede_to_ip_t
); );
end entity ganimede_toplevel; end entity ganimede;
architecture rtl of ganimede_toplevel is architecture rtl of ganimede is
--- SIGNAL DECLERATIONS --- --- SIGNAL DECLERATIONS ---
signal drivers_to_controller : drivers_to_controller_t; signal gan_int_interface_in : int_interface_in_t;
signal controller_to_drivers : controller_to_drivers_t; signal gan_int_interface_out : int_interface_out_t;
signal gan_ext_interface_in : ext_interface_in_t;
signal gan_ext_interface_out : ext_interface_out_t;
--signal gan_socbridge_WE_in : std_logic; --signal gan_socbridge_WE_in : std_logic;
--signal gan_socbridge_WE_out : std_logic; --signal gan_socbridge_WE_out : std_logic;
@ -42,30 +38,34 @@ architecture rtl of ganimede_toplevel is
-- data_out : out std_logic_vector(WIDTH - 1 downto 0) -- data_out : out std_logic_vector(WIDTH - 1 downto 0)
-- ); -- );
--end component; --end component;
component socbridge_driver is
port(
clk : in std_logic;
reset : in std_logic;
ext_in : in ext_to_socbridge_driver_t;
ext_out : out socbridge_driver_to_ext_t;
int_in : out buffer_to_socbridge_driver_t;
int_out : in socbridge_driver_to_buffer_t
);
end component;
begin begin
--- CONNECT EXTERNAL SIGNALS TO INTERNAL CONNECTIONS --- --- CONNECT EXTERNAL SIGNALS TO INTERNAL CONNECTIONS ---
gan_int_interface_in <= int_interface_in;
int_interface_out <= gan_int_interface_out;
gan_ext_interface_in <= ext_interface_in;
ext_interface_out <= gan_ext_interface_out;
--- DRIVER INSTANTIATION --- --- DRIVER INSTANTIATION ---
socbridge_inst: entity gan_socbridge.socbridge_driver socbridge_driver_inst: socbridge_driver
port map( port map(
clk => clk, clk => clk,
rst => rst, reset => reset,
controller_to_socbridge_driver => controller_to_drivers.socbridge, ext_in => gan_ext_interface_in.socbridge,
socbridge_driver_to_controller => drivers_to_controller.socbridge, ext_out => gan_ext_interface_out.socbridge,
ext_to_socbridge_driver => ext_to_ganimede.socbridge, int_in => gan_int_interface_in.socbridge,
socbridge_driver_to_ext => ganimede_to_ext.socbridge, int_out => gan_int_interface_out.socbridge
ip_to_socbridge_driver => ip_to_ganimede.socbridge,
socbridge_driver_to_ip => ganimede_to_ip.socbridge
);
controller_unit_inst: entity controller.control_unit
port map(
clk => clk,
rst => rst,
cpu_to_controller => cpu_to_ganimede,
controller_to_cpu => ganimede_to_cpu,
drivers_to_controller => drivers_to_controller,
controller_to_drivers => controller_to_drivers
); );
--- LATER WE ADD OPTIMIZATIONS HERE --- --- LATER WE ADD OPTIMIZATIONS HERE ---

View File

@ -1,215 +0,0 @@
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.NUMERIC_STD.all;
library ganimede;
use ganimede.io_types.all;
library gan_socbridge;
use gan_socbridge.socbridge_driver_pkg.all;
library controller;
entity ganimede_tb is
end entity ganimede_tb;
architecture tb of ganimede_tb is
constant CLK_PERIOD : Time := 10 ns;
constant SIMULATION_CYCLE_COUNT : integer := 2000;
signal clk, rst : std_logic := '0';
signal controller_to_socbridge_driver_cmd : command_t;
signal controller_to_socbridge_driver_address : std_logic_vector(31 downto 0);
signal cmd_size : positive;
signal ext_to_ganimede : ext_to_ganimede_t := (socbridge => (
payload => (others => '0'),
control => (others => '0')
));
signal ganimede_to_ext : ganimede_to_ext_t;
signal ganimede_to_ip : ganimede_to_ip_t;
signal ganimede_to_cpu : controller_to_cpu_t;
signal cpu_to_ganimede : cpu_to_controller_t := (
driver_id => (others => '0'),
address => (others => '0'),
seq_mem_access_count => 0,
cmd => (others => '0')
);
signal ip_to_ganimede : ip_to_ganimede_t := (socbridge => (
payload => (others => '0'),
write_enable_out => '0',
is_full_in => '0'
));
signal cpu_to_controller: cpu_to_controller_t := (
driver_id => (others => '0'),
address => (others => '0'),
seq_mem_access_count => 0,
cmd => "00"
);
signal drivers_to_controller: drivers_to_controller_t := (socbridge => (is_active => '0'));
signal controller_to_cpu: controller_to_cpu_t;
signal controller_to_drivers: controller_to_drivers_t;
signal curr_word : std_logic_vector(ext_to_ganimede.socbridge.payload'length - 1 downto 0);
signal expected_out : std_logic_vector(ganimede_to_ext.socbridge.payload'length - 1 downto 0);
procedure fail(error_msg : string) is
begin
wait for CLK_PERIOD;
report "Simulation ending due to: " & error_msg & ". Shutting down..." severity FAILURE;
end procedure;
procedure check_next_state(correct_state: state_t) is
begin
if(not (correct_state = G_next_state)) then
report "Next State is not what was expected, found " & state_t'image(G_next_state)
& " but expected " & state_t'image(correct_state) severity error;
fail("Next State");
end if;
end procedure;
procedure check_data_out(correct_data: std_logic_vector(ganimede_to_ext.socbridge.payload'length - 1 downto 0)) is
begin
if(not (correct_data = ganimede_to_ext.socbridge.payload)) then
report "Data out is not what was expected, found " & to_string(ganimede_to_ext.socbridge.payload)
& " but expected " & to_string(correct_data) severity error;
fail("Data out");
end if;
end procedure;
procedure check_parity(correct_data: std_logic_vector(ganimede_to_ext.socbridge.payload'length - 1 downto 0)) is
begin
if(not (calc_parity(correct_data) = calc_parity(ganimede_to_ext.socbridge.payload))) then
report "Parity out is not what was expected, found " & std_logic'image(calc_parity(ganimede_to_ext.socbridge.payload))
& " but expected " & std_logic'image(calc_parity(correct_data)) severity error;
fail("Parity out");
end if;
end procedure;
begin
ganimede_inst: entity ganimede.ganimede_toplevel
port map(
clk => clk,
rst => rst,
cpu_to_ganimede => cpu_to_ganimede,
ganimede_to_cpu => ganimede_to_cpu,
ext_to_ganimede => ext_to_ganimede,
ganimede_to_ext => ganimede_to_ext,
ip_to_ganimede => ip_to_ganimede,
ganimede_to_ip => ganimede_to_ip
);
ext_to_ganimede.socbridge.control(1) <= clk;
controller_clock_proc: process
begin
for i in 0 to SIMULATION_CYCLE_COUNT - 1 loop
wait for CLK_PERIOD / 2;
clk <= not clk;
end loop;
wait;
end process controller_clock_proc;
stimulus_proc: process
begin
report "Starting Simulation Stimulus!";
rst <= '1';
cpu_to_controller.address <= (others => '0');
cpu_to_controller.cmd <= "00";
cpu_to_controller.driver_id <= "1";
cpu_to_controller.seq_mem_access_count <= 256;
wait for 3 * CLK_PERIOD;
report "Reset grace period ended, starting stimulus...";
rst <= '0';
cpu_to_controller.address <= x"FA0FA0FA";
cpu_to_controller.cmd <= "01";
wait until drivers_to_controller.socbridge.is_active = '1';
report "Task received in driver, awaiting completion...";
cpu_to_controller.address <= (others => '0');
cpu_to_controller.cmd <= "00";
wait until drivers_to_controller.socbridge.is_active = '0';
wait for CLK_PERIOD;
report "Task completed in driver, sending next task...";
cpu_to_controller.address <= x"FA0FA0FA";
cpu_to_controller.cmd <= "10";
wait for CLK_PERIOD;
wait until drivers_to_controller.socbridge.is_active = '1';
report "Task received in driver, awaiting completion...";
cpu_to_controller.address <= (others => '0');
cpu_to_controller.cmd <= "00";
wait until drivers_to_controller.socbridge.is_active = '0';
wait for CLK_PERIOD;
report "Task completed in driver, ending simulation stimulus";
cpu_to_controller.address <= (others => '0');
cpu_to_controller.cmd <= "00";
cpu_to_controller.driver_id <= "0";
cpu_to_controller.seq_mem_access_count <= 0;
wait;
end process stimulus_proc;
external_stimulus_signal: process(curr_word)
begin
ext_to_ganimede.socbridge.payload <= curr_word;
ext_to_ganimede.socbridge.control(0) <= calc_parity(curr_word);
end process external_stimulus_signal;
external_stimulus: process
variable input : positive := 1;
begin
wait for CLK_PERIOD / 1000;
curr_word <= "00000000";
wait for 999 * CLK_PERIOD / 1000;
wait for 2 * CLK_PERIOD;
wait for CLK_PERIOD / 2;
wait for 10* CLK_PERIOD;
curr_word <= "00001001";
wait for CLK_PERIOD;
curr_word <= "00000000";
wait for CLK_PERIOD * 140;
curr_word <= "00101001";
wait for CLK_PERIOD;
curr_word <= "00000000";
wait for CLK_PERIOD * 140;
curr_word <= "00101001";
wait for CLK_PERIOD;
curr_word <= "00000000";
wait for CLK_PERIOD * 20;
curr_word <= "01100111";
wait for CLK_PERIOD;
for x in 0 to 127 loop
curr_word <= std_logic_vector(to_unsigned(input, 8));
input := input + 1 mod 256;
wait for CLK_PERIOD;
end loop;
curr_word <= "00000000";
wait for CLK_PERIOD * 140;
wait for CLK_PERIOD * 20;
curr_word <= "01100111";
wait for CLK_PERIOD;
for x in 0 to 127 loop
curr_word <= std_logic_vector(to_unsigned(input, 8));
input := input + 1 mod 256;
wait for CLK_PERIOD;
end loop;
wait;
end process external_stimulus;
internal_stimulus: process
variable input : positive := 1;
begin
ip_to_ganimede.socbridge.is_full_in <= '0';
ip_to_ganimede.socbridge.write_enable_out <= '0';
wait for 3 * CLK_PERIOD;
-- stimulus goes here
ip_to_ganimede.socbridge.write_enable_out <= '1';
ip_to_ganimede.socbridge.payload <= std_logic_vector(to_unsigned(input, ip_to_ganimede.socbridge.payload'length));
input := input + 1 mod 256;
wait until rising_edge(clk) and ganimede_to_ip.socbridge.is_full_out = '0';
wait until falling_edge(clk);
for x in 0 to 1000 loop
ip_to_ganimede.socbridge.payload <= std_logic_vector(to_unsigned(input, ip_to_ganimede.socbridge.payload'length));
input := input + 1 mod 256;
wait until rising_edge(clk) and ganimede_to_ip.socbridge.is_full_out = '0';
wait until falling_edge(clk);
end loop;
wait;
end process internal_stimulus;
end architecture tb;

View File

@ -5,52 +5,64 @@ use IEEE.MATH_REAL.all;
package io_types is package io_types is
--- CONSTANTS --- --- CONSTANTS ---
constant number_of_drivers : natural := 1; constant number_of_drivers: natural := 1;
constant address_width : natural := 32; constant address_width: natural := 32;
constant inst_word_width : natural := 2; constant seq_vector_length: natural := 8;
constant inst_word_width: natural := 2;
--- STANDARD TYPES --- --- STANDARD TYPES ---
type instruction_command_t is (NO_OP, READ, WRITE); type instruction_command_t is (NO_OP, READ, WRITE);
type ext_protocol_def_t is record type ext_protocol_def_t is record
name: string (1 to 20); name: string (1 to 20);
payload_width : natural; payload_width: natural;
control_width_in, control_width_out : natural; control_width_in, control_width_out: natural;
end record ext_protocol_def_t; end record ext_protocol_def_t;
type interface_inst_t is record type interface_inst_t is record
socbridge : ext_protocol_def_t; socbridge: ext_protocol_def_t;
end record interface_inst_t; end record interface_inst_t;
--- CONTROL UNIT --- --- CONTROL UNIT ---
type cpu_to_controller_t is record type cpu_to_controller_t is record
driver_id : std_logic_vector(number_of_drivers - 1 downto 0); driver_id: std_logic_vector(number_of_drivers - 1 downto 0);
address : std_logic_vector(address_width - 1 downto 0); address: std_logic_vector(address_width - 1 downto 0);
seq_mem_access_count : integer; seq_mem_access_count: integer;
cmd : std_logic_vector(1 downto 0); cmd: std_logic_vector(1 downto 0);
end record cpu_to_controller_t; end record cpu_to_controller_t;
type controller_to_cpu_t is record type controller_to_cpu_t is record
ready : std_logic; ready: std_logic;
end record controller_to_cpu_t; end record controller_to_cpu_t;
--type controller_to_socbridge_driver_t is record
-- driver_id: std_logic_vector(number_of_drivers - 1 downto 0);
-- address: std_logic_vector(address_width - 1 downto 0);
-- seq_mem_access_count: integer;
-- instruction: instruction_command_t;
--end record controller_to_socbridge_driver_t;
--type socbridge_driver_to_controller_t is record
-- active_driver: std_logic_vector(number_of_drivers - 1 downto 0);
--end record socbridge_driver_to_controller_t;
type socbridge_driver_to_controller_t is record
is_active : std_logic;
end record socbridge_driver_to_controller_t;
type controller_to_socbridge_driver_t is record
request: std_logic;
address: std_logic_vector(address_width - 1 downto 0);
seq_mem_access_count: integer;
instruction: instruction_command_t;
end record controller_to_socbridge_driver_t;
--- PROTOCOL INFORMATION --- --- PROTOCOL INFORMATION ---
constant interface_inst : interface_inst_t := ( constant interface_inst : interface_inst_t := (
socbridge => ("SoCBridge ", 8, 2, 2) socbridge => ("SoCBridge ", 8, 2, 2)
); );
--- AUTOGENERATED TYPES --- --- AUTOGENERATED TYPES ---
type socbridge_driver_to_controller_t is record
is_active : std_logic;
end record socbridge_driver_to_controller_t;
type controller_to_socbridge_driver_t is record
request : std_logic;
address : std_logic_vector(address_width - 1 downto 0);
seq_mem_access_count : integer;
instruction : instruction_command_t;
end record controller_to_socbridge_driver_t;
type ext_to_socbridge_driver_t is record type ext_to_socbridge_driver_t is record
payload : STD_LOGIC_VECTOR(interface_inst.socbridge.payload_width - 1 downto 0); payload : STD_LOGIC_VECTOR(interface_inst.socbridge.payload_width - 1 downto 0);
control : STD_LOGIC_VECTOR(interface_inst.socbridge.control_width_in - 1 downto 0); control : STD_LOGIC_VECTOR(interface_inst.socbridge.control_width_in - 1 downto 0);
@ -61,38 +73,30 @@ package io_types is
control : STD_LOGIC_VECTOR(interface_inst.socbridge.control_width_in - 1 downto 0); control : STD_LOGIC_VECTOR(interface_inst.socbridge.control_width_in - 1 downto 0);
end record socbridge_driver_to_ext_t; end record socbridge_driver_to_ext_t;
type socbridge_driver_to_ip_t is record type socbridge_driver_to_buffer_t is record
payload : STD_LOGIC_VECTOR(interface_inst.socbridge.payload_width - 1 downto 0); payload : STD_LOGIC_VECTOR(interface_inst.socbridge.payload_width - 1 downto 0);
write_enable_in, is_full_out : std_logic; write_enable_in, is_full_out : std_logic;
end record socbridge_driver_to_ip_t; end record socbridge_driver_to_buffer_t;
type ip_to_socbridge_driver_t is record type buffer_to_socbridge_driver_t is record
payload : STD_LOGIC_VECTOR(interface_inst.socbridge.payload_width - 1 downto 0); payload : STD_LOGIC_VECTOR(interface_inst.socbridge.payload_width - 1 downto 0);
write_enable_out, is_full_in : std_logic; write_enable_out, is_full_in : std_logic;
end record ip_to_socbridge_driver_t; end record buffer_to_socbridge_driver_t;
type controller_to_drivers_t is record type ext_interface_in_t is record
socbridge : controller_to_socbridge_driver_t; socbridge : ext_to_socbridge_driver_t;
end record controller_to_drivers_t; end record ext_interface_in_t;
type drivers_to_controller_t is record type ext_interface_out_t is record
socbridge : socbridge_driver_to_controller_t;
end record drivers_to_controller_t;
type ext_to_ganimede_t is record
socbridge : ext_to_socbridge_driver_t;
end record ext_to_ganimede_t;
type ganimede_to_ext_t is record
socbridge : socbridge_driver_to_ext_t; socbridge : socbridge_driver_to_ext_t;
end record ganimede_to_ext_t; end record ext_interface_out_t;
type ganimede_to_ip_t is record type int_interface_out_t is record
socbridge : socbridge_driver_to_ip_t; socbridge : socbridge_driver_to_buffer_t;
end record ganimede_to_ip_t; end record int_interface_out_t;
type ip_to_ganimede_t is record type int_interface_in_t is record
socbridge : ip_to_socbridge_driver_t; socbridge : buffer_to_socbridge_driver_t;
end record ip_to_ganimede_t; end record int_interface_in_t;
end package io_types; end package io_types;

View File

@ -1,185 +0,0 @@
title = "ganimede"
createdAt = "2025-03-14"
maintainer = ""
email = ""
version = "0.0.1"
[libraries.ganimede]
vhdl-version = "93c"
path = "ganimede"
[libraries.controller]
vhdl-version = "93c"
path = "controller"
[libraries.testbenches]
vhdl-version = "93c"
path = "control_socbridge_merge"
[libraries.gaisler]
vhdl-version = "93c"
path = "grlib-com-nx-2024.4-b4295/lib/gaisler"
[libraries.grlib]
vhdl-version = "93c"
path = "grlib-com-nx-2024.4-b4295/lib/grlib"
[libraries.gr_socbridge_tb]
vhdl-version = "93c"
path = "grlib-com-nx-2024.4-b4295/verification/socbridge"
[libraries.techmap]
vhdl-version = "93c"
path = "grlib-com-nx-2024.4-b4295/lib/techmap/gencomp"
[libraries.alltech]
vhdl-version = "93c"
path = "grlib-com-nx-2024.4-b4295/lib/techmap/alltech"
[libraries.altera_mf]
vhdl-version = "93c"
path = "grlib-com-nx-2024.4-b4295/lib/techmap/altera_mf"
[libraries.apa]
vhdl-version = "93c"
path = "grlib-com-nx-2024.4-b4295/lib/techmap/apa"
[libraries.artisan]
vhdl-version = "93c"
path = "grlib-com-nx-2024.4-b4295/lib/techmap/artisan"
[libraries.atc18]
vhdl-version = "93c"
path = "grlib-com-nx-2024.4-b4295/lib/techmap/atc18"
[libraries.axcelerator]
vhdl-version = "93c"
path = "grlib-com-nx-2024.4-b4295/lib/techmap/axcelerator"
[libraries.cust1]
vhdl-version = "93c"
path = "grlib-com-nx-2024.4-b4295/lib/techmap/cust1"
[libraries.cycloneiii]
vhdl-version = "93c"
path = "grlib-com-nx-2024.4-b4295/lib/techmap/cycloneiii"
[libraries.dware]
vhdl-version = "93c"
path = "grlib-com-nx-2024.4-b4295/lib/techmap/dware"
[libraries.ec]
vhdl-version = "93c"
path = "grlib-com-nx-2024.4-b4295/lib/techmap/ec"
[libraries.eclipsee]
vhdl-version = "93c"
path = "grlib-com-nx-2024.4-b4295/lib/techmap/eclipsee"
[libraries.fusion]
vhdl-version = "93c"
path = "grlib-com-nx-2024.4-b4295/lib/techmap/fusion"
[libraries.inferred]
vhdl-version = "93c"
path = "grlib-com-nx-2024.4-b4295/lib/techmap/inferred"
[libraries.grdware]
vhdl-version = "93c"
path = "grlib-com-nx-2024.4-b4295/lib/techmap/grdware"
[libraries.maps]
vhdl-version = "93c"
path = "grlib-com-nx-2024.4-b4295/lib/techmap/maps"
[libraries.nx]
vhdl-version = "93c"
path = "grlib-com-nx-2024.4-b4295/lib/techmap/nx"
[libraries.polarfire]
vhdl-version = "93c"
path = "grlib-com-nx-2024.4-b4295/lib/techmap/polarfire"
[libraries.nexus]
vhdl-version = "93c"
path = "grlib-com-nx-2024.4-b4295/lib/techmap/nexus"
[libraries.proasic3]
vhdl-version = "93c"
path = "grlib-com-nx-2024.4-b4295/lib/techmap/proasic3"
[libraries.proasic3e]
vhdl-version = "93c"
path = "grlib-com-nx-2024.4-b4295/lib/techmap/proasic3e"
[libraries.proasic3l]
vhdl-version = "93c"
path = "grlib-com-nx-2024.4-b4295/lib/techmap/proasic3l"
[libraries.saed32]
vhdl-version = "93c"
path = "grlib-com-nx-2024.4-b4295/lib/techmap/saed32"
[libraries.smartfusion2]
vhdl-version = "93c"
path = "grlib-com-nx-2024.4-b4295/lib/techmap/smartfusion2"
[libraries.stratixiii]
vhdl-version = "93c"
path = "grlib-com-nx-2024.4-b4295/lib/techmap/stratixiii"
[libraries.stratixii]
vhdl-version = "93c"
path = "grlib-com-nx-2024.4-b4295/lib/techmap/stratixii"
[libraries.stratixiv]
vhdl-version = "93c"
path = "grlib-com-nx-2024.4-b4295/lib/techmap/stratixiv"
[libraries.stratixv]
vhdl-version = "93c"
path = "grlib-com-nx-2024.4-b4295/lib/techmap/stratixv"
[libraries.umc18]
vhdl-version = "93c"
path = "grlib-com-nx-2024.4-b4295/lib/techmap/umc18"
[libraries.unisim]
vhdl-version = "93c"
path = "grlib-com-nx-2024.4-b4295/lib/techmap/unisim"
[libraries.virage90]
vhdl-version = "93c"
path = "grlib-com-nx-2024.4-b4295/lib/techmap/virage90"
[libraries.virage]
vhdl-version = "93c"
path = "grlib-com-nx-2024.4-b4295/lib/techmap/virage"
[libraries.virtex]
vhdl-version = "93c"
path = "grlib-com-nx-2024.4-b4295/lib/techmap/virtex"
[libraries.virtex5]
vhdl-version = "93c"
path = "grlib-com-nx-2024.4-b4295/lib/techmap/virtex5"
[libraries.opencores]
vhdl-version = "93c"
path = "grlib-com-nx-2024.4-b4295/lib/opencores"
[libraries.eth]
vhdl-version = "93c"
path = "grlib-com-nx-2024.4-b4295/lib/eth"
[libraries.micron]
vhdl-version = "93c"
path = "grlib-com-nx-2024.4-b4295/lib/micron"
[libraries.ahb2ahb]
vhdl-version = "93c"
path = "grlib-com-nx-2024.4-b4295/verification/ahb2ahb"
[libraries.gan_socbridge]
vhdl-version = "93c"
path = "socbridge"

View File

@ -3,14 +3,11 @@ use IEEE.std_logic_1164.all;
use IEEE.NUMERIC_STD.all; use IEEE.NUMERIC_STD.all;
library ganimede; library ganimede;
use ganimede.io_types.all; use ganimede.io_types.all;
library gan_socbridge; library socbridge;
use gan_socbridge.socbridge_driver_pkg.all; use socbridge.socbridge_driver_tb_pkg.all;
entity socbridge_driver is entity socbridge_driver is
generic(
MAX_PKT_SIZE : integer range 1 to 128 := 32
);
port( port(
clk : in std_logic; clk : in std_logic;
rst : in std_logic; rst : in std_logic;
@ -18,8 +15,8 @@ entity socbridge_driver is
socbridge_driver_to_controller : out socbridge_driver_to_controller_t; socbridge_driver_to_controller : out socbridge_driver_to_controller_t;
ext_to_socbridge_driver : in ext_to_socbridge_driver_t; ext_to_socbridge_driver : in ext_to_socbridge_driver_t;
socbridge_driver_to_ext : out socbridge_driver_to_ext_t; socbridge_driver_to_ext : out socbridge_driver_to_ext_t;
ip_to_socbridge_driver : in ip_to_socbridge_driver_t; socbridge_driver_to_buffer : out socbridge_driver_to_buffer_t;
socbridge_driver_to_ip : out socbridge_driver_to_ip_t buffer_to_socbridge_driver : in buffer_to_socbridge_driver_t
); );
end entity socbridge_driver; end entity socbridge_driver;
@ -27,246 +24,230 @@ architecture rtl of socbridge_driver is
signal next_parity_out : std_logic; signal next_parity_out : std_logic;
signal ext_to_socbridge_driver_rec : ext_protocol_t; signal ext_to_socbridge_driver_rec : ext_protocol_t;
signal next_data_out : std_logic_vector(interface_inst.socbridge.payload_width - 1 downto 0); shared variable socbridge_driver_to_ext_data_cmd : std_logic_vector(interface_inst.socbridge.payload_width - 1 downto 0);
signal next_rx_transaction : transaction_t; signal test : std_logic_vector(interface_inst.socbridge.payload_width - 1 downto 0);
signal next_tx_transaction : transaction_t; signal next_cmd : command_t;
signal next_tx_data_size, next_rx_data_size : integer; signal next_cmd_size : integer;
signal next_rx_state : rx_state_t; signal next_state : state_t;
signal next_tx_state : tx_state_t; signal curr_cmd_bits : std_logic_vector(4 downto 0);
signal curr_response : response_t;
signal curr_response_bits : std_logic_vector(4 downto 0);
signal st : state_rec_t; signal st : state_rec_t;
--- TRANSLATOR --- --- TRANSLATOR ---
signal trans_st : translator_state_rec_t; signal trans_st : translator_state_rec_t;
signal trans_next_state : translator_state_t; signal trans_next_state : translator_state_t;
--- FSM COMMUNICATION ---
signal tx_sent_response, rx_received_response : std_logic;
--- MANAGEMENT COMMUNICATION ---
signal mgnt_valid_in, mgnt_valid_out, mgnt_ready_out : std_logic;
begin begin
--- DEBUG GLOBAL BINDINGS ---
-- synthesis translate_off
G_next_parity_out <= next_parity_out;
G_ext_to_socbridge_driver_rec <= ext_to_socbridge_driver_rec;
G_next_state <= next_state;
G_socbridge_driver_to_ext_data_cmd <=test;
G_curr_command_bits <= curr_cmd_bits;
G_curr_response <= curr_response;
G_curr_response_bits <= curr_response_bits;
G_st <= st;
G_trans_st <= trans_st;
-- synthesis translate_on
ext_to_socbridge_driver_rec.data <= ext_to_socbridge_driver.payload; ext_to_socbridge_driver_rec.data <= ext_to_socbridge_driver.payload;
ext_to_socbridge_driver_rec.clk <= ext_to_socbridge_driver.control(1); ext_to_socbridge_driver_rec.clk <= ext_to_socbridge_driver.control(1);
ext_to_socbridge_driver_rec.parity <= ext_to_socbridge_driver.control(0); ext_to_socbridge_driver_rec.parity <= ext_to_socbridge_driver.control(0);
comb_proc: process(ext_to_socbridge_driver, ip_to_socbridge_driver, -- Helpful Bindings --
st, controller_to_socbridge_driver, trans_st, curr_response_bits <= ext_to_socbridge_driver.payload(7 downto 3); -- CANT USE ext_to_socbridge_driver_REC here for some reason, the assignment becomes stasteful
tx_sent_response, rx_received_response) -- Not sure that the two process method is helping here: if this was a normal
variable curr_response_bits : std_logic_vector(4 downto 0); -- signal assignment there would be no confusion.
variable local_next_rx_transaction : transaction_t; -- in the case ... <= ext_to_socbridge_driver_rec we get
variable local_next_tx_transaction : transaction_t; -- curr_resp | ext_to_socbridge_driver_rec | ext_to_socbridge_driver
variable local_next_data_out : std_logic_vector(interface_inst.socbridge.payload_width - 1 downto 0); -- 00000 | 00000000 | 00001001
-- 00000 | 00001001 | 00001001
-- 00001 | 00001001 | 00001001
-- 00001 | 00001001 | 00001001
--
-- but in the case ... <= ext_to_socbridge_driver we get
-- curr_resp | ext_to_socbridge_driver_rec | ext_to_socbridge_driver
-- 00000 | 00000000 | 00001001
-- 00001 | 00001001 | 00001001
-- 00001 | 00001001 | 00001001
-- 00001 | 00001001 | 00001001
with curr_response_bits select
curr_response <= WRITE_ACK when "00001",
WRITE_ACK when "00101",
READ_RESPONSE when "01000",
READ_RESPONSE when "01100",
NO_OP when others;
comb_proc: process(ext_to_socbridge_driver, buffer_to_socbridge_driver, curr_response, st, controller_to_socbridge_driver, trans_st)
begin begin
-- Helpful Bindings -- -- Outputs
next_rx_data_size <= 2 ** to_integer(unsigned(ext_to_socbridge_driver.payload(2 downto 0))); socbridge_driver_to_ext <= create_io_type_out_from_ext_protocol(st.socbridge_driver_to_ext_reg);
curr_response_bits := ext_to_socbridge_driver.payload(7 downto 3); with trans_st.curr_state select
-- Set helper var to current transaction seen at the input. socbridge_driver_to_controller.is_active <= '0' when IDLE,
local_next_rx_transaction := NO_OP; '1' when others;
if curr_response_bits = "10000" then
local_next_rx_transaction := WRITE_ADD;
elsif curr_response_bits = "10100" then
local_next_rx_transaction := WRITE;
elsif curr_response_bits = "11000" then
local_next_rx_transaction := READ_ADD;
elsif curr_response_bits = "11100" then
local_next_rx_transaction := READ;
elsif curr_response_bits = "01001" then
local_next_rx_transaction := P_ERR;
elsif curr_response_bits = "00101" or curr_response_bits = "00001" then
local_next_rx_transaction := WRITE_ACK;
elsif curr_response_bits = "01100" or curr_response_bits = "01000" then
local_next_rx_transaction := READ_RESPONSE;
end if;
-- Outputs --
socbridge_driver_to_ext.payload <= st.socbridge_driver_to_ext_reg.data;
socbridge_driver_to_ext.control(0) <= st.socbridge_driver_to_ext_reg.parity;
socbridge_driver_to_ext.control(1) <= st.socbridge_driver_to_ext_reg.clk;
if trans_st.curr_state = IDLE then
socbridge_driver_to_controller.is_active <= '0';
else
socbridge_driver_to_controller.is_active <= '1';
end if;
--- Next State Assignments --- --- State Transition Diagram ---
--- ### TX NEXT STATE ASSIGNMENTS ### --- --
case st.curr_tx_state is --
when IDLE => --
if local_next_tx_transaction /= NO_OP then -- +-----+
next_tx_state <= TX_HEADER; -- | |
else -- \|/ /--+
next_tx_state <= IDLE; -- IDLE<-------------------+
-- / \ |
-- / \ |
-- / \ |
-- \|/ \|/ |
-- TX_HEADER RX_HEADER |
-- |\ / | |
-- | \ / | |
-- | ADDR1 | |
-- | | | |
-- | \|/ | |
-- | ADDR2 | |
-- | | | |
-- | \|/ | |
-- | ADDR3 | |
-- | | | |
-- | \|/ | |
-- | ADDR4 | |
-- | /\ | |
-- | / \ | |
-- |-+ +----| +---+ |
-- \|/ \|/ \|/ | |
-- TX_BODY RX_RESPONSE---+ |
-- | | |
-- | +--+ | |
-- \|/\|/ | \|/ |
-- TX_ACK--+ RX_BODY |
-- | | |
-- | | |
-- +-----------+--------------+
--
--- Next State Assignment ---
case st.curr_state is
when IDLE =>
if st.curr_cmd = WRITE or st.curr_cmd = WRITE_ADD then
next_state <= TX_HEADER;
elsif st.curr_cmd = READ or st.curr_cmd = READ_ADD then
next_state <= RX_HEADER;
else
next_state <= IDLE;
end if; end if;
when TX_HEADER => when TX_HEADER =>
-- Commands -- The header only takes one word (cycle) to transmit.
if st.curr_tx_transaction = WRITE_ADD or st.curr_tx_transaction = READ_ADD then -- Continue to body or address directly afterwards.
next_tx_state <= ADDR1; if st.curr_cmd = WRITE_ADD then
elsif st.curr_tx_transaction = WRITE then next_state <= ADDR1;
next_tx_state <= TX_W_BODY;
elsif st.curr_tx_transaction = READ then
next_tx_state <= TX_AWAIT;
-- Responses
elsif st.curr_tx_transaction = READ_RESPONSE then
next_tx_state <= TX_R_BODY;
else
next_tx_state <= IDLE;
end if;
when TX_R_BODY =>
if st.tx_stage <= 1 then
next_tx_state <= IDLE;
else else
next_tx_state <= TX_R_BODY; next_state <= TX_BODY;
end if;
when TX_BODY =>
-- Here we want to stay in TX_BODY for the duration of a packet.
if st.write_stage = 0 then
next_state <= TX_ACK;
else
next_state <= TX_BODY;
end if;
when TX_ACK =>
-- Wait for write acknowledgement.
if curr_response = WRITE_ACK then
next_state <= IDLE;
else
next_state <= TX_ACK;
end if;
when RX_HEADER =>
-- The header only takes one word (cycle) to transmit.
-- Continue to awaiting response directly afterwards.
if st.curr_cmd = READ_ADD then
next_state <= ADDR1;
else
next_state <= RX_RESPONSE;
end if;
when RX_RESPONSE =>
-- Wait for read response.
if curr_response = READ_RESPONSE then
next_state <= RX_BODY;
else
next_state <= RX_RESPONSE;
end if;
when RX_BODY =>
-- Here we want to stay in RX_BODY for the duration of a packet.
if st.read_stage = 0 then
next_state <= IDLE;
else
next_state <= RX_BODY;
end if; end if;
when ADDR1 => when ADDR1 =>
next_tx_state <= ADDR2; -- Transmits the entire address and returns to the appropriate
next_state <= ADDR2;
when ADDR2 => when ADDR2 =>
next_tx_state <= ADDR3; next_state <= ADDR3;
when ADDR3 => when ADDR3 =>
next_tx_state <= ADDR4; next_state <= ADDR4;
when ADDR4 => when ADDR4 =>
if st.curr_tx_transaction = READ_ADD then if st.curr_cmd = WRITE or st.curr_cmd = WRITE_ADD then
next_tx_state <= TX_AWAIT; next_state <= TX_BODY;
elsif st.curr_tx_transaction = WRITE_ADD then
next_tx_state <= TX_W_BODY;
else else
next_tx_state <= IDLE; next_state <= RX_RESPONSE;
end if;
when TX_W_BODY =>
if st.tx_stage <= 1 then
next_tx_state <= TX_AWAIT;
else
next_tx_state <= TX_W_BODY;
end if;
when TX_AWAIT =>
-- Wait for RX FSM to get a response
if (st.curr_tx_transaction = WRITE_ADD or st.curr_tx_transaction = WRITE)
and st.curr_rx_transaction = WRITE_ACK then
next_tx_state <= IDLE;
elsif (st.curr_tx_transaction = READ_ADD or st.curr_tx_transaction = READ)
and st.curr_rx_transaction = READ_RESPONSE and st.rx_stage = 1 then
next_tx_state <= IDLE;
else
next_tx_state <= TX_AWAIT;
end if; end if;
end case; end case;
--- Next State Assignment Of RX FSM ---
case st.curr_rx_state is
when IDLE =>
if local_next_rx_transaction /= NO_OP then
next_rx_state <= RX_HEADER;
else
next_rx_state <= IDLE;
end if;
when RX_HEADER =>
-- Commands
if st.curr_rx_transaction = WRITE_ADD or st.curr_rx_transaction = READ_ADD then
next_rx_state <= ADDR1;
elsif st.curr_rx_transaction = WRITE then
next_rx_state <= RX_W_BODY;
elsif st.curr_rx_transaction = READ then
next_rx_state <= RX_AWAIT;
-- Responses
elsif st.curr_rx_transaction = READ_RESPONSE then
next_rx_state <= RX_R_BODY;
else
next_rx_state <= IDLE;
end if;
when RX_R_BODY =>
if st.rx_stage <= 1 then
next_rx_state <= IDLE;
else
next_rx_state <= RX_R_BODY;
end if;
when ADDR1 =>
next_rx_state <= ADDR2;
when ADDR2 =>
next_rx_state <= ADDR3;
when ADDR3 =>
next_rx_state <= ADDR4;
when ADDR4 =>
if st.curr_rx_transaction = READ_ADD then
next_rx_state <= RX_AWAIT;
elsif st.curr_rx_transaction = WRITE_ADD then
next_rx_state <= RX_W_BODY;
else
next_rx_state <= IDLE; -- Potentially superfluous safety
end if;
when RX_W_BODY =>
if st.rx_stage <= 1 then
next_rx_state <= RX_AWAIT;
else
next_rx_state <= RX_W_BODY;
end if;
when RX_AWAIT =>
-- Wait for TX FSM to send a response
if (st.curr_rx_transaction = WRITE_ADD or st.curr_rx_transaction = WRITE)
and st.curr_tx_transaction = WRITE_ACK then
next_rx_state <= IDLE;
elsif (st.curr_rx_transaction = READ_ADD or st.curr_rx_transaction = READ)
and st.curr_tx_transaction = READ_RESPONSE and st.tx_stage = 1 then
next_rx_state <= IDLE;
else
next_rx_state <= RX_AWAIT;
end if;
end case;
--- Combinatorial output based on current state --- --- Combinatorial output based on current state ---
local_next_data_out := (others => '0'); socbridge_driver_to_ext_data_cmd := (others => '0');
socbridge_driver_to_ip.is_full_out <= '1'; socbridge_driver_to_buffer.is_full_out <= '1';
socbridge_driver_to_ip.write_enable_in <= '0'; socbridge_driver_to_buffer.write_enable_in <= '0';
socbridge_driver_to_ip.payload <= (others => '0'); socbridge_driver_to_buffer.payload <= (others => '0');
--- ### TX_STATE BASED OUTPUT ### --- case st.curr_state is
case st.curr_tx_state is
when IDLE => when IDLE =>
if st.curr_cmd = WRITE or st.curr_cmd = WRITE_ADD then
socbridge_driver_to_ext_data_cmd := get_cmd_bits(st.curr_cmd) & get_size_bits(st.curr_cmd_size);
elsif st.curr_cmd = READ or st.curr_cmd = READ_ADD then
socbridge_driver_to_ext_data_cmd := get_cmd_bits(st.curr_cmd) & get_size_bits(st.curr_cmd_size);
else
end if;
when TX_HEADER => when TX_HEADER =>
if st.curr_tx_transaction = WRITE_ACK or st.curr_tx_transaction = READ_RESPONSE then if st.curr_cmd = WRITE_ADD then
local_next_data_out := get_header_bits(st.curr_tx_transaction, st.curr_rx_transaction) & get_size_bits(st.rx_data_size); socbridge_driver_to_ext_data_cmd := st.curr_addr(7 downto 0);
else else
local_next_data_out := get_header_bits(st.curr_tx_transaction, st.curr_rx_transaction) & get_size_bits(st.tx_data_size); socbridge_driver_to_ext_data_cmd := buffer_to_socbridge_driver.payload;
socbridge_driver_to_buffer.is_full_out <= '0';
end if; end if;
when TX_W_BODY => when TX_BODY =>
if st.tx_stage > 0 then if st.write_stage > 0 then
socbridge_driver_to_ip.is_full_out <= '0'; socbridge_driver_to_buffer.is_full_out <= '0';
local_next_data_out := ip_to_socbridge_driver.payload; socbridge_driver_to_ext_data_cmd := buffer_to_socbridge_driver.payload;
else
socbridge_driver_to_ext_data_cmd := (others => '0');
end if; end if;
when TX_R_BODY => when TX_ACK =>
if st.tx_stage > 0 then
socbridge_driver_to_ip.is_full_out <= '0';
local_next_data_out := ip_to_socbridge_driver.payload;
end if;
when TX_AWAIT =>
when ADDR1 =>
local_next_data_out := st.curr_tx_addr(31 downto 24);
when ADDR2 =>
local_next_data_out := st.curr_tx_addr(23 downto 16);
when ADDR3 =>
local_next_data_out := st.curr_tx_addr(15 downto 8);
when ADDR4 =>
local_next_data_out := st.curr_tx_addr(7 downto 0);
end case;
--- ### RX_STATE BASED OUTPUT ### ---
mgnt_valid_in <= '0';
mgnt_valid_out <= '0';
mgnt_ready_out <= '0';
case st.curr_rx_state is
when IDLE =>
when RX_HEADER => when RX_HEADER =>
when RX_W_BODY => if st.curr_cmd = READ_ADD then
-- TODO Add output signals to management unit later socbridge_driver_to_ext_data_cmd := st.curr_addr(7 downto 0);
-- TODO REPLACE TWO BELOW end if;
socbridge_driver_to_ip.payload <= st.ext_to_socbridge_driver_reg.data; when RX_RESPONSE =>
socbridge_driver_to_ip.write_enable_in <= '1'; when RX_BODY =>
when RX_R_BODY => socbridge_driver_to_buffer.payload <= st.ext_to_socbridge_driver_reg.data;
socbridge_driver_to_ip.payload <= st.ext_to_socbridge_driver_reg.data; socbridge_driver_to_buffer.write_enable_in <= '1';
socbridge_driver_to_ip.write_enable_in <= '1';
when RX_AWAIT =>
if st.curr_rx_transaction = WRITE or st.curr_rx_transaction = WRITE_ADD then
mgnt_valid_in <= '1';
end if;
when ADDR1 => when ADDR1 =>
socbridge_driver_to_ext_data_cmd := st.curr_addr(15 downto 8);
when ADDR2 => when ADDR2 =>
socbridge_driver_to_ext_data_cmd := st.curr_addr(23 downto 16);
when ADDR3 => when ADDR3 =>
socbridge_driver_to_ext_data_cmd := st.curr_addr(31 downto 24);
when ADDR4 => when ADDR4 =>
if st.curr_cmd = WRITE_ADD then
socbridge_driver_to_buffer.is_full_out <= '0';
socbridge_driver_to_ext_data_cmd := buffer_to_socbridge_driver.payload;
report integer'image(to_integer(signed(socbridge_driver_to_ext_data_cmd))) & " "& integer'image(to_integer(signed(buffer_to_socbridge_driver.payload)));
end if;
end case; end case;
next_parity_out <= calc_parity(local_next_data_out); next_parity_out <= calc_parity(socbridge_driver_to_ext_data_cmd);
--- DEBUG GLOBAL BINDINGS ---
-- synthesis translate_off
test <= socbridge_driver_to_ext_data_cmd;
-- synthesis translate_on
--- TRANSLATOR --- --- TRANSLATOR ---
--- Next state assignment --- Next state assignment
case trans_st.curr_state is case trans_st.curr_state is
when IDLE => when IDLE =>
@ -277,7 +258,7 @@ begin
end if; end if;
-- Wait for driver to go idle and send next instruction. Then enter AWAIT -- Wait for driver to go idle and send next instruction. Then enter AWAIT
when SEND => when SEND =>
if st.curr_tx_state /= IDLE then if st.curr_state /= IDLE then
trans_next_state <= SEND_ACCEPTED; trans_next_state <= SEND_ACCEPTED;
else else
trans_next_state <= SEND; trans_next_state <= SEND;
@ -287,56 +268,45 @@ begin
trans_next_state <= AWAIT; trans_next_state <= AWAIT;
-- Wait for driver to finish current instruction, then reenter SEND -- Wait for driver to finish current instruction, then reenter SEND
when AWAIT => when AWAIT =>
if trans_st.curr_inst.seq_mem_access_count <= 0 and st.curr_tx_state = IDLE then if trans_st.curr_inst.seq_mem_access_count <= 0 and st.curr_state = IDLE then
trans_next_state <= IDLE; trans_next_state <= IDLE;
elsif st.curr_tx_state = IDLE then elsif st.curr_state = IDLE then
trans_next_state <= SEND; trans_next_state <= SEND;
else else
trans_next_state <= AWAIT; trans_next_state <= AWAIT;
end if; end if;
end case; end case;
--- NEXT TX TRANSACTION --- --- Combinatorial output based on state
local_next_tx_transaction := NO_OP; next_cmd <= NO_OP;
next_tx_data_size <= 0; next_cmd_size <= 0;
if trans_st.curr_state = IDLE and st.curr_rx_state = RX_AWAIT then
if st.curr_rx_transaction = WRITE or st.curr_rx_transaction = WRITE_ADD then
local_next_tx_transaction := WRITE_ACK;
elsif st.curr_rx_transaction = READ or st.curr_rx_transaction = READ_ADD then
next_tx_data_size <= st.rx_data_size;
local_next_tx_transaction := READ_RESPONSE;
end if;
end if;
case trans_st.curr_state is case trans_st.curr_state is
when IDLE => when IDLE =>
when SEND => when SEND =>
if trans_st.is_first_word = '1' then if trans_st.is_first_word = '1' then
if trans_st.curr_inst.instruction = READ then if trans_st.curr_inst.instruction = READ then
local_next_tx_transaction := READ_ADD; next_cmd <= READ_ADD;
elsif trans_st.curr_inst.instruction = WRITE then elsif trans_st.curr_inst.instruction = WRITE then
local_next_tx_transaction := WRITE_ADD; next_cmd <= WRITE_ADD;
end if; end if;
else else
if trans_st.curr_inst.instruction = READ then if trans_st.curr_inst.instruction = READ then
local_next_tx_transaction := READ; next_cmd <= READ;
elsif trans_st.curr_inst.instruction = WRITE then elsif trans_st.curr_inst.instruction = WRITE then
local_next_tx_transaction := WRITE; next_cmd <= WRITE;
end if; end if;
end if; end if;
if trans_st.curr_inst.seq_mem_access_count > MAX_PKT_SIZE then if trans_st.curr_inst.seq_mem_access_count > 128 then
next_tx_data_size <= MAX_PKT_SIZE; next_cmd_size <= 128;
elsif trans_st.curr_inst.seq_mem_access_count > 0 then elsif trans_st.curr_inst.seq_mem_access_count > 0 then
next_tx_data_size <= trans_st.curr_inst.seq_mem_access_count; next_cmd_size <= trans_st.curr_inst.seq_mem_access_count;
else else
next_tx_data_size <= 0; next_cmd_size <= 0;
end if; end if;
when others => when others =>
end case; end case;
next_tx_transaction <= local_next_tx_transaction;
next_rx_transaction <= local_next_rx_transaction;
next_data_out <= local_next_data_out;
end process comb_proc; end process comb_proc;
-- Process updating internal registers based on primary clock -- Process updating internal registers based on primary clock
seq_proc: process(ext_to_socbridge_driver_rec.clk, rst, clk) seq_proc: process(ext_to_socbridge_driver_rec.clk, rst, clk)
@ -346,79 +316,47 @@ begin
st.socbridge_driver_to_ext_reg.data <= (others => '0'); st.socbridge_driver_to_ext_reg.data <= (others => '0');
st.socbridge_driver_to_ext_reg.clk <= '0'; st.socbridge_driver_to_ext_reg.clk <= '0';
st.socbridge_driver_to_ext_reg.parity <= '1'; st.socbridge_driver_to_ext_reg.parity <= '1';
st.curr_tx_state <= IDLE; st.curr_state <= IDLE;
st.curr_rx_state <= IDLE; st.write_stage <= 0;
st.tx_stage <= 0; st.read_stage <= 0;
st.rx_stage <= 0; st.curr_cmd <= NO_OP;
st.curr_tx_transaction <= NO_OP; st.curr_cmd_size <= 0;
st.curr_rx_transaction <= NO_OP; st.curr_addr <= (others => '0');
st.tx_data_size <= 0;
st.curr_tx_addr <= (others => '0');
st.curr_rx_addr <= (others => '0');
st.curr_write_data <= (others => '0');
st.curr_read_data <= (others => '0');
elsif(rising_edge(ext_to_socbridge_driver_rec.clk)) then elsif(rising_edge(ext_to_socbridge_driver_rec.clk)) then
st.ext_to_socbridge_driver_reg.data <= ext_to_socbridge_driver_rec.data; st.ext_to_socbridge_driver_reg.data <= ext_to_socbridge_driver_rec.data;
st.ext_to_socbridge_driver_reg.clk <= ext_to_socbridge_driver_rec.clk; st.ext_to_socbridge_driver_reg.clk <= ext_to_socbridge_driver_rec.clk;
st.ext_to_socbridge_driver_reg.parity <= ext_to_socbridge_driver_rec.parity; st.ext_to_socbridge_driver_reg.parity <= ext_to_socbridge_driver_rec.parity;
st.socbridge_driver_to_ext_reg.data <= next_data_out; st.socbridge_driver_to_ext_reg.data <= socbridge_driver_to_ext_data_cmd;
st.socbridge_driver_to_ext_reg.clk <= not st.socbridge_driver_to_ext_reg.clk; st.socbridge_driver_to_ext_reg.clk <= not st.socbridge_driver_to_ext_reg.clk;
st.socbridge_driver_to_ext_reg.parity <= next_parity_out; st.socbridge_driver_to_ext_reg.parity <= next_parity_out;
st.curr_tx_state <= next_tx_state; st.curr_state <= next_state;
st.curr_rx_state <= next_rx_state; case st.curr_state is
case st.curr_tx_state is
when IDLE => when IDLE =>
st.curr_tx_transaction <= next_tx_transaction; st.curr_cmd <= next_cmd;
st.tx_data_size <= next_tx_data_size; st.curr_cmd_size <= next_cmd_size;
st.curr_tx_addr <= trans_st.curr_inst.address; st.curr_addr <= trans_st.curr_inst.address;
if next_tx_transaction = WRITE_ADD or next_tx_transaction = WRITE if next_cmd_size > 0 then
or next_tx_transaction = READ_RESPONSE then st.write_stage <= next_cmd_size - 1;
st.tx_stage <= next_tx_data_size; st.read_stage <= next_cmd_size - 1;
else
st.tx_stage <= 0;
end if; end if;
when TX_W_BODY => when TX_HEADER =>
if st.tx_stage > 0 then when TX_BODY =>
st.tx_stage <= st.tx_stage - 1; if st.write_stage > 0 then
st.write_stage <= st.write_stage - 1;
end if; end if;
when TX_R_BODY => when TX_ACK =>
if st.tx_stage > 0 then st.curr_cmd <= NO_OP;
st.tx_stage <= st.tx_stage - 1; st.curr_cmd_size <= 0;
when RX_HEADER =>
when RX_BODY =>
if st.read_stage > 0 then
st.read_stage <= st.read_stage - 1;
else
st.curr_cmd <= NO_OP;
st.curr_cmd_size <= 0;
end if; end if;
when others =>
end case;
case st.curr_rx_state is
when IDLE =>
st.curr_rx_transaction <= next_rx_transaction;
st.rx_data_size <= next_rx_data_size;
if next_rx_transaction = WRITE_ADD or next_rx_transaction = WRITE
or next_rx_transaction = READ_RESPONSE then
st.rx_stage <= next_rx_data_size;
else
st.rx_stage <= 0;
end if;
when RX_HEADER =>
if st.curr_rx_transaction = READ then
st.curr_rx_addr <= std_logic_vector(to_unsigned(to_integer(unsigned(st.curr_rx_addr) + 4), 32));
end if;
when RX_R_BODY =>
if st.rx_stage > 0 then
st.rx_stage <= st.rx_stage - 1;
end if;
when RX_W_BODY =>
if st.rx_stage > 0 then
st.rx_stage <= st.rx_stage - 1;
st.curr_write_data((st.rx_stage) * 8 - 1 downto (st.rx_stage - 1) * 8) <= st.ext_to_socbridge_driver_reg.data;
end if;
when ADDR1 =>
st.curr_rx_addr(31 downto 24) <= st.ext_to_socbridge_driver_reg.data;
when ADDR2 =>
st.curr_rx_addr(23 downto 16) <= st.ext_to_socbridge_driver_reg.data;
when ADDR3 =>
st.curr_rx_addr(15 downto 8) <= st.ext_to_socbridge_driver_reg.data;
when ADDR4 =>
st.curr_rx_addr(7 downto 0) <= st.ext_to_socbridge_driver_reg.data;
when others => when others =>
end case; end case;
end if; end if;
@ -443,9 +381,9 @@ begin
trans_st.is_first_word <= '1'; trans_st.is_first_word <= '1';
when SEND => when SEND =>
when SEND_ACCEPTED => when SEND_ACCEPTED =>
trans_st.curr_inst.seq_mem_access_count <= trans_st.curr_inst.seq_mem_access_count - MAX_PKT_SIZE; trans_st.curr_inst.seq_mem_access_count <= trans_st.curr_inst.seq_mem_access_count - 128;
when AWAIT => when AWAIT =>
if trans_st.curr_inst.seq_mem_access_count <= 0 and st.curr_tx_state = IDLE then if trans_st.curr_inst.seq_mem_access_count <= 0 and st.curr_state = IDLE then
trans_st.curr_inst.request <= '0'; trans_st.curr_inst.request <= '0';
trans_st.curr_inst.address <= (others => '0'); trans_st.curr_inst.address <= (others => '0');
trans_st.curr_inst.seq_mem_access_count <= 0; trans_st.curr_inst.seq_mem_access_count <= 0;

View File

@ -1,12 +1,11 @@
library IEEE; library IEEE;
use IEEE.std_logic_1164.all; use IEEE.std_logic_1164.all;
use ieee.numeric_std.all;
use IEEE.MATH_REAL.all; use IEEE.MATH_REAL.all;
library work; library work;
use work.socbridge_driver_pkg.all; use work.socbridge_driver_tb_pkg.all;
library ganimede; library ganimede;
use ganimede.io_types.all; use ganimede.io_types.all;
library gan_socbridge; library socbridge;
entity socbridge_driver_tb is entity socbridge_driver_tb is
@ -15,95 +14,319 @@ end entity socbridge_driver_tb;
architecture tb of socbridge_driver_tb is architecture tb of socbridge_driver_tb is
signal clk : std_logic := '0'; signal clk : std_logic := '0';
signal rst : std_logic; signal rst : std_logic;
signal cmd : command_t;
signal address : std_logic_vector(31 downto 0);
signal cmd_size : positive;
signal ext_to_socbridge_driver : ext_to_socbridge_driver_t; signal ext_to_socbridge_driver : ext_to_socbridge_driver_t;
signal socbridge_driver_to_ext : socbridge_driver_to_ext_t; signal socbridge_driver_to_ext : socbridge_driver_to_ext_t;
signal ip_to_socbridge_driver : ip_to_socbridge_driver_t; signal buffer_to_socbridge_driver : buffer_to_socbridge_driver_t;
signal socbridge_driver_to_ip : socbridge_driver_to_ip_t; signal socbridge_driver_to_buffer : socbridge_driver_to_buffer_t;
signal controller_to_socbridge_driver : controller_to_socbridge_driver_t; signal controller_to_socbridge_driver : controller_to_socbridge_driver_t;
signal socbridge_driver_to_controller : socbridge_driver_to_controller_t; signal socbridge_driver_controller : socbridge_driver_to_controller_t;
shared variable done : boolean := FALSE; signal curr_word : std_logic_vector(ext_to_socbridge_driver.payload'length - 1 downto 0);
signal expected_out : std_logic_vector(socbridge_driver_to_ext.payload'length - 1 downto 0);
constant CLK_PERIOD : TIME := 10 ns; constant CLK_PERIOD : TIME := 10 ns;
constant MAX_CYCLE_COUNT : INTEGER := 1000000; constant SIMULATION_CYCLE_COUNT : INTEGER := 100;
procedure fail(error_msg : string) is
begin
wait for CLK_PERIOD;
report "Simulation ending due to: " & error_msg & ". Shutting down..." severity FAILURE;
end procedure;
procedure check_next_state(correct_state: state_t) is
begin
if(not (correct_state = G_next_state)) then
report "Next State is not what was expected, found " & state_t'image(G_next_state)
& " but expected " & state_t'image(correct_state) severity error;
fail("Next State");
end if;
end procedure;
procedure check_data_out(correct_data: std_logic_vector(socbridge_driver_to_ext.payload'length - 1 downto 0)) is
begin
if(not (correct_data = socbridge_driver_to_ext.payload)) then
report "Data out is not what was expected, found " & to_string(socbridge_driver_to_ext.payload)
& " but expected " & to_string(correct_data) severity error;
fail("Data out");
end if;
end procedure;
procedure check_parity(correct_data: std_logic_vector(socbridge_driver_to_ext.payload'length - 1 downto 0)) is
begin
if(not (calc_parity(correct_data) = calc_parity(socbridge_driver_to_ext.payload))) then
report "Parity out is not what was expected, found " & std_logic'image(calc_parity(socbridge_driver_to_ext.payload))
& " but expected " & std_logic'image(calc_parity(correct_data)) severity error;
fail("Parity out");
end if;
end procedure;
-- component socbridge_driver is
-- port(
-- clk : in std_logic;
-- rst : in std_logic;
-- cmd : in command_t;
-- address : in std_logic_vector(31 downto 0);
-- cmd_size: in positive;
-- ext_to_socbridge_driver : in ext_to_socbridge_driver_t;
-- socbridge_driver_to_ext : out socbridge_driver_to_ext_t;
-- buffer_to_socbridge_driver : out buffer_to_socbridge_driver_t;
-- socbridge_driver_to_buffer : in socbridge_driver_to_buffer_t
-- );
-- end component socbridge_driver;
begin begin
socbridge_driver_inst: entity gan_socbridge.socbridge_driver socbridge_driver_inst: entity socbridge.socbridge_driver
port map( port map(
clk => clk, clk => clk,
rst => rst, rst => rst,
controller_to_socbridge_driver => controller_to_socbridge_driver, controller_to_socbridge_driver => controller_to_socbridge_driver,
socbridge_driver_to_controller => socbridge_driver_to_controller, socbridge_driver_to_controller => socbridge_driver_controller,
ext_to_socbridge_driver => ext_to_socbridge_driver, ext_to_socbridge_driver => ext_to_socbridge_driver,
socbridge_driver_to_ext => socbridge_driver_to_ext, socbridge_driver_to_ext => socbridge_driver_to_ext,
ip_to_socbridge_driver => ip_to_socbridge_driver, buffer_to_socbridge_driver => buffer_to_socbridge_driver,
socbridge_driver_to_ip => socbridge_driver_to_ip socbridge_driver_to_buffer => socbridge_driver_to_buffer
); );
ext_to_socbridge_driver.control(1) <= clk; ext_to_socbridge_driver.control(1) <= clk;
real_clk_proc: process real_clk_proc: process
variable cycle_count :integer := 0;
begin begin
while (not done) and (cycle_count < MAX_CYCLE_COUNT) loop for x in 0 to SIMULATION_CYCLE_COUNT*2 loop
clk <= not clk; clk <= not clk;
wait for CLK_PERIOD / 2; wait for CLK_PERIOD / 2;
end loop; end loop;
wait; wait;
end process real_clk_proc; end process real_clk_proc;
reset_proc: process
begin
rst <= '1';
wait for CLK_PERIOD * 3;
rst <= '0';
wait;
end process reset_proc;
verify_clk: process
variable last_clk : std_logic;
begin
wait for CLK_PERIOD / 2;
for x in 0 to SIMULATION_CYCLE_COUNT loop
if last_clk = socbridge_driver_to_ext.control(1) then
report "Secondary side clk not correct." severity error;
end if;
last_clk := socbridge_driver_to_ext.control(1);
wait for CLK_PERIOD;
end loop;
wait;
end process verify_clk;
verify_out_signals: process
begin
wait for CLK_PERIOD / 2;
for x in 0 to SIMULATION_CYCLE_COUNT loop
check_data_out(expected_out);
check_parity(expected_out);
wait for CLK_PERIOD;
end loop;
wait;
end process verify_out_signals;
verify_signals : process
begin
expected_out <= "00000000";
wait for 3 * CLK_PERIOD;
wait for CLK_PERIOD / 3;
expected_out <= "00000000";
check_next_state(IDLE);
wait for CLK_PERIOD /4;
check_next_state(TX_HEADER);
wait for CLK_PERIOD * 3 / 4;
expected_out <= get_cmd_bits(WRITE) & get_size_bits_sim(2);
check_next_state(TX_BODY);
wait for CLK_PERIOD;
expected_out <= "00000001";
check_next_state(TX_BODY);
wait for CLK_PERIOD;
expected_out <= "00000010";
check_next_state(TX_ACK);
wait for CLK_PERIOD;
expected_out <= "00000000";
check_next_state(TX_ACK);
wait for CLK_PERIOD;
check_next_state(IDLE);
wait for CLK_PERIOD * 6;
expected_out <= "00000000";
check_next_state(IDLE);
wait for CLK_PERIOD /4;
check_next_state(TX_HEADER);
wait for CLK_PERIOD * 3 / 4;
expected_out <= get_cmd_bits(WRITE_ADD) & get_size_bits(2);
check_next_state(ADDR1);
wait for CLK_PERIOD;
expected_out <= x"FA";
check_next_state(ADDR2);
wait for CLK_PERIOD;
expected_out <= x"A0";
check_next_state(ADDR3);
wait for CLK_PERIOD;
expected_out <= x"0F";
check_next_state(ADDR4);
wait for CLK_PERIOD;
expected_out <= x"FA";
check_next_state(TX_BODY);
wait for CLK_PERIOD;
expected_out <= "00000100";
check_next_state(TX_BODY);
wait for CLK_PERIOD;
expected_out <= "00001000";
check_next_state(TX_ACK);
wait for CLK_PERIOD;
expected_out <= "00000000";
check_next_state(TX_ACK);
wait for CLK_PERIOD;
expected_out <= "00000000";
check_next_state(IDLE);
wait for CLK_PERIOD * 2;
wait for CLK_PERIOD /4;
check_next_state(RX_HEADER);
wait for CLK_PERIOD * 3 / 4;
expected_out <= get_cmd_bits(READ) & get_size_bits(2);
check_next_state(RX_RESPONSE);
wait for CLK_PERIOD;
expected_out <= "00000000";
check_next_state(RX_RESPONSE);
wait for CLK_PERIOD;
check_next_state(RX_BODY);
wait for CLK_PERIOD;
check_next_state(RX_BODY);
wait for CLK_PERIOD;
check_next_state(IDLE);
wait for CLK_PERIOD * 5;
wait for CLK_PERIOD /4;
check_next_state(RX_HEADER);
wait for CLK_PERIOD * 3 / 4;
expected_out <= get_cmd_bits(READ_ADD) & get_size_bits(2);
check_next_state(ADDR1);
wait for CLK_PERIOD;
expected_out <= x"FA";
check_next_state(ADDR2);
wait for CLK_PERIOD;
expected_out <= x"A0";
check_next_state(ADDR3);
wait for CLK_PERIOD;
expected_out <= x"0F";
check_next_state(ADDR4);
wait for CLK_PERIOD;
expected_out <= x"FA";
check_next_state(RX_RESPONSE);
wait for CLK_PERIOD;
expected_out <= "00000000";
check_next_state(RX_RESPONSE);
wait for CLK_PERIOD;
check_next_state(RX_BODY);
wait for CLK_PERIOD;
check_next_state(RX_BODY);
wait for CLK_PERIOD;
check_next_state(IDLE);
wait;
end process verify_signals;
command_stimulus: process command_stimulus: process
begin begin
controller_to_socbridge_driver.instruction <= NO_OP; cmd <= NO_OP;
controller_to_socbridge_driver.seq_mem_access_count <= 0; cmd_size <= 2;
controller_to_socbridge_driver.request <= '0'; wait for 3*CLK_PERIOD;
controller_to_socbridge_driver.address <= x"00000000"; wait for CLK_PERIOD / 2;
wait until rst='0'; cmd <= WRITE;
for i in 100 downto 0 loop wait for CLK_PERIOD;
wait until rising_edge(clk); cmd <= NO_OP;
end loop; wait for CLK_PERIOD * 10;
controller_to_socbridge_driver.instruction <= WRITE; cmd <= WRITE_ADD;
controller_to_socbridge_driver.seq_mem_access_count <= 128; address <= x"FA0FA0FA";
controller_to_socbridge_driver.address <= x"40000000"; wait for CLK_PERIOD;
wait until rising_edge(clk); cmd <= NO_OP;
controller_to_socbridge_driver.request <= '1'; address <= (others => '0');
wait until socbridge_driver_to_controller.is_active = '1'; wait for CLK_PERIOD * 10;
controller_to_socbridge_driver.request <= '0'; cmd <= READ;
wait until socbridge_driver_to_controller.is_active = '0'; wait for CLK_PERIOD;
for i in 100 downto 0 loop cmd <= NO_OP;
wait until rising_edge(clk); wait for CLK_PERIOD * 10;
end loop; cmd <= READ_ADD;
controller_to_socbridge_driver.instruction <= READ; address <= x"FA0FA0FA";
controller_to_socbridge_driver.seq_mem_access_count <= 128; wait for CLK_PERIOD;
controller_to_socbridge_driver.address <= x"40000000"; cmd <= NO_OP;
wait until rising_edge(clk); address <= (others => '0');
controller_to_socbridge_driver.request <= '1';
wait until socbridge_driver_to_controller.is_active = '1';
controller_to_socbridge_driver.request <= '0';
wait until socbridge_driver_to_controller.is_active = '0';
done := TRUE;
wait; wait;
end process command_stimulus; end process command_stimulus;
internal_stimulus: process external_stimulus_signal: process(curr_word)
variable count : integer := 1;
begin begin
ip_to_socbridge_driver.is_full_in <= '0'; ext_to_socbridge_driver.payload <= curr_word;
ip_to_socbridge_driver.write_enable_out <= '0'; ext_to_socbridge_driver.control(0) <= calc_parity(curr_word);
wait until rst = '0'; end process external_stimulus_signal;
-- stimulus goes here
while not done loop external_stimulus: process
wait until (rising_edge(socbridge_driver_to_ext.control(1)) or falling_edge(socbridge_driver_to_ext.control(1))) and socbridge_driver_to_ip.is_full_out = '0'; begin
ip_to_socbridge_driver.payload <= std_logic_vector(to_unsigned(count, 8)); rst <= '0';
count := count + 1; wait for CLK_PERIOD / 1000;
end loop; rst <= '1';
curr_word <= "00000000";
wait for 999 * CLK_PERIOD / 1000;
wait for 2 * CLK_PERIOD;
rst <= '0';
wait for CLK_PERIOD / 2;
wait for 4* CLK_PERIOD;
curr_word <= "00001001";
wait for CLK_PERIOD;
curr_word <= "00000000";
wait for CLK_PERIOD * 14;
curr_word <= "00101001";
wait for CLK_PERIOD;
curr_word <= "00000000";
wait for CLK_PERIOD*5;
curr_word <= "01000001";
wait for CLK_PERIOD;
curr_word <= "10000000";
wait for CLK_PERIOD;
curr_word <= "01000000";
wait for CLK_PERIOD;
curr_word <= "00000000";
wait for CLK_PERIOD*12;
curr_word <= "01100001";
wait for CLK_PERIOD;
curr_word <= "00100000";
wait for CLK_PERIOD;
curr_word <= "00010000";
wait for CLK_PERIOD;
curr_word <= "00000000";
wait;
end process external_stimulus;
internal_stimulus: process
begin
buffer_to_socbridge_driver.is_full_in <= '0';
buffer_to_socbridge_driver.write_enable_out <= '0';
wait for 3 * CLK_PERIOD;
-- stimulus goes here
buffer_to_socbridge_driver.write_enable_out <= '1';
buffer_to_socbridge_driver.payload <= "00000001";
wait until rising_edge(clk) and socbridge_driver_to_buffer.is_full_out = '0';
wait until falling_edge(clk);
buffer_to_socbridge_driver.payload <= "00000010";
wait until rising_edge(clk) and socbridge_driver_to_buffer.is_full_out = '0';
wait until falling_edge(clk);
buffer_to_socbridge_driver.payload <= "00000100";
wait until rising_edge(clk) and socbridge_driver_to_buffer.is_full_out = '0';
wait until falling_edge(clk);
buffer_to_socbridge_driver.payload <= "00001000";
wait until rising_edge(clk) and socbridge_driver_to_buffer.is_full_out = '0';
wait until falling_edge(clk);
buffer_to_socbridge_driver.payload <= "00010000";
wait until socbridge_driver_to_buffer.is_full_out = '0';
wait for CLK_PERIOD/2;
wait until rising_edge(clk);
wait until rising_edge(clk);
buffer_to_socbridge_driver.payload <= "00100000";
wait until socbridge_driver_to_buffer.is_full_out = '0';
wait for CLK_PERIOD/2;
wait until rising_edge(clk);
wait until rising_edge(clk); --- ??? Why all these rising_edge checks?
wait; wait;
end process internal_stimulus; end process internal_stimulus;
end architecture tb ; end architecture tb ;

View File

@ -6,19 +6,20 @@ library ganimede;
use ganimede.io_types.all; use ganimede.io_types.all;
package socbridge_driver_pkg is package socbridge_driver_tb_pkg is
subtype command_size_t is integer range 0 to 128; subtype command_size_t is integer range 0 to 128;
type transaction_t is type command_t is
(NO_OP, WRITE_ADD, WRITE, READ_ADD, READ, P_ERR, WRITE_ACK, READ_RESPONSE); (NO_OP, WRITE_ADD, WRITE, READ_ADD, READ, P_ERR);
type rx_state_t is type response_t is
(IDLE, ADDR1, ADDR2, ADDR3, ADDR4, RX_AWAIT, (NO_OP, WRITE_ACK, READ_RESPONSE);
RX_R_BODY, RX_HEADER, RX_W_BODY);
type state_t is
(IDLE, ADDR1, ADDR2, ADDR3, ADDR4,
TX_HEADER, TX_BODY, TX_ACK,
RX_HEADER, RX_RESPONSE, RX_BODY);
type tx_state_t is
(IDLE, ADDR1, ADDR2, ADDR3, ADDR4, TX_AWAIT,
TX_HEADER, TX_W_BODY, TX_R_BODY);
--- TRANSLATOR --- --- TRANSLATOR ---
type translator_state_t is (IDLE, SEND, SEND_ACCEPTED, AWAIT); type translator_state_t is (IDLE, SEND, SEND_ACCEPTED, AWAIT);
@ -26,7 +27,7 @@ package socbridge_driver_pkg is
curr_inst : controller_to_socbridge_driver_t; curr_inst : controller_to_socbridge_driver_t;
curr_state : translator_state_t; curr_state : translator_state_t;
is_first_word : std_logic; is_first_word : std_logic;
end record translator_state_rec_t; end record translator_state_rec_t;
type ext_protocol_t is record type ext_protocol_t is record
data : std_logic_vector(interface_inst.socbridge.payload_width - 1 downto 0); data : std_logic_vector(interface_inst.socbridge.payload_width - 1 downto 0);
@ -35,17 +36,12 @@ package socbridge_driver_pkg is
end record ext_protocol_t; end record ext_protocol_t;
type state_rec_t is record type state_rec_t is record
curr_rx_transaction : transaction_t; curr_state: state_t;
curr_tx_transaction : transaction_t;
curr_rx_state: rx_state_t;
curr_tx_state: tx_state_t;
ext_to_socbridge_driver_reg, socbridge_driver_to_ext_reg : ext_protocol_t; ext_to_socbridge_driver_reg, socbridge_driver_to_ext_reg : ext_protocol_t;
tx_stage, rx_stage : NATURAL; write_stage, read_stage : NATURAL;
tx_data_size, rx_data_size : integer; curr_cmd : command_t;
curr_write_data : std_logic_vector(31 downto 0); curr_cmd_size: integer;
curr_read_data : std_logic_vector(31 downto 0); curr_addr : std_logic_vector(31 downto 0);
curr_tx_addr : std_logic_vector(31 downto 0);
curr_rx_addr : std_logic_vector(31 downto 0);
end record state_rec_t; end record state_rec_t;
impure function calc_parity( impure function calc_parity(
d : STD_LOGIC_VECTOR(interface_inst.socbridge.payload_width - 1 downto 0) d : STD_LOGIC_VECTOR(interface_inst.socbridge.payload_width - 1 downto 0)
@ -54,13 +50,26 @@ package socbridge_driver_pkg is
input: ext_protocol_t input: ext_protocol_t
) return socbridge_driver_to_ext_t; ) return socbridge_driver_to_ext_t;
function to_string ( a: std_logic_vector) return string; function to_string ( a: std_logic_vector) return string;
pure function get_header_bits(transaction : transaction_t; caused_by: transaction_t) return std_logic_vector; pure function get_cmd_bits(command : command_t) return std_logic_vector;
pure function get_size_bits(size : command_size_t) return std_logic_vector; pure function get_size_bits(size : command_size_t) return std_logic_vector;
pure function get_size_bits_sim(size : command_size_t) return std_logic_vector; pure function get_size_bits_sim(size : command_size_t) return std_logic_vector;
--- DEBUG GLOBAL SIGNALS ---
-- synthesis translate_off
signal G_next_parity_out : std_logic;
signal G_ext_to_socbridge_driver_rec : ext_protocol_t;
signal G_socbridge_driver_to_ext_data_cmd : std_logic_vector(interface_inst.socbridge.payload_width - 1 downto 0);
signal G_next_state : state_t;
signal G_curr_command : command_t;
signal G_curr_command_bits : std_logic_vector(4 downto 0);
signal G_curr_response : response_t;
signal G_curr_response_bits : std_logic_vector(4 downto 0);
signal G_st : state_rec_t;
signal G_trans_st : translator_state_rec_t;
-- synthesis translate_on
end package socbridge_driver_pkg; end package socbridge_driver_tb_pkg;
package body socbridge_driver_pkg is package body socbridge_driver_tb_pkg is
function to_string ( a: std_logic_vector) return string is function to_string ( a: std_logic_vector) return string is
variable b : string (1 to a'length) := (others => NUL); variable b : string (1 to a'length) := (others => NUL);
variable stri : integer := 1; variable stri : integer := 1;
@ -96,33 +105,18 @@ package body socbridge_driver_pkg is
val.control(0) := input.parity; val.control(0) := input.parity;
return val; return val;
end function; end function;
pure function get_cmd_bits(command : command_t)
pure function get_header_bits(transaction : transaction_t; caused_by : transaction_t)
return std_logic_vector is return std_logic_vector is
variable val : std_logic_vector(4 downto 0); variable val : std_logic_vector(4 downto 0);
begin begin
val := "11111"; with command select
if transaction = NO_OP then val := "00000" when NO_OP,
val := "00000"; "10000" when WRITE_ADD,
elsif transaction = WRITE_ADD then "10100" when WRITE,
val := "10000"; "11000" when READ_ADD,
elsif transaction = WRITE then "11100" when READ,
val := "10100"; "01001" when P_ERR,
elsif transaction = READ_ADD then "11111" when others;
val := "11000";
elsif transaction = READ then
val := "11100";
elsif transaction = WRITE_ACK and caused_by = WRITE then
val := "00101";
elsif transaction = WRITE_ACK and caused_by = WRITE_ADD then
val := "00001";
elsif transaction = READ_RESPONSE and caused_by = READ then
val := "01100";
elsif transaction = READ_RESPONSE and caused_by = READ_ADD then
val := "01000";
elsif transaction = P_ERR then
val := "01001";
end if;
return val; return val;
end function; end function;
@ -159,4 +153,4 @@ package body socbridge_driver_pkg is
val := std_logic_vector(TO_UNSIGNED(size - 1, 3)); val := std_logic_vector(TO_UNSIGNED(size - 1, 3));
return val; return val;
end function; end function;
end package body socbridge_driver_pkg; end package body socbridge_driver_tb_pkg;

View File

@ -3,25 +3,15 @@ standard = "1993"
# File names are either absolute or relative to the parent folder of the vhdl_ls.toml file # File names are either absolute or relative to the parent folder of the vhdl_ls.toml file
[libraries] [libraries]
ganimede.files = [ ganimede.files = [
'ganimede/io_type_pkg.vhd', 'ganimede/io_type_pkg.vhd'
'ganimede/ganimede.vhd'
] ]
gan_socbridge.files = [ socbridge.files = [
'socbridge/*.vhd' 'socbridge/*.vhd'
] ]
controller.files = [ controller.files = [
'controller/*.vhd', 'controller/*.vhd',
] ]
grlib.files = [
'grlib-com-nx-2024.4-b4295/lib/grlib/**/*.vhd',
]
techmap.files = [
'grlib-com-nx-2024.4-b4295/lib/techmap/gencomp/**/*.vhd',
]
gaisler.files = [
'grlib-com-nx-2024.4-b4295/lib/gaisler/**/*.vhd',
]
[lint] [lint]
unused = 'error' # Upgrade the 'unused' diagnostic to the 'error' severity unused = 'error' # Upgrade the 'unused' diagnostic to the 'error' severity