Compare commits

..

15 Commits
main ... v1.0.0

Author SHA1 Message Date
2b85765e1f made ganimede synthesizable 2025-04-07 12:21:20 +02:00
31f0c45f2b socbridge fully works with existing socbridge 2025-04-07 11:24:51 +02:00
abbe417dd3 added most functionality for answering to commands from external socbridge 2025-04-04 17:51:46 +02:00
3cf9a13019 Updated driver with split FSMs, DMA from socbridge works 2025-04-04 16:48:26 +02:00
842d8b2305 fixed imports for socbridge 2025-04-04 16:47:53 +02:00
0747cbfdc9 made some progress on reformatting socbridge driver 2025-04-03 17:13:01 +02:00
ffa2ee768c added grlib support (socbridge needs to be recompiled) 2025-04-03 16:14:26 +02:00
c6c5d2d7fc RX FSM almost done 2025-04-03 12:23:51 +02:00
b3a2c4e34a Rough outline of new FSMs probably done. All remaining work is hopefully covered by TODOs 2025-04-02 17:26:51 +02:00
421ed1c006 Continued work on updating FSMs in SoCBridge-driver 2025-04-02 16:13:00 +02:00
b09ab5f1ad Started reworking socbridge driver 2025-04-01 17:04:29 +02:00
d739518596 Added synthesis artifact folder to gitignore 2025-03-31 11:12:59 +02:00
678afc4bd9 testbench might work but ghdl broke so could not test 2025-03-17 12:16:20 +01:00
88dcd19a47 Refactored controller types to support multiple drivers. Also started ganimede tb 2025-03-14 17:01:15 +01:00
10d519301e Started working on implementing units in top level 2025-03-13 17:20:28 +01:00
25 changed files with 1266 additions and 715 deletions

2
.gitignore vendored
View File

@ -1,2 +1,4 @@
**/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
Building is facilitated by [Gantry](https://git.kryddan.xyz/kryddan/gantry). A dockerized version of GHDL is available in `scripts` Read the README.md in `./scripts`
# Build instructions # Build instructions
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. TBW

6
scripts/README.md Normal file
View File

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

68
scripts/build_env.py Normal file
View File

@ -0,0 +1,68 @@
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)

4
scripts/dependecies.md Normal file
View File

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

39
scripts/elab.py Normal file
View File

@ -0,0 +1,39 @@
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)

87
scripts/gantry.py Normal file
View File

@ -0,0 +1,87 @@
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()

View File

@ -1,6 +0,0 @@
#!/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"

9
scripts/install_gantry.sh Executable file
View File

@ -0,0 +1,9 @@
#!/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"

81
scripts/nxp_script.py Normal file
View File

@ -0,0 +1,81 @@
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)

14
scripts/requirements.txt Normal file
View File

@ -0,0 +1,14 @@
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

View File

@ -1,6 +0,0 @@
#!/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 Normal file
View File

