Compare commits

..

15 Commits

Author SHA1 Message Date
545d1ed4da Restored gtkwave file for socbridge driver testbench 2025-04-08 14:36:21 +02:00
dea3036a13 Fixed some bugs and made manager compatible with byte addressing 2025-04-08 14:33:01 +02:00
47b6529523 Created testbench for management unit but it does not work correctly yet 2025-04-07 17:59:01 +02:00
15cc7c6000 Renamed some types 2025-04-07 15:04:43 +02:00
70275f624a first version of management unit done 2025-04-07 15:04:15 +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
27 changed files with 1423 additions and 383 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_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_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

@ -8,10 +8,10 @@ entity control_unit is
port ( port (
clk, rst : in std_logic; clk, rst : in std_logic;
cpu_to_controller : in cpu_to_controller_t; manager_to_controller : in manager_to_controller_t;
controller_to_cpu : out controller_to_cpu_t; controller_to_manager : out controller_to_manager_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(manager_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_manager.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)
@ -56,10 +56,10 @@ begin
else else
state.ready <= not ored; state.ready <= not ored;
if ored = '0' then if ored = '0' then
state.address <= cpu_to_controller.address; state.address <= manager_to_controller.address;
state.seq_mem_access_count <= cpu_to_controller.seq_mem_access_count; state.seq_mem_access_count <= manager_to_controller.seq_mem_access_count;
state.curr_driver <= cpu_to_controller.driver_id(0); state.curr_driver <= manager_to_controller.driver_id(0);
with cpu_to_controller.cmd select with manager_to_controller.cmd select
state.instruction <= WRITE when "01", state.instruction <= WRITE when "01",
READ when "10", READ when "10",
NO_OP when others; NO_OP when others;

View File

@ -14,14 +14,14 @@ architecture tb of control_unit_tb is
constant cycle: Time := 10 ns; constant cycle: Time := 10 ns;
signal clock: std_logic := '0'; signal clock: std_logic := '0';
signal reset: std_logic := '0'; signal reset: std_logic := '0';
signal cpu_to_controller: cpu_to_controller_t := ( signal manager_to_controller: manager_to_controller_t := (
(others => '0'), (others => '0'),
(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_manager: controller_to_manager_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;
@ -40,21 +40,21 @@ begin
port map( port map(
clk => clock, clk => clock,
rst => reset, rst => reset,
cpu_to_controller => cpu_to_controller, manager_to_controller => manager_to_controller,
controller_to_cpu => controller_to_cpu, controller_to_manager => controller_to_manager,
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
begin begin
wait for cycle; wait for cycle;
cpu_to_controller.driver_id <= "1"; manager_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"; manager_to_controller.address <= x"F0F0F0F0";
cpu_to_controller.seq_mem_access_count <= 3; manager_to_controller.seq_mem_access_count <= 3;
cpu_to_controller.cmd <= "01"; manager_to_controller.cmd <= "01";
word_counter := 3; word_counter := 3;
wait for cycle; wait for cycle;
current_driver <= "1"; current_driver <= "1";
@ -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';

View File

@ -1,24 +1,32 @@
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_tb_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; manager_to_ganimede : in manager_to_controller_t;
ext_interface_out : out ext_interface_out_t; ganimede_to_manager : out controller_to_manager_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 ext_to_drivers : ext_to_ganimede_t;
signal gan_int_interface_out : int_interface_out_t; signal drivers_to_ext : ganimede_to_ext_t;
signal gan_ext_interface_in : ext_interface_in_t; signal drivers_to_ip : ganimede_to_ip_t;
signal gan_ext_interface_out : ext_interface_out_t; signal ip_to_drivers : ip_to_ganimede_t;
signal drivers_to_controller : drivers_to_controller_t;
signal controller_to_drivers : controller_to_drivers_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 +46,34 @@ 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; ip_to_drivers <= ip_to_ganimede;
int_interface_out <= gan_int_interface_out; ganimede_to_ip <= drivers_to_ip;
gan_ext_interface_in <= ext_interface_in; ext_to_drivers <= ext_to_ganimede;
ext_interface_out <= gan_ext_interface_out; ganimede_to_ext <= drivers_to_ext;
--- 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,
manager_to_controller => manager_to_ganimede,
controller_to_manager => ganimede_to_manager,
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_tb_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,57 +5,34 @@ 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 manager_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); --Noop: 00; Write: 01; Read: 10
end record cpu_to_controller_t; end record manager_to_controller_t;
type controller_to_cpu_t is record type controller_to_manager_t is record
ready: std_logic; ready : std_logic;
end record controller_to_cpu_t; end record controller_to_manager_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 := (
@ -63,6 +40,17 @@ package io_types is
); );
--- 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 : controller_to_socbridge_driver_t;
end record controller_to_drivers_t;
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; socbridge : ext_to_socbridge_driver_t;
end record ext_interface_in_t; end record ext_to_ganimede_t;
type ext_interface_out_t is record 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;

189
src/gantry.toml Normal file
View File

@ -0,0 +1,189 @@
title = "ganimede"
createdAt = "2025-03-14"
maintainer = ""
email = ""
version = "0.0.1"
[libraries.gan_socbridge]
vhdl-version = "93c"
path = "socbridge"
[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.manager]
vhdl-version = "93c"
path = "manager"

View File

@ -0,0 +1,86 @@
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.MATH_REAL.all;
use ieee.numeric_std.all;
library manager;
use manager.management_types.all;
library ganimede;
use ganimede.io_types.all;
entity management_unit is
port (
clk, rst : in std_logic;
manager_to_controller : out manager_to_controller_t;
controller_to_manager : in controller_to_manager_t;
socbridge_driver_to_manager : in socbridge_driver_to_manager_t;
manager_to_socbridge_driver : out manager_to_socbridge_driver_t
);
end entity management_unit;
architecture rtl of management_unit is
signal manager_state : manager_state_t;
signal write_address : manager_word_t;
signal read_address : manager_word_t;
signal msg_size : manager_word_t;
-- Address indexing whole words, not bytes
signal word_address : natural;
begin
word_address <= to_integer(shift_right(unsigned(socbridge_driver_to_manager.address), address_shift));
read_address <= manager_state.memory(word_address);
write_address <= manager_state.memory(word_address);
comb_proc: process(controller_to_manager, socbridge_driver_to_manager)
begin
-- Read data from manager to SoCBridge driver
manager_to_socbridge_driver.ready <= '1';
manager_to_socbridge_driver.data <= manager_state.memory(word_address);
manager_to_socbridge_driver.valid <= '1';
end process comb_proc;
-- tre sorters sätt att avsluta en skrivning:
-- timeout om vi villha det
-- en lastbit genooom axi interface
-- vi har fått all data vi begärde.
seq_proc: process(clk)
begin
if rising_edge(clk) then
if rst = '1' then
manager_state <= manager_state_reset_val;
else
-- Write data from SoCBridge driver to address
if socbridge_driver_to_manager.valid = '1' then
manager_state.memory(word_address) <= socbridge_driver_to_manager.data;
if socbridge_driver_to_manager.address = read_address_index
or socbridge_driver_to_manager.address = write_address_index then
-- CLEAR BUFFER TO IP CORE
end if;
end if;
-- Is there a read instruction in memory
if read_address /= empty_word and controller_to_manager.ready = '1' then
manager_to_controller.address <= read_address;
manager_to_controller.driver_id <= "1"; -- Only supprts one driver at present
manager_to_controller.seq_mem_access_count <= to_integer(unsigned(msg_size));
manager_to_controller.cmd <= "10";
-- Is there a write instruction in memory
elsif write_address /= empty_word and controller_to_manager.ready = '1' then
manager_to_controller.address <= write_address;
manager_to_controller.driver_id <= "1"; -- Only supports one driver at present
manager_to_controller.seq_mem_access_count <= to_integer(unsigned(msg_size));
manager_to_controller.cmd <= "01";
else
-- No instruction present in memory, all zeroes to control unit
manager_to_controller.address <= (others => '0');
manager_to_controller.driver_id <= "0"; -- Only supprts one driver at present
manager_to_controller.seq_mem_access_count <= 0;
manager_to_controller.cmd <= "00";
end if;
end if;
end if;
end process seq_proc;
end architecture rtl ;

View File

@ -0,0 +1,45 @@
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.MATH_REAL.all;
library ganimede;
use ganimede.io_types.all;
package management_types is
constant WORD_SIZE : natural := 32;
-- Amount to right shift addres to convert e.g 0x00000004 to 0x00000001 for 32-bit words
constant address_shift : natural := natural(FLOOR(LOG2(real(WORD_SIZE) / real(8))));
subtype manager_word_t is std_logic_vector(WORD_SIZE - 1 downto 0);
constant empty_word : std_logic_vector(WORD_SIZE - 1 downto 0) := (others => '0');
constant mem_words : natural := 64;
type memory_t is array (0 to mem_words - 1) of manager_word_t;
-- Index in memory array where memory read address is kept.
-- Read is active while it is not all zero.
constant read_address_index : std_logic_vector(WORD_SIZE - 1 downto 0) := x"00000000";
-- Index in memory array where memory write address is kept.
-- Write is active while it is not all zero. Mutex with read address
constant write_address_index : std_logic_vector(WORD_SIZE - 1 downto 0) := x"00000001";
constant access_size : std_logic_vector(WORD_SIZE - 1 downto 0) := x"00000002";
-- Status register for debugging
type manager_state_t is record
memory : memory_t;
data_out : manager_word_t;
end record manager_state_t;
-- reset value of status register
constant manager_state_reset_val : manager_state_t := ((others => (others => '0')), x"00000000");
type socbridge_driver_to_manager_t is record
address : manager_word_t;
data : manager_word_t;
valid: std_logic;
end record socbridge_driver_to_manager_t;
type manager_to_socbridge_driver_t is record
data : manager_word_t;
valid : std_logic;
ready : std_logic;
end record manager_to_socbridge_driver_t;
end package;

View File

@ -0,0 +1,124 @@
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.MATH_REAL.all;
use IEEE.numeric_std.all;
library ganimede;
use ganimede.io_types.all;
library manager;
use manager.management_types.all;
entity management_unit_tb is
end entity management_unit_tb;
architecture tb of management_unit_tb is
signal clk : std_logic := '0';
signal rst : std_logic;
signal manager_to_controller : manager_to_controller_t;
signal controller_to_manager : controller_to_manager_t := (ready => '0');
signal socbridge_driver_to_manager : socbridge_driver_to_manager_t := (
address => (others => '0'),
data => (others => '0'),
valid => '0'
);
signal manager_to_socbridge_driver : manager_to_socbridge_driver_t;
constant halfcycle: Time := 5 ns;
constant cycle: Time := 2 * halfcycle;
function to_string ( a: std_logic_vector) return string is
variable b : string (1 to a'length) := (others => NUL);
variable stri : integer := 1;
begin
for i in a'range loop
b(stri) := std_logic'image(a((i)))(2);
stri := stri+1;
end loop;
return b;
end function;
begin
clock_proc: process
begin
for i in 0 to 50 loop
wait for halfcycle;
clk <= not clk;
end loop;
wait;
end process clock_proc;
management_unit_inst: entity manager.management_unit
port map(
clk => clk,
rst => rst,
manager_to_controller => manager_to_controller,
controller_to_manager => controller_to_manager,
socbridge_driver_to_manager => socbridge_driver_to_manager,
manager_to_socbridge_driver => manager_to_socbridge_driver
);
tb_proc: process
begin
controller_to_manager.ready <= '0';
rst <= '1';
wait for cycle;
rst <= '0';
report "Testing write to 0x00000014";
socbridge_driver_to_manager.data <= x"FA0FA0FA";
socbridge_driver_to_manager.address <= x"00000014";
socbridge_driver_to_manager.valid <= '1';
wait for cycle;
socbridge_driver_to_manager.valid <= '0';
socbridge_driver_to_manager.data <= x"00000000";
socbridge_driver_to_manager.address <= x"00000000";
wait for halfcycle;
assert manager_to_socbridge_driver.data = x"FA0FA0FA" report "Write to address 0x00000005 failed! expected 0xFA0FA0FA but got " & natural'image(to_integer(unsigned(manager_to_socbridge_driver.data))) severity error;
wait for 5 * cycle;
report "Testing submission of write instruction of 10 words to address 0x40000000";
controller_to_manager.ready <= '1';
socbridge_driver_to_manager.data <= x"40000000";
socbridge_driver_to_manager.address <= x"00000004";
socbridge_driver_to_manager.valid <= '1';
wait for cycle;
socbridge_driver_to_manager.data <= x"0000000A";
socbridge_driver_to_manager.address <= x"00000008";
socbridge_driver_to_manager.address <= x"00000000";
socbridge_driver_to_manager.valid <= '1';
wait for cycle;
socbridge_driver_to_manager.valid <= '0';
socbridge_driver_to_manager.data <= x"00000000";
wait for cycle;
controller_to_manager.ready <= '1';
wait for halfcycle;
assert manager_to_controller.address = x"40000000" report "Controller got the wrong address! Expected 0x40000000 but got " & to_string(manager_to_controller.address) severity error;
assert manager_to_controller.cmd = "10" report "Controller got the wrong command! Expected 0b10 but got " & to_string(manager_to_controller.cmd) severity error;
assert manager_to_controller.seq_mem_access_count = 10 report "Controller got the wrong message size! expected 10 but got " & natural'image(manager_to_controller.seq_mem_access_count) severity error;
wait for 5 * cycle;
controller_to_manager.ready <= '0';
report "Testing submission of read instruction of 20 words from address 0x50000000";
socbridge_driver_to_manager.data <= x"50000000";
socbridge_driver_to_manager.address <= x"00000000";
socbridge_driver_to_manager.valid <= '1';
wait for cycle;
socbridge_driver_to_manager.data <= x"00000014";
socbridge_driver_to_manager.address <= x"00000008";
socbridge_driver_to_manager.valid <= '1';
wait for cycle;
socbridge_driver_to_manager.valid <= '0';
socbridge_driver_to_manager.address <= x"00000000";
socbridge_driver_to_manager.data <= x"00000000";
controller_to_manager.ready <= '1';
wait for halfcycle;
assert manager_to_controller.address = x"50000000" report "Controller got the wrong address! Expected 0x50000000 but got " & to_string(manager_to_controller.address) severity error;
assert manager_to_controller.cmd = "01" report "Controller got the wrong command! Expected 0b01 but got " & to_string(manager_to_controller.cmd) severity error;
assert manager_to_controller.seq_mem_access_count = 20 report "Controller got the wrong message size! expected 20 but got " & natural'image(manager_to_controller.seq_mem_access_count) severity error;
wait;
end process tb_proc;
end architecture tb ;

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_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;
@ -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;
@ -25,12 +28,13 @@ 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); shared variable socbridge_driver_to_ext_data_cmd : std_logic_vector(interface_inst.socbridge.payload_width - 1 downto 0);
shared variable next_rx_transaction : transaction_t;
shared variable next_tx_transaction : transaction_t;
signal test : 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_cmd : command_t;
signal next_cmd_size : integer; signal next_cmd_size : integer;
signal next_state : state_t; signal next_rx_state : rx_state_t;
signal next_tx_state : tx_state_t;
signal curr_cmd_bits : std_logic_vector(4 downto 0); 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 curr_response_bits : std_logic_vector(4 downto 0);
signal st : state_rec_t; signal st : state_rec_t;
--- TRANSLATOR --- --- TRANSLATOR ---
@ -41,10 +45,8 @@ begin
-- synthesis translate_off -- synthesis translate_off
G_next_parity_out <= next_parity_out; G_next_parity_out <= next_parity_out;
G_ext_to_socbridge_driver_rec <= ext_to_socbridge_driver_rec; 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_socbridge_driver_to_ext_data_cmd <=test;
G_curr_command_bits <= curr_cmd_bits; G_curr_command_bits <= curr_cmd_bits;
G_curr_response <= curr_response;
G_curr_response_bits <= curr_response_bits; G_curr_response_bits <= curr_response_bits;
G_st <= st; G_st <= st;
G_trans_st <= trans_st; G_trans_st <= trans_st;
@ -71,175 +73,224 @@ begin
-- 00001 | 00001001 | 00001001 -- 00001 | 00001001 | 00001001
-- 00001 | 00001001 | 00001001 -- 00001 | 00001001 | 00001001
with curr_response_bits select comb_proc: process(ext_to_socbridge_driver, ip_to_socbridge_driver, st, controller_to_socbridge_driver, trans_st)
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 -- Outputs
socbridge_driver_to_ext <= create_io_type_out_from_ext_protocol(st.socbridge_driver_to_ext_reg); socbridge_driver_to_ext <= create_io_type_out_from_ext_protocol(st.socbridge_driver_to_ext_reg);
with trans_st.curr_state select
socbridge_driver_to_controller.is_active <= '0' when IDLE,
'1' when others;
--- State Transition Diagram --- -- Set helper var to current transaction seen at the input.
-- next_rx_transaction := NO_OP;
-- if curr_response_bits = "10000" then
-- next_rx_transaction := WRITE_ADD;
-- +-----+ elsif curr_response_bits = "10100" then
-- | | next_rx_transaction := WRITE;
-- \|/ /--+ elsif curr_response_bits = "11000" then
-- IDLE<-------------------+ next_rx_transaction := READ_ADD;
-- / \ | elsif curr_response_bits = "11100" then
-- / \ | next_rx_transaction := READ;
-- / \ | elsif curr_response_bits = "01001" then -- TODO Might have to check bits 2:0
-- \|/ \|/ | next_rx_transaction := P_ERR;
-- TX_HEADER RX_HEADER | elsif curr_response_bits = "00101" then
-- |\ / | | next_rx_transaction := WRITE_ACK;
-- | \ / | | elsif curr_response_bits = "01100" then
-- | ADDR1 | | next_rx_transaction := READ_RESPONSE;
-- | | | | end if;
-- | \|/ | |
-- | ADDR2 | | if trans_st.curr_state = IDLE then
-- | | | | socbridge_driver_to_controller.is_active <= '0';
-- | \|/ | |
-- | 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 else
next_state <= IDLE; socbridge_driver_to_controller.is_active <= '1';
end if;
--- Next State Assignment Of RX FSM ---
case st.curr_rx_state is
when IDLE =>
if st.curr_rx_transaction /= NO_OP then
--next_rx_state <= TX_HEADER;
else
next_rx_state <= IDLE;
end if;
when RX_R_BODY =>
-- Here we want to stay in RX_R_BODY for the duration of a packet.
if st.rx_stage = 0 then
next_rx_state <= IDLE;
else
next_rx_state <= RX_R_BODY;
end if;
when ADDR1 =>
-- Transmits the entire address and returns to the appropriate
next_rx_state <= ADDR2;
when ADDR2 =>
next_rx_state <= ADDR3;
when ADDR3 =>
next_rx_state <= ADDR4;
when ADDR4 =>
if next_rx_transaction = WRITE_ADD then
next_rx_state <= RX_R_BODY;
elsif next_rx_transaction = READ_ADD then
--next_rx_state <= TELL_TX_TO_SEND_A_READ_RESPONSE;
else
next_rx_state <= IDLE; -- Potentially superfluous safety
end if;
end case;
--- Next State Assignments ---
--- ### TX NEXT STATE ASSIGNMENTS ### ---
case st.curr_tx_state is
when IDLE =>
if next_tx_transaction = READ_ADD or next_tx_transaction = READ or
next_tx_transaction = WRITE_ADD or next_tx_transaction = WRITE then
next_tx_state <= TX_HEADER;
-- Otherwise we are ready to send a response to a read.
elsif RESPONSE_READY then -- TODO define RESPONSE_READY
-- IMMEDIATLY GO INTO CORRECT STATE?
--next_tx_state <= RESPONSE;
else
next_tx_state <= IDLE;
end if;
when RESPONSE =>
-- TODO consider whether this should be moved to TX_W_BODY
if st.tx_stage = 0 then
next_tx_state <= IDLE;
else
next_tx_state <= RESPONSE;
end if; end if;
when TX_HEADER => when TX_HEADER =>
-- The header only takes one word (cycle) to transmit. -- The header only takes one word (cycle) to transmit.
-- Continue to body or address directly afterwards. -- Continue to body or address directly afterwards.
if st.curr_cmd = WRITE_ADD then if st.curr_tx_transaction = WRITE_ADD then
next_state <= ADDR1; next_tx_state <= ADDR1;
else else
next_state <= TX_BODY; next_tx_state <= TX_W_BODY;
end if; end if;
when TX_BODY => when TX_W_BODY =>
-- Here we want to stay in TX_BODY for the duration of a packet. -- Here we want to stay in TX_W_BODY for the duration of a packet.
if st.write_stage = 0 then if st.tx_stage = 0 then
next_state <= TX_ACK; next_tx_state <= TX_AWAIT;
else else
next_state <= TX_BODY; next_tx_state <= TX_W_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 -- Transmits the entire address and returns to the appropriate
next_state <= ADDR2; next_tx_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 = WRITE or st.curr_tx_transaction = WRITE_ADD then
next_state <= TX_BODY; next_tx_state <= TX_W_BODY;
else else
next_state <= RX_RESPONSE; -- If it is a read instruction we wait for response.
-- TODO separate read from NO_OP and P_ERR
next_tx_state <= TX_AWAIT;
end if;
when TX_AWAIT =>
-- Wait for RX FSM to get a response
if st.curr_rx_transaction = WRITE_ACK or st.curr_rx_transaction = READ_RESPONSE then
next_tx_state <= IDLE;
else
next_tx_state <= TX_AWAIT;
end if;
end case;
--- ### RX NEXT STATE ASSIGNMENTS ### ---
case st.curr_rx_state is
when IDLE =>
-- Do we have a command, if so enter command state.
if next_rx_transaction = READ_ADD or next_rx_transaction = READ or
next_rx_transaction = WRITE_ADD or next_rx_transaction = WRITE then
next_rx_state <= WRITE;
-- Otherwise we are ready to send a response to a read.
elsif RESPONSE_READY then -- TODO define RESPONSE_READY
-- SHOULD WE NOT MOVE TO CORRECT RESPONSE IMMEDIATLY?
next_rx_state <= RESPONSE;
else
next_rx_state <= IDLE;
end if;
when RESPONSE =>
-- TODO consider whether this should be moved to rx_W_BODY
if st.rx_stage = 0 then
next_rx_state <= IDLE;
else
next_rx_state <= RESPONSE;
end if;
when RX_W_ACK =>
next_rx_state <= IDLE;
when RX_R_BODY =>
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 or st.curr_rx_transaction = READ_ADD then
next_rx_state <= RX_R_BODY;
else
-- If it is a read instruction we wait for response.
-- TODO separate read from NO_OP and P_ERR
--next_rx_state <= TX_AWAIT;
end if; end if;
end case; end case;
--- Combinatorial output based on current state --- --- Combinatorial output based on current state ---
socbridge_driver_to_ext_data_cmd := (others => '0'); socbridge_driver_to_ext_data_cmd := (others => '0');
socbridge_driver_to_buffer.is_full_out <= '1'; socbridge_driver_to_ip.is_full_out <= '1';
socbridge_driver_to_buffer.write_enable_in <= '0'; socbridge_driver_to_ip.write_enable_in <= '0';
socbridge_driver_to_buffer.payload <= (others => '0'); socbridge_driver_to_ip.payload <= (others => '0');
case st.curr_state is --- ### TX_STATE BASED OUTPUT ### ---
case st.curr_tx_state is
when IDLE => when IDLE =>
if st.curr_cmd = WRITE or st.curr_cmd = WRITE_ADD then if st.curr_tx_transaction = WRITE or st.curr_tx_transaction = WRITE_ADD then
socbridge_driver_to_ext_data_cmd := get_cmd_bits(st.curr_cmd) & get_size_bits(st.curr_cmd_size); socbridge_driver_to_ext_data_cmd := get_header_bits(st.curr_tx_transaction) & get_size_bits(st.curr_cmd_size);
elsif st.curr_cmd = READ or st.curr_cmd = READ_ADD then elsif st.curr_tx_transaction = READ or st.curr_tx_transaction = READ_ADD then
socbridge_driver_to_ext_data_cmd := get_cmd_bits(st.curr_cmd) & get_size_bits(st.curr_cmd_size); socbridge_driver_to_ext_data_cmd := get_header_bits(st.curr_tx_transaction) & get_size_bits(st.curr_cmd_size);
else else
end if; end if;
when TX_HEADER => when TX_HEADER =>
if st.curr_cmd = WRITE_ADD then if st.curr_tx_transaction = WRITE_ADD or st.curr_tx_transaction = READ_ADD then
socbridge_driver_to_ext_data_cmd := st.curr_addr(7 downto 0); socbridge_driver_to_ext_data_cmd := st.curr_addr(31 downto 24);
else else
socbridge_driver_to_ext_data_cmd := buffer_to_socbridge_driver.payload; socbridge_driver_to_ext_data_cmd := ip_to_socbridge_driver.payload;
socbridge_driver_to_buffer.is_full_out <= '0'; socbridge_driver_to_ip.is_full_out <= '0';
end if; end if;
when TX_BODY => when TX_W_BODY =>
if st.write_stage > 0 then if st.tx_stage > 0 then
socbridge_driver_to_buffer.is_full_out <= '0'; socbridge_driver_to_ip.is_full_out <= '0';
socbridge_driver_to_ext_data_cmd := buffer_to_socbridge_driver.payload; socbridge_driver_to_ext_data_cmd := ip_to_socbridge_driver.payload;
else else
socbridge_driver_to_ext_data_cmd := (others => '0'); socbridge_driver_to_ext_data_cmd := (others => '0');
end if; end if;
when TX_ACK => when TX_HEADER =>
when RX_HEADER => if st.curr_tx_transaction = READ_ADD then
if st.curr_cmd = READ_ADD then
socbridge_driver_to_ext_data_cmd := st.curr_addr(7 downto 0);
end if;
when RX_RESPONSE =>
when RX_BODY =>
socbridge_driver_to_buffer.payload <= st.ext_to_socbridge_driver_reg.data;
socbridge_driver_to_buffer.write_enable_in <= '1';
when ADDR1 =>
socbridge_driver_to_ext_data_cmd := st.curr_addr(15 downto 8);
when ADDR2 =>
socbridge_driver_to_ext_data_cmd := st.curr_addr(23 downto 16);
when ADDR3 =>
socbridge_driver_to_ext_data_cmd := st.curr_addr(31 downto 24); socbridge_driver_to_ext_data_cmd := st.curr_addr(31 downto 24);
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 if;
when TX_AWAIT =>
when ADDR1 =>
socbridge_driver_to_ext_data_cmd := st.curr_addr(23 downto 16);
when ADDR2 =>
socbridge_driver_to_ext_data_cmd := st.curr_addr(15 downto 8);
when ADDR3 =>
socbridge_driver_to_ext_data_cmd := st.curr_addr(7 downto 0);
when ADDR4 =>
if st.curr_tx_transaction = WRITE_ADD then
socbridge_driver_to_ip.is_full_out <= '0';
socbridge_driver_to_ext_data_cmd := ip_to_socbridge_driver.payload;
report integer'image(to_integer(signed(socbridge_driver_to_ext_data_cmd))) & " "& integer'image(to_integer(signed(ip_to_socbridge_driver.payload)));
end if;
end case;
--- ### RX_STATE BASED OUTPUT ### ---
case st.curr_rx_state is
when IDLE =>
when ADDR1 =>
when ADDR2 =>
when ADDR3 =>
when ADDR4 =>
when RX_W_ACK =>
when RX_R_BODY =>
socbridge_driver_to_ip.payload <= st.ext_to_socbridge_driver_reg.data;
socbridge_driver_to_ip.write_enable_in <= '1';
end case; end case;
next_parity_out <= calc_parity(socbridge_driver_to_ext_data_cmd); next_parity_out <= calc_parity(socbridge_driver_to_ext_data_cmd);
--- DEBUG GLOBAL BINDINGS --- --- DEBUG GLOBAL BINDINGS ---
@ -258,7 +309,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,9 +319,9 @@ 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;
@ -278,27 +329,27 @@ begin
end case; end case;
--- Combinatorial output based on state --- Combinatorial output based on state
next_cmd <= NO_OP; next_tx_transaction := NO_OP;
next_cmd_size <= 0; next_cmd_size <= 0;
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; 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; 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; next_tx_transaction := READ;
elsif trans_st.curr_inst.instruction = WRITE then elsif trans_st.curr_inst.instruction = WRITE then
next_cmd <= WRITE; 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_cmd_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_cmd_size <= trans_st.curr_inst.seq_mem_access_count;
else else
@ -316,10 +367,11 @@ 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_tx_transaction <= NO_OP;
st.curr_cmd_size <= 0; st.curr_cmd_size <= 0;
st.curr_addr <= (others => '0'); st.curr_addr <= (others => '0');
@ -330,33 +382,36 @@ begin
st.socbridge_driver_to_ext_reg.data <= socbridge_driver_to_ext_data_cmd; 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_state <= next_state; st.curr_tx_state <= next_tx_state;
case st.curr_state is 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.curr_cmd_size <= next_cmd_size;
st.curr_addr <= trans_st.curr_inst.address; st.curr_addr <= trans_st.curr_inst.address;
if next_cmd_size > 0 then if next_cmd_size > 0 then
st.write_stage <= next_cmd_size - 1; st.tx_stage <= next_cmd_size - 1;
st.read_stage <= next_cmd_size - 1; st.rx_stage <= next_cmd_size - 1;
end if; end if;
when TX_HEADER => when TX_HEADER =>
when TX_BODY => when TX_W_BODY =>
if st.write_stage > 0 then if st.tx_stage > 0 then
st.write_stage <= st.write_stage - 1; st.tx_stage <= st.tx_stage - 1;
end if; end if;
when TX_ACK => when others =>
st.curr_cmd <= NO_OP; end case;
case st.curr_rx_state is
when IDLE =>
st.curr_rx_transaction <= next_rx_transaction;
when RX_W_ACK =>
st.curr_tx_transaction <= NO_OP;
st.curr_cmd_size <= 0; st.curr_cmd_size <= 0;
when RX_HEADER => when RX_R_BODY =>
when RX_BODY => if st.rx_stage > 0 then
if st.read_stage > 0 then st.rx_stage <= st.rx_stage - 1;
st.read_stage <= st.read_stage - 1;
else else
st.curr_cmd <= NO_OP; st.curr_tx_transaction <= NO_OP;
st.curr_cmd_size <= 0; st.curr_cmd_size <= 0;
end if; end if;
when others => when others =>
end case; end case;
end if; end if;
@ -381,9 +436,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

@ -5,7 +5,7 @@ library work;
use work.socbridge_driver_tb_pkg.all; use work.socbridge_driver_tb_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
@ -19,8 +19,8 @@ architecture tb of socbridge_driver_tb is
signal cmd_size : positive; 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_controller : socbridge_driver_to_controller_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);
@ -71,8 +71,8 @@ architecture tb of socbridge_driver_tb is
-- cmd_size: in positive; -- cmd_size: in positive;
-- 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;
-- buffer_to_socbridge_driver : out buffer_to_socbridge_driver_t; -- ip_to_socbridge_driver : out ip_to_socbridge_driver_t;
-- socbridge_driver_to_buffer : in socbridge_driver_to_buffer_t -- socbridge_driver_to_ip : in socbridge_driver_to_ip_t
-- ); -- );
-- end component socbridge_driver; -- end component socbridge_driver;
@ -85,8 +85,8 @@ begin
socbridge_driver_to_controller => socbridge_driver_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,
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;
@ -299,30 +299,30 @@ begin
internal_stimulus: process internal_stimulus: process
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 <= "00000001"; ip_to_socbridge_driver.payload <= "00000001";
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);
buffer_to_socbridge_driver.payload <= "00000010"; ip_to_socbridge_driver.payload <= "00000010";
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);
buffer_to_socbridge_driver.payload <= "00000100"; ip_to_socbridge_driver.payload <= "00000100";
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);
buffer_to_socbridge_driver.payload <= "00001000"; ip_to_socbridge_driver.payload <= "00001000";
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);
buffer_to_socbridge_driver.payload <= "00010000"; ip_to_socbridge_driver.payload <= "00010000";
wait until socbridge_driver_to_buffer.is_full_out = '0'; wait until socbridge_driver_to_ip.is_full_out = '0';
wait for CLK_PERIOD/2; wait for CLK_PERIOD/2;
wait until rising_edge(clk); wait until rising_edge(clk);
wait until rising_edge(clk); wait until rising_edge(clk);
buffer_to_socbridge_driver.payload <= "00100000"; ip_to_socbridge_driver.payload <= "00100000";
wait until socbridge_driver_to_buffer.is_full_out = '0'; wait until socbridge_driver_to_ip.is_full_out = '0';
wait for CLK_PERIOD/2; wait for CLK_PERIOD/2;
wait until rising_edge(clk); wait until rising_edge(clk);
wait until rising_edge(clk); --- ??? Why all these rising_edge checks? wait until rising_edge(clk); --- ??? Why all these rising_edge checks?