@ -0,0 +1 @@
**/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 socbridge; library gan_socbridge;
use socbridge.socbridge_driver_tb_pkg.all; use gan_socbridge.socbridge_driver_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_buffer : socbridge_driver_to_buffer_t; signal socbridge_driver_to_ip : socbridge_driver_to_ip_t;
signal buffer_to_socbridge_driver : buffer_to_socbridge_driver_t := ( signal ip_to_socbridge_driver : ip_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 socbridge_driver_to_controller: socbridge_driver_to_controller_t := (is_active => '0'); signal drivers_to_controller: drivers_to_controller_t := (socbridge => (is_active => '0'));
signal controller_to_cpu: controller_to_cpu_t; signal controller_to_cpu: controller_to_cpu_t;
signal controller_to_socbridge_driver: controller_to_socbridge_driver_t; signal controller_to_drivers: controller_to_drivers_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_socbridge_driver, controller_to_socbridge_driver => controller_to_drivers.socbridge,
socbridge_driver_to_controller => socbridge_driver_to_controller, socbridge_driver_to_controller => drivers_to_controller.socbridge,
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,
buffer_to_socbridge_driver => buffer_to_socbridge_driver, ip_to_socbridge_driver => ip_to_socbridge_driver,
socbridge_driver_to_buffer => socbridge_driver_to_buffer socbridge_driver_to_ip => socbridge_driver_to_ip
); );
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,
socbridge_driver_to_controller => socbridge_driver_to_controller, drivers_to_controller => drivers_to_controller,
controller_to_socbridge_driver => controller_to_socbridge_driver controller_to_drivers => controller_to_drivers
); );
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 socbridge_driver_to_controller.is_active = '1'; wait until drivers_to_controller.socbridge.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 socbridge_driver_to_controller.is_active = '0'; wait until drivers_to_controller.socbridge.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 socbridge_driver_to_controller.is_active = '1'; wait until drivers_to_controller.socbridge.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 socbridge_driver_to_controller.is_active = '0'; wait until drivers_to_controller.socbridge.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
buffer_to_socbridge_driver.is_full_in <= '0'; ip_to_socbridge_driver.is_full_in <= '0';
buffer_to_socbridge_driver.write_enable_out <= '0'; ip_to_socbridge_driver.write_enable_out <= '0';
wait for 3 * CLK_PERIOD; wait for 3 * CLK_PERIOD;
-- stimulus goes here -- stimulus goes here
buffer_to_socbridge_driver.write_enable_out <= '1'; ip_to_socbridge_driver.write_enable_out <= '1';
buffer_to_socbridge_driver.payload <= std_logic_vector(to_unsigned(input, buffer_to_socbridge_driver.payload'length)); ip_to_socbridge_driver.payload <= std_logic_vector(to_unsigned(input, ip_to_socbridge_driver.payload'length));
input := input + 1 mod 256; input := input + 1 mod 256;
wait until rising_edge(clk) and socbridge_driver_to_buffer.is_full_out = '0'; wait until rising_edge(clk) and socbridge_driver_to_ip.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
buffer_to_socbridge_driver.payload <= std_logic_vector(to_unsigned(input, buffer_to_socbridge_driver.payload'length)); ip_to_socbridge_driver.payload <= std_logic_vector(to_unsigned(input, ip_to_socbridge_driver.payload'length));
input := input + 1 mod 256; input := input + 1 mod 256;
wait until rising_edge(clk) and socbridge_driver_to_buffer.is_full_out = '0'; wait until rising_edge(clk) and socbridge_driver_to_ip.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;
socbridge_driver_to_controller : in socbridge_driver_to_controller_t; drivers_to_controller : in drivers_to_controller_t;
controller_to_socbridge_driver : out controller_to_socbridge_driver_t controller_to_drivers : out controller_to_drivers_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, socbridge_driver_to_controller, state) comb_proc: process(cpu_to_controller, drivers_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 socbridge_driver_to_controller.is_active; ored := ored or drivers_to_controller.socbridge.is_active;
end loop ready_reduction; end loop ready_reduction;
controller_to_socbridge_driver.request <= state.curr_driver; controller_to_drivers.socbridge.request <= state.curr_driver;
controller_to_socbridge_driver.address <= state.address; controller_to_drivers.socbridge.address <= state.address;
controller_to_socbridge_driver.seq_mem_access_count <= state.seq_mem_access_count; controller_to_drivers.socbridge.seq_mem_access_count <= state.seq_mem_access_count;
controller_to_cpu.ready <= state.ready; controller_to_cpu.ready <= state.ready;
controller_to_socbridge_driver.instruction <= state.instruction; controller_to_drivers.socbridge.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 socbridge_driver_to_controller: socbridge_driver_to_controller_t := (is_active => '0'); signal drivers_to_controller: drivers_to_controller_t := (socbridge => (is_active => '0'));
signal controller_to_cpu: controller_to_cpu_t; signal controller_to_cpu: controller_to_cpu_t;
signal controller_to_socbridge_driver: controller_to_socbridge_driver_t; signal controller_to_drivers: controller_to_drivers_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,
socbridge_driver_to_controller => socbridge_driver_to_controller, drivers_to_controller => drivers_to_controller,
controller_to_socbridge_driver => controller_to_socbridge_driver controller_to_drivers => controller_to_drivers
); );
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";
socbridge_driver_to_controller.is_active <= '0'; drivers_to_controller.socbridge.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;
socbridge_driver_to_controller.is_active <= '0'; drivers_to_controller.socbridge.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_socbridge_driver.request = '1' report "Incorrect driver_id from control_unit" severity error; assert controller_to_drivers.socbridge.request = '1' report "Incorrect driver_id 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.address = x"F0F0F0F0" report "Incorrect address from control_unit" severity error;
assert controller_to_socbridge_driver.instruction = WRITE report "Incorrect memory op from control_unit" severity error; assert controller_to_drivers.socbridge.instruction = WRITE report "Incorrect memory op from control_unit" severity error;
wait for 5 * cycle; wait for 5 * cycle;
reset <= '1'; reset <= '1';