View File

@ -9,17 +9,17 @@ use ganimede.io_types.all;
package socbridge_driver_tb_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 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,
RESPONSE, READ, WRITE, PAYLOAD,
type state_t is RX_W_ACK, RX_R_BODY, RX_HEADER, RX_W_BODY);
(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, TX_W_ACK);
--- TRANSLATOR --- --- TRANSLATOR ---
type translator_state_t is (IDLE, SEND, SEND_ACCEPTED, AWAIT); type translator_state_t is (IDLE, SEND, SEND_ACCEPTED, AWAIT);
@ -36,10 +36,12 @@ 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;
curr_cmd_size: integer; curr_cmd_size: integer;
curr_addr : std_logic_vector(31 downto 0); curr_addr : std_logic_vector(31 downto 0);
end record state_rec_t; end record state_rec_t;
@ -50,7 +52,7 @@ 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(command : 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 --- --- DEBUG GLOBAL SIGNALS ---
@ -58,7 +60,8 @@ package socbridge_driver_tb_pkg is
signal G_next_parity_out : std_logic; signal G_next_parity_out : std_logic;
signal G_ext_to_socbridge_driver_rec : ext_protocol_t; 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_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_next_rx_state : rx_state_t;
signal G_next_tx_state : tx_state_t;
signal G_curr_command : command_t; signal G_curr_command : command_t;
signal G_curr_command_bits : std_logic_vector(4 downto 0); signal G_curr_command_bits : std_logic_vector(4 downto 0);
signal G_curr_response : response_t; signal G_curr_response : response_t;
@ -105,18 +108,25 @@ 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)
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 = P_ERR then
val := "01001";
end if;
return val; return val;
end function; end function;

View File

@ -3,15 +3,28 @@ 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',
] ]
manager.files = [
'manager/*.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