1
src/ganimede/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
ganimede

View File

@ -1,24 +1,28 @@
library IEEE; library IEEE;
use IEEE.std_logic_1164.all; use IEEE.std_logic_1164.all;
library work; library ganimede;
use work.io_types.all; use ganimede.io_types.all;
library gan_socbridge;
use gan_socbridge.socbridge_driver_pkg.all;
library controller;
entity ganimede is entity ganimede_toplevel is
port ( port (
clk : in std_logic; clk : in std_logic;
reset : in std_logic; rst : in std_logic;
ext_interface_in : in ext_interface_in_t; cpu_to_ganimede : in cpu_to_controller_t;
ext_interface_out : out ext_interface_out_t; ganimede_to_cpu : out controller_to_cpu_t;
int_interface_in : in int_interface_in_t; ext_to_ganimede : in ext_to_ganimede_t;
int_interface_out : out int_interface_out_t ganimede_to_ext : out ganimede_to_ext_t;
ip_to_ganimede : in ip_to_ganimede_t;
ganimede_to_ip : out ganimede_to_ip_t
); );
end entity ganimede; end entity ganimede_toplevel;
architecture rtl of ganimede is architecture rtl of ganimede_toplevel is
--- SIGNAL DECLERATIONS --- --- SIGNAL DECLERATIONS ---
signal gan_int_interface_in : int_interface_in_t; signal drivers_to_controller : drivers_to_controller_t;
signal gan_int_interface_out : int_interface_out_t; signal controller_to_drivers : controller_to_drivers_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;
@ -38,34 +42,30 @@ architecture rtl of ganimede 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_driver_inst: socbridge_driver socbridge_inst: entity gan_socbridge.socbridge_driver
port map( port map(
clk => clk, clk => clk,
reset => reset, rst => rst,
ext_in => gan_ext_interface_in.socbridge, controller_to_socbridge_driver => controller_to_drivers.socbridge,
ext_out => gan_ext_interface_out.socbridge, socbridge_driver_to_controller => drivers_to_controller.socbridge,
int_in => gan_int_interface_in.socbridge, ext_to_socbridge_driver => ext_to_ganimede.socbridge,
int_out => gan_int_interface_out.socbridge socbridge_driver_to_ext => ganimede_to_ext.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

@ -0,0 +1,215 @@
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,64 +5,52 @@ 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 seq_vector_length: natural := 8; constant inst_word_width : natural := 2;
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);
@ -73,30 +61,38 @@ 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_buffer_t is record type socbridge_driver_to_ip_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_buffer_t; end record socbridge_driver_to_ip_t;
type buffer_to_socbridge_driver_t is record type ip_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 buffer_to_socbridge_driver_t; end record ip_to_socbridge_driver_t;
type ext_interface_in_t is record type controller_to_drivers_t is record
socbridge : ext_to_socbridge_driver_t; socbridge : controller_to_socbridge_driver_t;
end record ext_interface_in_t; end record controller_to_drivers_t;
type ext_interface_out_t is record type drivers_to_controller_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 ext_interface_out_t; end record ganimede_to_ext_t;
type int_interface_out_t is record type ganimede_to_ip_t is record
socbridge : socbridge_driver_to_buffer_t; socbridge : socbridge_driver_to_ip_t;
end record int_interface_out_t; end record ganimede_to_ip_t;
type int_interface_in_t is record type ip_to_ganimede_t is record
socbridge : buffer_to_socbridge_driver_t; socbridge : ip_to_socbridge_driver_t;
end record int_interface_in_t; end record ip_to_ganimede_t;
end package io_types; end package io_types;

185
src/gantry.toml Normal file
View File

@ -0,0 +1,185 @@
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,11 +3,14 @@ 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 socbridge; library gan_socbridge;
use socbridge.socbridge_driver_tb_pkg.all; use gan_socbridge.socbridge_driver_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;
@ -15,8 +18,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;
socbridge_driver_to_buffer : out socbridge_driver_to_buffer_t; ip_to_socbridge_driver : in ip_to_socbridge_driver_t;
buffer_to_socbridge_driver : in buffer_to_socbridge_driver_t socbridge_driver_to_ip : out socbridge_driver_to_ip_t
); );
end entity socbridge_driver; end entity socbridge_driver;
@ -24,230 +27,246 @@ 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;
shared variable socbridge_driver_to_ext_data_cmd : std_logic_vector(interface_inst.socbridge.payload_width - 1 downto 0); signal next_data_out : std_logic_vector(interface_inst.socbridge.payload_width - 1 downto 0);
signal test : std_logic_vector(interface_inst.socbridge.payload_width - 1 downto 0); signal next_rx_transaction : transaction_t;
signal next_cmd : command_t; signal next_tx_transaction : transaction_t;
signal next_cmd_size : integer; signal next_tx_data_size, next_rx_data_size : integer;
signal next_state : state_t; signal next_rx_state : rx_state_t;
signal curr_cmd_bits : std_logic_vector(4 downto 0); signal next_tx_state : tx_state_t;
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);
-- Helpful Bindings -- comb_proc: process(ext_to_socbridge_driver, ip_to_socbridge_driver,
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 st, controller_to_socbridge_driver, trans_st,
-- Not sure that the two process method is helping here: if this was a normal tx_sent_response, rx_received_response)
-- signal assignment there would be no confusion. variable curr_response_bits : std_logic_vector(4 downto 0);
-- in the case ... <= ext_to_socbridge_driver_rec we get variable local_next_rx_transaction : transaction_t;
-- curr_resp | ext_to_socbridge_driver_rec | ext_to_socbridge_driver variable local_next_tx_transaction : transaction_t;
-- 00000 | 00000000 | 00001001 variable local_next_data_out : std_logic_vector(interface_inst.socbridge.payload_width - 1 downto 0);
-- 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
-- Outputs -- Helpful Bindings --
socbridge_driver_to_ext <= create_io_type_out_from_ext_protocol(st.socbridge_driver_to_ext_reg); next_rx_data_size <= 2 ** to_integer(unsigned(ext_to_socbridge_driver.payload(2 downto 0)));
with trans_st.curr_state select curr_response_bits := ext_to_socbridge_driver.payload(7 downto 3);
socbridge_driver_to_controller.is_active <= '0' when IDLE, -- Set helper var to current transaction seen at the input.
'1' when others; local_next_rx_transaction := NO_OP;
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;
--- State Transition Diagram --- --- Next State Assignments ---
-- --- ### 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
-- IDLE<-------------------+ next_tx_state <= 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 =>
-- The header only takes one word (cycle) to transmit. -- Commands
-- Continue to body or address directly afterwards. if st.curr_tx_transaction = WRITE_ADD or st.curr_tx_transaction = READ_ADD then
if st.curr_cmd = WRITE_ADD then next_tx_state <= ADDR1;
next_state <= ADDR1; elsif st.curr_tx_transaction = WRITE then
else next_tx_state <= TX_W_BODY;
next_state <= TX_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; end if;
when TX_BODY => when TX_R_BODY =>
-- Here we want to stay in TX_BODY for the duration of a packet. if st.tx_stage <= 1 then
if st.write_stage = 0 then next_tx_state <= IDLE;
next_state <= TX_ACK;
else else
next_state <= TX_BODY; next_tx_state <= TX_R_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 =>
-- Transmits the entire address and returns to the appropriate next_tx_state <= ADDR2;
next_state <= ADDR2;
when ADDR2 => when ADDR2 =>
next_state <= ADDR3; next_tx_state <= ADDR3;
when ADDR3 => when ADDR3 =>
next_state <= ADDR4; next_tx_state <= ADDR4;
when ADDR4 => when ADDR4 =>
if st.curr_cmd = WRITE or st.curr_cmd = WRITE_ADD then if st.curr_tx_transaction = READ_ADD then
next_state <= TX_BODY; next_tx_state <= TX_AWAIT;
elsif st.curr_tx_transaction = WRITE_ADD then
next_tx_state <= TX_W_BODY;
else else
next_state <= RX_RESPONSE; next_tx_state <= IDLE;
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 ---
--- Combinatorial output based on current state --- case st.curr_rx_state is
socbridge_driver_to_ext_data_cmd := (others => '0');
socbridge_driver_to_buffer.is_full_out <= '1';
socbridge_driver_to_buffer.write_enable_in <= '0';
socbridge_driver_to_buffer.payload <= (others => '0');
case st.curr_state is
when IDLE => when IDLE =>
if st.curr_cmd = WRITE or st.curr_cmd = WRITE_ADD then if local_next_rx_transaction /= NO_OP then
socbridge_driver_to_ext_data_cmd := get_cmd_bits(st.curr_cmd) & get_size_bits(st.curr_cmd_size); next_rx_state <= RX_HEADER;
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 else
end if; next_rx_state <= IDLE;
when TX_HEADER =>
if st.curr_cmd = WRITE_ADD then
socbridge_driver_to_ext_data_cmd := st.curr_addr(7 downto 0);
else
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_BODY =>
if st.write_stage > 0 then
socbridge_driver_to_buffer.is_full_out <= '0';
socbridge_driver_to_ext_data_cmd := buffer_to_socbridge_driver.payload;
else
socbridge_driver_to_ext_data_cmd := (others => '0');
end if;
when TX_ACK =>
when RX_HEADER => when RX_HEADER =>
if st.curr_cmd = READ_ADD then -- Commands
socbridge_driver_to_ext_data_cmd := st.curr_addr(7 downto 0); if st.curr_rx_transaction = WRITE_ADD or st.curr_rx_transaction = READ_ADD then
end if; next_rx_state <= ADDR1;
when RX_RESPONSE => elsif st.curr_rx_transaction = WRITE then
when RX_BODY => next_rx_state <= RX_W_BODY;
socbridge_driver_to_buffer.payload <= st.ext_to_socbridge_driver_reg.data; elsif st.curr_rx_transaction = READ then
socbridge_driver_to_buffer.write_enable_in <= '1'; 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 => when ADDR1 =>
socbridge_driver_to_ext_data_cmd := st.curr_addr(15 downto 8); next_rx_state <= ADDR2;
when ADDR2 => when ADDR2 =>
socbridge_driver_to_ext_data_cmd := st.curr_addr(23 downto 16); next_rx_state <= ADDR3;
when ADDR3 => when ADDR3 =>
socbridge_driver_to_ext_data_cmd := st.curr_addr(31 downto 24); next_rx_state <= ADDR4;
when ADDR4 => when ADDR4 =>
if st.curr_cmd = WRITE_ADD then if st.curr_rx_transaction = READ_ADD then
socbridge_driver_to_buffer.is_full_out <= '0'; next_rx_state <= RX_AWAIT;
socbridge_driver_to_ext_data_cmd := buffer_to_socbridge_driver.payload; elsif st.curr_rx_transaction = WRITE_ADD then
report integer'image(to_integer(signed(socbridge_driver_to_ext_data_cmd))) & " "& integer'image(to_integer(signed(buffer_to_socbridge_driver.payload))); 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 if;
end case; end case;
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 ---
--- Combinatorial output based on current state ---
local_next_data_out := (others => '0');
socbridge_driver_to_ip.is_full_out <= '1';
socbridge_driver_to_ip.write_enable_in <= '0';
socbridge_driver_to_ip.payload <= (others => '0');
--- ### TX_STATE BASED OUTPUT ### ---
case st.curr_tx_state is
when IDLE =>
when TX_HEADER =>
if st.curr_tx_transaction = WRITE_ACK or st.curr_tx_transaction = READ_RESPONSE then
local_next_data_out := get_header_bits(st.curr_tx_transaction, st.curr_rx_transaction) & get_size_bits(st.rx_data_size);
else
local_next_data_out := get_header_bits(st.curr_tx_transaction, st.curr_rx_transaction) & get_size_bits(st.tx_data_size);
end if;
when TX_W_BODY =>
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_R_BODY =>
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_W_BODY =>
-- TODO Add output signals to management unit later
-- TODO REPLACE TWO BELOW
socbridge_driver_to_ip.payload <= st.ext_to_socbridge_driver_reg.data;
socbridge_driver_to_ip.write_enable_in <= '1';
when RX_R_BODY =>
socbridge_driver_to_ip.payload <= st.ext_to_socbridge_driver_reg.data;
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 ADDR2 =>
when ADDR3 =>
when ADDR4 =>
end case;
next_parity_out <= calc_parity(local_next_data_out);
--- TRANSLATOR ---
--- Next state assignment --- Next state assignment
case trans_st.curr_state is case trans_st.curr_state is
when IDLE => when IDLE =>
@ -258,7 +277,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_state /= IDLE then if st.curr_tx_state /= IDLE then
trans_next_state <= SEND_ACCEPTED; trans_next_state <= SEND_ACCEPTED;
else else
trans_next_state <= SEND; trans_next_state <= SEND;
@ -268,45 +287,56 @@ 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_state = IDLE then if trans_st.curr_inst.seq_mem_access_count <= 0 and st.curr_tx_state = IDLE then
trans_next_state <= IDLE; trans_next_state <= IDLE;
elsif st.curr_state = IDLE then elsif st.curr_tx_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;
--- Combinatorial output based on state --- NEXT TX TRANSACTION ---
next_cmd <= NO_OP; local_next_tx_transaction := NO_OP;
next_cmd_size <= 0; next_tx_data_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
next_cmd <= READ_ADD; local_next_tx_transaction := READ_ADD;
elsif trans_st.curr_inst.instruction = WRITE then elsif trans_st.curr_inst.instruction = WRITE then
next_cmd <= WRITE_ADD; local_next_tx_transaction := WRITE_ADD;
end if; end if;
else else
if trans_st.curr_inst.instruction = READ then if trans_st.curr_inst.instruction = READ then
next_cmd <= READ; local_next_tx_transaction := READ;
elsif trans_st.curr_inst.instruction = WRITE then elsif trans_st.curr_inst.instruction = WRITE then
next_cmd <= WRITE; local_next_tx_transaction := WRITE;
end if; end if;
end if; end if;
if trans_st.curr_inst.seq_mem_access_count > 128 then if trans_st.curr_inst.seq_mem_access_count > MAX_PKT_SIZE then
next_cmd_size <= 128; next_tx_data_size <= MAX_PKT_SIZE;
elsif trans_st.curr_inst.seq_mem_access_count > 0 then elsif trans_st.curr_inst.seq_mem_access_count > 0 then
next_cmd_size <= trans_st.curr_inst.seq_mem_access_count; next_tx_data_size <= trans_st.curr_inst.seq_mem_access_count;
else else
next_cmd_size <= 0; next_tx_data_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)
@ -316,47 +346,79 @@ 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_state <= IDLE; st.curr_tx_state <= IDLE;
st.write_stage <= 0; st.curr_rx_state <= IDLE;
st.read_stage <= 0; st.tx_stage <= 0;
st.curr_cmd <= NO_OP; st.rx_stage <= 0;
st.curr_cmd_size <= 0; st.curr_tx_transaction <= NO_OP;
st.curr_addr <= (others => '0'); st.curr_rx_transaction <= NO_OP;
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 <= socbridge_driver_to_ext_data_cmd; st.socbridge_driver_to_ext_reg.data <= next_data_out;
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_state <= next_state; st.curr_tx_state <= next_tx_state;
case st.curr_state is st.curr_rx_state <= next_rx_state;
case st.curr_tx_state is
when IDLE => when IDLE =>
st.curr_cmd <= next_cmd; st.curr_tx_transaction <= next_tx_transaction;
st.curr_cmd_size <= next_cmd_size; st.tx_data_size <= next_tx_data_size;
st.curr_addr <= trans_st.curr_inst.address; st.curr_tx_addr <= trans_st.curr_inst.address;
if next_cmd_size > 0 then if next_tx_transaction = WRITE_ADD or next_tx_transaction = WRITE
st.write_stage <= next_cmd_size - 1; or next_tx_transaction = READ_RESPONSE then
st.read_stage <= next_cmd_size - 1; st.tx_stage <= next_tx_data_size;
else
st.tx_stage <= 0;
end if; end if;
when TX_HEADER => when TX_W_BODY =>
when TX_BODY => if st.tx_stage > 0 then
if st.write_stage > 0 then st.tx_stage <= st.tx_stage - 1;
st.write_stage <= st.write_stage - 1;
end if; end if;
when TX_ACK => when TX_R_BODY =>
st.curr_cmd <= NO_OP; if st.tx_stage > 0 then
st.curr_cmd_size <= 0; st.tx_stage <= st.tx_stage - 1;
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;
@ -381,9 +443,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 - 128; trans_st.curr_inst.seq_mem_access_count <= trans_st.curr_inst.seq_mem_access_count - MAX_PKT_SIZE;
when AWAIT => when AWAIT =>
if trans_st.curr_inst.seq_mem_access_count <= 0 and st.curr_state = IDLE then if trans_st.curr_inst.seq_mem_access_count <= 0 and st.curr_tx_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

@ -6,20 +6,19 @@ library ganimede;
use ganimede.io_types.all; use ganimede.io_types.all;
package socbridge_driver_tb_pkg is package socbridge_driver_pkg is
subtype command_size_t is integer range 0 to 128; subtype command_size_t is integer range 0 to 128;
type command_t is type transaction_t is
(NO_OP, WRITE_ADD, WRITE, READ_ADD, READ, P_ERR); (NO_OP, WRITE_ADD, WRITE, READ_ADD, READ, P_ERR, WRITE_ACK, READ_RESPONSE);
type response_t is type rx_state_t is
(NO_OP, WRITE_ACK, READ_RESPONSE); (IDLE, ADDR1, ADDR2, ADDR3, ADDR4, RX_AWAIT,
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);
@ -27,7 +26,7 @@ package socbridge_driver_tb_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);
@ -36,12 +35,17 @@ package socbridge_driver_tb_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_state: state_t; curr_rx_transaction : transaction_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;
write_stage, read_stage : NATURAL; tx_stage, rx_stage : NATURAL;
curr_cmd : command_t; tx_data_size, rx_data_size : integer;
curr_cmd_size: integer; curr_write_data : std_logic_vector(31 downto 0);
curr_addr : std_logic_vector(31 downto 0); curr_read_data : 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)
@ -50,26 +54,13 @@ package socbridge_driver_tb_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_cmd_bits(command : command_t) return std_logic_vector; pure function get_header_bits(transaction : transaction_t; caused_by: transaction_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_tb_pkg; end package socbridge_driver_pkg;
package body socbridge_driver_tb_pkg is package body socbridge_driver_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;
@ -105,18 +96,33 @@ package body socbridge_driver_tb_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
with command select val := "11111";
val := "00000" when NO_OP, if transaction = NO_OP then
"10000" when WRITE_ADD, val := "00000";
"10100" when WRITE, elsif transaction = WRITE_ADD then
"11000" when READ_ADD, val := "10000";
"11100" when READ, elsif transaction = WRITE then
"01001" when P_ERR, val := "10100";
"11111" when others; elsif transaction = READ_ADD then
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;
@ -153,4 +159,4 @@ package body socbridge_driver_tb_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_tb_pkg; end package body socbridge_driver_pkg;

View File

@ -1,11 +1,12 @@
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_tb_pkg.all; use work.socbridge_driver_pkg.all;
library ganimede; library ganimede;
use ganimede.io_types.all; use ganimede.io_types.all;
library socbridge; library gan_socbridge;
entity socbridge_driver_tb is entity socbridge_driver_tb is
@ -14,319 +15,95 @@ 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 buffer_to_socbridge_driver : buffer_to_socbridge_driver_t; signal ip_to_socbridge_driver : ip_to_socbridge_driver_t;
signal socbridge_driver_to_buffer : socbridge_driver_to_buffer_t; signal socbridge_driver_to_ip : socbridge_driver_to_ip_t;
signal controller_to_socbridge_driver : controller_to_socbridge_driver_t; signal controller_to_socbridge_driver : controller_to_socbridge_driver_t;
signal socbridge_driver_controller : socbridge_driver_to_controller_t; signal socbridge_driver_to_controller : socbridge_driver_to_controller_t;
signal curr_word : std_logic_vector(ext_to_socbridge_driver.payload'length - 1 downto 0); shared variable done : boolean := FALSE;
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 SIMULATION_CYCLE_COUNT : INTEGER := 100; constant MAX_CYCLE_COUNT : INTEGER := 1000000;
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 socbridge.socbridge_driver socbridge_driver_inst: entity gan_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_controller, 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,
buffer_to_socbridge_driver => buffer_to_socbridge_driver, ip_to_socbridge_driver => ip_to_socbridge_driver,
socbridge_driver_to_buffer => socbridge_driver_to_buffer socbridge_driver_to_ip => socbridge_driver_to_ip
); );
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
for x in 0 to SIMULATION_CYCLE_COUNT*2 loop while (not done) and (cycle_count < MAX_CYCLE_COUNT) 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
cmd <= NO_OP; controller_to_socbridge_driver.instruction <= NO_OP;
cmd_size <= 2; controller_to_socbridge_driver.seq_mem_access_count <= 0;
wait for 3*CLK_PERIOD; controller_to_socbridge_driver.request <= '0';
wait for CLK_PERIOD / 2; controller_to_socbridge_driver.address <= x"00000000";
cmd <= WRITE; wait until rst='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 <= WRITE_ADD; controller_to_socbridge_driver.instruction <= WRITE;
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 for CLK_PERIOD * 10; wait until socbridge_driver_to_controller.is_active = '1';
cmd <= READ; controller_to_socbridge_driver.request <= '0';
wait for CLK_PERIOD; wait until socbridge_driver_to_controller.is_active = '0';
cmd <= NO_OP; for i in 100 downto 0 loop
wait for CLK_PERIOD * 10; wait until rising_edge(clk);
cmd <= READ_ADD; end loop;
address <= x"FA0FA0FA"; controller_to_socbridge_driver.instruction <= READ;
wait for CLK_PERIOD; controller_to_socbridge_driver.seq_mem_access_count <= 128;
cmd <= NO_OP; controller_to_socbridge_driver.address <= x"40000000";
address <= (others => '0'); wait until rising_edge(clk);
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;
external_stimulus_signal: process(curr_word)
begin
ext_to_socbridge_driver.payload <= curr_word;
ext_to_socbridge_driver.control(0) <= calc_parity(curr_word);
end process external_stimulus_signal;
external_stimulus: process
begin
rst <= '0';
wait for CLK_PERIOD / 1000;
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 internal_stimulus: process
variable count : integer := 1;
begin begin
buffer_to_socbridge_driver.is_full_in <= '0'; ip_to_socbridge_driver.is_full_in <= '0';
buffer_to_socbridge_driver.write_enable_out <= '0'; ip_to_socbridge_driver.write_enable_out <= '0';
wait for 3 * CLK_PERIOD; wait until rst = '0';
-- stimulus goes here -- stimulus goes here
buffer_to_socbridge_driver.write_enable_out <= '1';
buffer_to_socbridge_driver.payload <= "00000001"; while not done loop
wait until rising_edge(clk) and socbridge_driver_to_buffer.is_full_out = '0'; 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';
wait until falling_edge(clk); ip_to_socbridge_driver.payload <= std_logic_vector(to_unsigned(count, 8));
buffer_to_socbridge_driver.payload <= "00000010"; count := count + 1;
wait until rising_edge(clk) and socbridge_driver_to_buffer.is_full_out = '0'; end loop;
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

@ -3,15 +3,25 @@ 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'
] ]
socbridge.files = [ gan_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