Compare commits

..

59 Commits

Author SHA1 Message Date
f0783eefa4 cleanup: made some signals not concurrently conditional 2025-05-27 15:19:31 +02:00
a84397d626 cleanup: renamed variables to simplify. 2025-05-23 17:08:58 +02:00
07150fe14a cleanup: removed unused signals and state 2025-05-23 16:41:41 +02:00
9cdcb8cd74 cleanup: reduced manager signals kept in state furhter (no io pipelining support for external users) and removed valid and data_out stateful assignment 2025-05-23 16:36:07 +02:00
5f9783f3b3 cleanup: removed instruction type from translator (not used, and currently implied by which translator it is) 2025-05-23 15:42:50 +02:00
09a5318523 cleanup: made manager address be kept in one variable (io pipelined access to ganimede isn't likely) 2025-05-23 15:35:41 +02:00
cd6ff9a77a made buffers work with valid on rising edge 2025-05-23 15:18:57 +02:00
23ede53056 updated ganimede toplevel to support new socbridge stuff 2025-05-22 23:50:30 +02:00
b1eee9ce1e reduced complexity in dummy IP. Now works with buffers with no unnecessary stall 2025-05-22 23:49:40 +02:00
4e4853c540 fixed bug which occurs due to socbridge not handling addresses seperately for read and writes 2025-05-22 23:48:49 +02:00
4682d19720 made reads not start if read buffer is too full 2025-05-22 23:33:54 +02:00
1146970be5 Multipacket socbridge works?? 2025-05-21 23:20:10 +02:00
1be1f1bc63 added initial multi in-flight packets attempt, limited by receiving socbridge 2025-05-21 21:10:58 +02:00
0eef36028a works with large compression images now (>1kb) 2025-05-21 14:22:37 +02:00
20971bc0b0 updated gitignore 2025-05-19 19:38:34 +02:00
8de2e01b18 socbridge: added support for early termination (flushing) of read/write commands 2025-05-16 23:02:25 +02:00
507c310b81 fifo_buffer: added fullness value as output 2025-05-16 21:53:25 +02:00
12411c11dc fifo_deserializer: removed bad_bad counter (not needed) 2025-05-16 21:20:30 +02:00
633aeba58a fifo_serializer/fifo_deserializer: bug fixes 2025-05-16 21:03:11 +02:00
6eb61a047e fifo_buffer: fixed sizing so it maps to generic var instead of global 2025-05-16 21:02:40 +02:00
5661f79825 socbridge: fixed small race con bug and added fallback when reading empty buf 2025-05-16 20:59:02 +02:00
bf3e4a3576 buffer: added serializer and deserializer 2025-05-15 12:45:38 +02:00
07d7fce6b9 fixed a timing issue in buffer 2025-04-22 17:44:09 +02:00
51c35c56c9 fixed valid out signal 2025-04-22 16:43:17 +02:00
a2917a3b04 Dummy ip works 2025-04-22 14:36:27 +02:00
c44c153bb3 bidir transfer: now works in socbridge verification tb 2025-04-21 17:02:46 +02:00
94fa595d6f added dummy ip core which increments each element by 1 2025-04-21 15:23:18 +02:00
77de1ca975 WIP: bi-dir socbridge driver (fiddling with tb memory atm) 2025-04-21 15:20:44 +02:00
f2a03fab24 buffers appear to be working 2025-04-18 20:02:39 +02:00
6a6ebdef95 Standardized fifo type adn full test debugging 2025-04-18 15:27:34 +02:00
241fe60024 simple test software to run ganimede instructions on LEON3 tb 2025-04-17 17:25:20 +02:00
4d4778f541 added initial record type for instructions in management 2025-04-17 13:43:08 +02:00
a656eb24e7 fixed reading/writing from/to socbridge in entire system 2025-04-16 20:03:17 +02:00
48dff427d4 Standardized fifo types and names 2025-04-16 16:50:34 +02:00
554e3cadab buffer probably done but untested, need to rework ganimede toplevel 2025-04-15 18:06:34 +02:00
56ab5e090a minor fixes 2025-04-15 15:18:00 +02:00
44018d5827 Started work on fifo buffer 2025-04-10 16:14:16 +02:00
fccf2dbba3 PRIMITIVE SUCCESS: made ganimede work in simulation (only 4 byte r/w to ganimede) 2025-04-09 15:24:55 +02:00
b56ce3a590 Added prefix "gan_" to all libraries 2025-04-08 16:20:19 +02:00
5913fc8764 Restored gtkwave file for socbridge driver testbench 2025-04-08 14:59:33 +02:00
3fe4b9cedd Fixed some bugs and made manager compatible with byte addressing 2025-04-08 14:59:33 +02:00
f46fde4333 merged manager and ganimede-rework 2025-04-08 14:57:18 +02:00
11b42f3211 Renamed some types 2025-04-08 14:52:43 +02:00
1b2c7600e6 first version of management unit done 2025-04-08 14:52:43 +02:00
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
34 changed files with 2341 additions and 981 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 $@

2
src/.gitignore vendored Normal file
View File

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

View File

@ -1,11 +1,11 @@
library IEEE; library IEEE;
use IEEE.std_logic_1164.all; use IEEE.std_logic_1164.all;
use IEEE.NUMERIC_STD.all; use IEEE.NUMERIC_STD.all;
library ganimede; library gan_ganimede;
use ganimede.io_types.all; use gan_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 gan_controller;
entity control_socbridge_tb is entity control_socbridge_tb is
end entity control_socbridge_tb; end entity control_socbridge_tb;
@ -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

@ -1,17 +1,17 @@
library IEEE; library IEEE;
use IEEE.std_logic_1164.all; use IEEE.std_logic_1164.all;
use IEEE.MATH_REAL.all; use IEEE.MATH_REAL.all;
library ganimede; library gan_ganimede;
use ganimede.io_types.all; use gan_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; 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;
@ -26,49 +26,65 @@ architecture behave of control_unit is
end record state_t; end record state_t;
signal state: state_t; signal state: state_t;
shared variable ored: std_logic; signal ored_reading: std_logic;
signal ored_writing: std_logic;
begin begin
comb_proc: process(cpu_to_controller, socbridge_driver_to_controller, state) comb_proc: process(manager_to_controller, drivers_to_controller, state)
variable local_ored_reading : std_logic;
variable local_ored_writing : std_logic;
begin begin
ored := '0'; local_ored_reading := '0';
local_ored_writing := '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; local_ored_reading := local_ored_reading or drivers_to_controller.socbridge.is_reading;
local_ored_writing := local_ored_writing or drivers_to_controller.socbridge.is_writing;
end loop ready_reduction; end loop ready_reduction;
controller_to_socbridge_driver.request <= state.curr_driver; ored_reading <= local_ored_reading;
controller_to_socbridge_driver.address <= state.address; ored_writing <= local_ored_writing;
controller_to_socbridge_driver.seq_mem_access_count <= state.seq_mem_access_count; controller_to_drivers.socbridge.request <= state.curr_driver;
controller_to_cpu.ready <= state.ready; controller_to_drivers.socbridge.address <= state.address;
controller_to_socbridge_driver.instruction <= state.instruction; controller_to_drivers.socbridge.seq_mem_access_count <= state.seq_mem_access_count;
controller_to_manager.ready <= state.ready;
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)
begin begin
if rising_edge(clk) then if rising_edge(clk) then
if rst = '1' then if rst = '1' then
state <= ((others => '0'), state.address <= (others => '0');
0, state.seq_mem_access_count <= 0;
'0', state.curr_driver <= '0';
'1', state.ready <= '1';
NO_OP); state.instruction <= NO_OP;
else else
state.ready <= not ored; -- Make sure to tell the management unit instruction is done
if ored = '0' then if (ored_writing = '0' and ored_reading = '0') and state.ready = '0' then
state.address <= cpu_to_controller.address; state.ready <= '1';
state.seq_mem_access_count <= cpu_to_controller.seq_mem_access_count;
state.curr_driver <= cpu_to_controller.driver_id(0);
with cpu_to_controller.cmd select
state.instruction <= WRITE when "01",
READ when "10",
NO_OP when others;
else else
state <= ((others => '0'), end if;
0, controller_to_manager.done_reading <= ored_reading;
'0', controller_to_manager.done_writing <= ored_writing;
'1', if ored_reading = '0' or ored_writing = '0' then
NO_OP); state.address <= manager_to_controller.address;
state.seq_mem_access_count <= manager_to_controller.seq_mem_access_count;
state.curr_driver <= manager_to_controller.driver_id(0);
if manager_to_controller.cmd = "01" then
state.instruction <= WRITE;
elsif manager_to_controller.cmd = "10" then
state.instruction <= READ;
else
state.instruction <= NO_OP;
end if;
else
state.address <= (others => '0');
state.seq_mem_access_count <= 0;
state.curr_driver <= '0';
state.ready <= '1';
state.instruction <= NO_OP;
end if; end if;
end if; end if;
end if; end if;

View File

@ -2,9 +2,9 @@ library IEEE;
use IEEE.std_logic_1164.all; use IEEE.std_logic_1164.all;
use IEEE.MATH_REAL.all; use IEEE.MATH_REAL.all;
use IEEE.numeric_std.all; use IEEE.numeric_std.all;
library ganimede; library gan_ganimede;
use ganimede.io_types.all; use gan_ganimede.io_types.all;
library controller; library gan_controller;
entity control_unit_tb is entity control_unit_tb is
end entity control_unit_tb; end entity control_unit_tb;
@ -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;
@ -36,25 +36,25 @@ begin
wait; wait;
end process clock_proc; end process clock_proc;
control_unit_inst: entity controller.control_unit control_unit_inst: entity gan_controller.control_unit
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';

40
src/dummy_ip/dummy_ip.vhd Normal file
View File

@ -0,0 +1,40 @@
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.NUMERIC_STD.all;
entity dummy_ip is
port (
clk, rst : in std_logic;
ready_in, valid_in : in std_logic;
ready_out, valid_out : out std_logic;
data_in : in std_logic_vector(8 - 1 downto 0);
data_out : out std_logic_vector(8 - 1 downto 0)
);
end entity dummy_ip;
architecture rtl of dummy_ip is
signal incremented_in : std_logic_vector(8 - 1 downto 0);
begin
comb_proc: process(ready_in, valid_in, data_in, incremented_in)
begin
ready_out <= ready_in;
end process;
seq_proc: process(clk,rst)
begin
if rst = '1' then
valid_out <= '0';
data_out <= (others => '0');
elsif rising_edge(clk) then
if valid_in = '1' and ready_in = '1' then
valid_out <= '1';
data_out <= std_logic_vector(unsigned(data_in) + 1);
else
valid_out <= '0';
end if;
elsif falling_edge(clk) then
end if;
end process seq_proc;
end architecture rtl;

View File

@ -0,0 +1,105 @@
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.MATH_REAL.all;
use ieee.numeric_std.all;
library gan_ganimede;
use gan_ganimede.io_types.all;
library techmap;
use techmap.gencomp.all;
entity fifo_buffer is
generic (
buffer_size : natural := 64;
tech : integer := 0;
data_width : natural := 8
);
port (
rst, in_clk, out_clk : in std_logic;
ready_in : in std_logic;
ready_out : out std_logic;
valid_in : in std_logic;
valid_out : out std_logic;
data_in : in std_logic_vector(data_width - 1 downto 0);
data_out : out std_logic_vector(data_width - 1 downto 0);
used_slots : out integer range 0 to buffer_size
);
end entity fifo_buffer;
architecture rtl of fifo_buffer is
constant address_bits : natural := integer(ceil(log2(real(buffer_size))));
signal read_pointer : std_logic_vector(address_bits - 1 downto 0);
signal write_pointer : std_logic_vector(address_bits - 1 downto 0);
signal write_signal : std_logic;
signal buffer_full : std_logic;
signal buffer_empty : std_logic;
signal inverted_in_clock : std_logic;
signal customout : std_logic_vector(0 downto 0); -- techmap needs customout and it is does not have a default value for some reason
begin
techmap_ram_inst : entity techmap.syncram_2p
generic map(tech => tech,
abits => address_bits,
dbits => data_width,
sepclk => 1
)
port map(
rclk => out_clk,
renable => '1',
raddress => read_pointer,
dataout => data_out,
wclk => inverted_in_clock,
write => write_signal,
waddress => write_pointer,
datain => data_in,
customclk => in_clk, --NOTE: No clue what this does but it has to be set to something
customout => customout
);
inverted_in_clock <= not in_clk;
comb_proc: process(write_pointer, read_pointer, buffer_full, valid_in, rst)
variable write_pointer_inc : unsigned(address_bits - 1 downto 0);
begin
if write_pointer >= read_pointer then
used_slots <= to_integer(unsigned(write_pointer) - unsigned(read_pointer));
else
used_slots <= buffer_size - to_integer(unsigned(read_pointer)) + to_integer(unsigned(write_pointer));
end if;
ready_out <= not buffer_full;
write_signal <= (valid_in and not buffer_full) or rst;
write_pointer_inc := unsigned(write_pointer) + 1;
customout <= "0";
if write_pointer_inc = unsigned(read_pointer) then
buffer_full <= '1';
else
buffer_full <= '0';
end if;
if write_pointer = read_pointer then
buffer_empty <= '1';
else
buffer_empty <= '0';
end if;
end process comb_proc;
seq_proc: process(rst, in_clk, out_clk, buffer_full, valid_in, ready_in, buffer_empty, write_pointer, read_pointer)
begin
if rst = '1' then
read_pointer <= (others => '0');
write_pointer <= (others => '0');
else
if rising_edge(in_clk) then
if valid_in = '1' and buffer_full = '0'then
write_pointer <= std_logic_vector(unsigned(write_pointer) + 1);
end if;
end if;
if rising_edge(out_clk) then
if ready_in = '1' and buffer_empty = '0' then
read_pointer <= std_logic_vector(unsigned(read_pointer) + 1);
valid_out <= '1';
else
valid_out <= '0';
end if;
end if;
end if;
end process seq_proc;
end architecture rtl;

View File

@ -0,0 +1,74 @@
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.MATH_REAL.all;
use ieee.numeric_std.all;
entity fifo_deserializer is
generic (
output_width : natural := 8;
input_width : natural := 8;
endianess : integer := 0 -- 0: little endian, 1: big endian
);
port (
rst, clk : in std_logic;
ready_in : in std_logic;
ready_out : out std_logic;
valid_in : in std_logic;
valid_out : out std_logic;
data_in : in std_logic_vector(input_width - 1 downto 0);
data_out : out std_logic_vector(output_width - 1 downto 0)
);
end entity fifo_deserializer;
architecture rtl of fifo_deserializer is
constant out_over_in : natural := output_width / input_width - 1;
type state_t is record
count : integer;
data : std_logic_vector(output_width - 1 downto 0);
full_word : std_logic;
prev_ready : std_logic;
end record state_t;
signal st : state_t;
begin
comb_proc: process(rst,clk,valid_in,ready_in,data_in,st)
begin
if st.full_word = '1' and ready_in = '1' then
valid_out <= '1';
else
valid_out <= '0';
end if;
ready_out <= ready_in;
data_out <= st.data;
end process comb_proc;
seq_proc: process(clk, rst)
begin
if rst = '1' then
st.count <= 0;
st.data <= (others => '0');
st.full_word <= '0';
st.prev_ready <= '0';
elsif (rising_edge(clk)) then
st.prev_ready <= ready_in;
if valid_in = '1' and st.prev_ready = '1' then
if endianess = 0 then
st.data((out_over_in + 1 - st.count) * input_width - 1 downto (out_over_in - st.count) * input_width) <= data_in;
else
st.data((st.count + 1) * input_width - 1 downto st.count * input_width) <= data_in;
end if;
end if;
if st.full_word = '1' and ready_in = '1' then
st.full_word <= '0';
end if;
if st.count = out_over_in and valid_in = '1' then
st.full_word <= '1';
st.count <= 0;
elsif valid_in = '1' then
st.count <= st.count + 1;
end if;
end if;
end process seq_proc;
end architecture rtl;

View File

@ -0,0 +1,76 @@
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.MATH_REAL.all;
use ieee.numeric_std.all;
entity fifo_serializer is
generic (
output_width : natural := 8;
input_width : natural := 8;
endianess : integer := 0 -- 0: little endian, 1: big endian
);
port (
rst, clk : in std_logic;
ready_in : in std_logic;
ready_out : out std_logic;
valid_in : in std_logic;
valid_out : out std_logic;
data_in : in std_logic_vector(input_width - 1 downto 0);
data_out : out std_logic_vector(output_width - 1 downto 0)
);
end entity fifo_serializer;
architecture rtl of fifo_serializer is
constant in_over_out : natural := input_width / output_width - 1;
type state_t is record
count : integer;
valid : std_logic;
data : std_logic_vector(input_width - 1 downto 0);
end record state_t;
signal st : state_t;
begin
comb_proc: process(rst,clk,valid_in,ready_in,data_in,st)
begin
if st.valid = '0' and valid_in = '0' then
ready_out <= '1';
else
ready_out <= '0';
end if;
valid_out <= st.valid;
if st.count <= in_over_out and st.valid = '1' then
if endianess = 0 then
data_out <= st.data((input_width - st.count * output_width) - 1 downto input_width - (st.count + 1) * output_width);
else
data_out <= st.data((st.count + 1) * output_width - 1 downto st.count * output_width);
end if;
else
data_out <= (others => '0');
end if;
end process comb_proc;
seq_proc: process(clk, rst)
begin
if rst = '1' then
st.count <= 0;
st.valid <= '0';
st.data <= (others => '0');
elsif (rising_edge(clk)) then
if valid_in = '1' and st.count = 0 then
st.valid <= '1';
st.data <= data_in;
elsif valid_in = '1' and st.count = in_over_out and ready_in = '1' then
st.count <= 0;
st.valid <= '1';
st.data <= data_in;
elsif st.count = in_over_out and ready_in = '1' then
st.valid <= '0';
st.count <= 0;
elsif ready_in = '1' and st.valid = '1' then
st.count <= st.count + 1;
end if;
end if;
end process seq_proc;
end architecture rtl;

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

@ -0,0 +1 @@
ganimede

View File

@ -1,74 +1,130 @@
library IEEE; library IEEE;
use IEEE.std_logic_1164.all; use IEEE.std_logic_1164.all;
library work; library gan_ganimede;
use work.io_types.all; use gan_ganimede.io_types.all;
library gan_socbridge;
use gan_socbridge.socbridge_driver_pkg.all;
library gan_controller;
library gan_manager;
use gan_manager.management_types.all;
library gan_buffer;
entity ganimede is entity ganimede_toplevel is
generic (
tech : integer
);
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; ext_to_ganimede : in ext_to_ganimede_t;
ext_interface_out : out ext_interface_out_t; ganimede_to_ext : out ganimede_to_ext_t;
int_interface_in : in int_interface_in_t; ip_to_ganimede : in ip_to_ganimede_t;
int_interface_out : out int_interface_out_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 manager_to_controller : manager_to_controller_t;
signal gan_ext_interface_out : ext_interface_out_t; signal controller_to_manager : controller_to_manager_t;
signal socbridge_driver_to_manager : socbridge_driver_to_manager_t;
signal manager_to_socbridge_driver : manager_to_socbridge_driver_t;
signal socbridge_driver_to_buffer : fifo_interface_t;
signal buffer_to_socbridge_driver : fifo_interface_t;
signal ip_to_socbridge_driver : ip_to_socbridge_driver_t;
signal socbridge_clk : std_logic;
signal ganimede_to_ip_reset : std_logic;
constant buf_size :integer := 2*1024;
--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;
--signal gan_socbridge_is_full_in : std_logic; --signal gan_socbridge_is_full_in : std_logic;
--signal gan_socbridge_is_full_out : std_logic; --signal gan_socbridge_is_full_out : std_logic;
--- COMPONENT DECLERATIONS ---
--component fifo is
-- generic(
-- WIDTH : positive;
-- DEPTH : positive
-- );
-- port(
-- clk, reset, read_enable, write_enable : in std_logic;
-- is_full, is_empty : out std_logic;
-- data_in : in std_logic_vector(WIDTH - 1 downto 0);
-- data_out : out std_logic_vector(WIDTH - 1 downto 0)
-- );
--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 --- --- INTERNAL CONNECTIONS ---
gan_int_interface_in <= int_interface_in; ip_to_socbridge_driver.fifo <= buffer_to_socbridge_driver;
int_interface_out <= gan_int_interface_out; ip_to_socbridge_driver.flush <= ip_to_ganimede.socbridge.flush;
gan_ext_interface_in <= ext_interface_in; ganimede_to_ip_reset <= rst or ip_to_ganimede.socbridge.flush;
ext_interface_out <= gan_ext_interface_out; ganimede_to_ip.socbridge.used_slots <= 0;
ip_to_socbridge_driver.read_fifo.data <= (others => '0');
ip_to_socbridge_driver.read_fifo.valid <= '0';
ip_to_socbridge_driver.read_fifo.ready <= '0';
--- DRIVER INSTANTIATION --- --- DRIVER INSTANTIATION ---
socbridge_driver_inst: socbridge_driver socbridge_driver_inst: entity gan_socbridge.socbridge_driver
port map( generic map(
clk => clk, BUFFER_SIZE => buf_size
reset => reset, )
ext_in => gan_ext_interface_in.socbridge, port map(
ext_out => gan_ext_interface_out.socbridge, clk => clk,
int_in => gan_int_interface_in.socbridge, socbridge_clk => socbridge_clk,
int_out => gan_int_interface_out.socbridge rst => rst,
); controller_to_socbridge_driver => controller_to_drivers.socbridge,
socbridge_driver_to_controller => drivers_to_controller.socbridge,
manager_to_socbridge_driver => manager_to_socbridge_driver,
socbridge_driver_to_manager => socbridge_driver_to_manager,
ext_to_socbridge_driver => ext_to_ganimede.socbridge,
socbridge_driver_to_ext => ganimede_to_ext.socbridge,
ip_to_socbridge_driver => ip_to_socbridge_driver,
socbridge_driver_to_ip => socbridge_driver_to_buffer
);
--- LATER WE ADD OPTIMIZATIONS HERE --- controller_inst: entity gan_controller.control_unit
port map(
clk => clk,
rst => rst,
manager_to_controller => manager_to_controller,
controller_to_manager => controller_to_manager,
drivers_to_controller => drivers_to_controller,
controller_to_drivers => controller_to_drivers
);
manager_inst: entity gan_manager.management_unit
port map(
clk => clk,
rst => rst,
manager_to_controller => manager_to_controller,
controller_to_manager => controller_to_manager,
manager_to_socbridge_driver => manager_to_socbridge_driver,
socbridge_driver_to_manager => socbridge_driver_to_manager
);
fifo_buffer_to_ip_inst : entity gan_buffer.fifo_buffer
generic map (
buffer_size => buf_size,
tech => tech
)
port map(
in_clk => socbridge_clk,
out_clk => clk,
rst => ganimede_to_ip_reset,
ready_in => ip_to_ganimede.socbridge.fifo.ready,
ready_out => buffer_to_socbridge_driver.ready,
valid_in => socbridge_driver_to_buffer.valid,
valid_out => ganimede_to_ip.socbridge.valid,
data_in => socbridge_driver_to_buffer.data,
data_out => ganimede_to_ip.socbridge.data,
used_slots => ip_to_socbridge_driver.read_fifo.used_slots
);
fifo_buffer_from_ip_inst : entity gan_buffer.fifo_buffer
generic map (
buffer_size => buf_size,
tech => tech
)
port map(
in_clk => clk,
out_clk => socbridge_clk,
rst => rst,
ready_in => socbridge_driver_to_buffer.ready,
ready_out => ganimede_to_ip.socbridge.ready,
valid_in => ip_to_ganimede.socbridge.fifo.valid,
valid_out => buffer_to_socbridge_driver.valid,
data_in => ip_to_ganimede.socbridge.fifo.data,
data_out => buffer_to_socbridge_driver.data,
used_slots => buffer_to_socbridge_driver.used_slots
);
end architecture rtl; end architecture rtl;

View File

@ -0,0 +1,110 @@
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.NUMERIC_STD.all;
library gan_ganimede;
use gan_ganimede.io_types.all;
library gan_socbridge;
use gan_socbridge.socbridge_driver_pkg.all;
library gan_controller;
entity ganimede_tb is
end entity ganimede_tb;
architecture tb of ganimede_tb is
signal done : boolean := false;
constant CLK_PERIOD : Time := 10 ns;
constant SIMULATION_CYCLE_COUNT : integer := 2000;
signal clk, rst : std_logic := '0';
signal controller_to_socbridge_driver_cmd : instruction_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_manager : controller_to_manager_t;
signal manager_to_ganimede : manager_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 manager_to_controller: manager_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_manager: controller_to_manager_t;
signal controller_to_drivers: controller_to_drivers_t;
begin
ganimede_inst: entity gan_ganimede.ganimede_toplevel
port map(
clk => clk,
rst => rst,
manager_to_ganimede => manager_to_ganimede,
ganimede_to_manager => ganimede_to_manager,
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;
real_clk_proc: process
variable cycle_count :integer := 0;
begin
while (not done) and (cycle_count < MAX_CYCLE_COUNT) loop
clk <= not clk;
wait for CLK_PERIOD / 2;
end loop;
wait;
end process real_clk_proc;
stimulus_proc: process
begin
report "Starting Simulation Stimulus!";
done <= false;
rst <= '1';
wait for 3 * CLK_PERIOD;
report "Reset grace period ended, starting stimulus...";
rst <= '0';
report "Test finished, ending simultaion...";
done <= true;
wait;
end process stimulus_proc;
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,60 @@ 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; constant fifo_width : natural := 8;
--- STANDARD TYPES --- --- STANDARD TYPES ---
type instruction_command_t is (NO_OP, READ, WRITE); type instruction_command_t is (NO_OP, READ, WRITE);
type fifo_interface_t is record
ready, valid : std_logic;
data : std_logic_vector(fifo_width - 1 downto 0);
used_slots : integer;
end record fifo_interface_t;
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, done_reading, done_writing : 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 := (
socbridge => ("SoCBridge ", 8, 2, 2) socbridge => ("SoCBridge ", 8, 2, 2)
); );
--- AUTOGENERATED TYPES --- --- AUTOGENERATED TYPES ---
type socbridge_driver_to_controller_t is record
is_reading : std_logic;
is_writing : 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 +69,36 @@ 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 subtype socbridge_driver_to_ip_t is fifo_interface_t;
payload : STD_LOGIC_VECTOR(interface_inst.socbridge.payload_width - 1 downto 0);
write_enable_in, is_full_out : std_logic;
end record socbridge_driver_to_buffer_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); fifo: fifo_interface_t;
write_enable_out, is_full_in : std_logic; read_fifo: fifo_interface_t;
end record buffer_to_socbridge_driver_t; flush: std_logic;
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;

65
src/gantry.toml Normal file
View File

@ -0,0 +1,65 @@
title = "ganimede"
createdAt = "2025-03-14"
maintainer = ""
email = ""
version = "0.0.1"
[libraries.gan_socbridge]
vhdl-version = "93c"
path = "socbridge"
[libraries.gan_manager]
vhdl-version = "93c"
path = "manager"
[libraries.gan_ganimede]
vhdl-version = "93c"
path = "ganimede"
[libraries.gan_controller]
vhdl-version = "93c"
path = "controller"
[libraries.gan_dummy_ip]
vhdl-version = "93c"
path = "dummy_ip"
[libraries.gan_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"
[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_buffer]
vhdl-version = "93c"
path = "fifo_buffer"

View File

@ -0,0 +1,110 @@
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.MATH_REAL.all;
use ieee.numeric_std.all;
library gan_manager;
use gan_manager.management_types.all;
library gan_ganimede;
use gan_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;
-- Address indexing whole words, not bytes
signal word_address : natural;
signal cmd : std_logic_vector(1 downto 0);
function pack(word: manager_word_t) return std_logic_vector is
begin
return word.address & word.size & word.command & word.reserved;
end function;
function unpack(word: std_logic_vector) return manager_word_t is
variable val : manager_word_t;
begin
val.address := word(31 downto 10);
val.size := word(9 downto 6);
val.command := word(5 downto 3);
val.reserved := word(2 downto 0);
return val;
end function;
begin
read_address <= manager_state.memory(0);
write_address <= manager_state.memory(1);
comb_proc: process(controller_to_manager, socbridge_driver_to_manager,manager_state)
variable local_word_address : natural;
begin
local_word_address := to_integer(shift_right(unsigned(socbridge_driver_to_manager.address), address_shift)) mod mem_words;
-- Read data from manager to SoCBridge driver
manager_to_socbridge_driver.ready <= '1';
manager_to_socbridge_driver.data <= pack(manager_state.memory(local_word_address));
manager_to_socbridge_driver.valid <= '1';
word_address <= local_word_address;
manager_to_controller.cmd <= cmd;
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) <= unpack(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;
-- Is the controller done executing an instruction
else
if controller_to_manager.done_reading = '1' then
manager_state.memory(0) <= manager_word_reset_val;
end if;
if controller_to_manager.done_writing = '1' then
manager_state.memory(1) <= manager_word_reset_val;
end if;
end if;
-- Is there a read instruction in memory
if pack(read_address) /= empty_word and controller_to_manager.ready = '1' and controller_to_manager.done_reading = '0' then
manager_to_controller.address <= read_address.address & "0000000000";
manager_to_controller.driver_id <= "1"; -- Only supprts one driver at present
manager_to_controller.seq_mem_access_count <= 2**to_integer(unsigned(read_address.size)) * 2**10;
cmd <= "10";
-- Is there a write instruction in memory
elsif pack(write_address) /= empty_word and controller_to_manager.ready = '1' and controller_to_manager.done_writing = '0'then
manager_to_controller.address <= write_address.address & "0000000000";
manager_to_controller.driver_id <= "1"; -- Only supports one driver at present
manager_to_controller.seq_mem_access_count <= 2**to_integer(unsigned(read_address.size)) * 2**10;
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;
cmd <= "00";
end if;
end if;
end if;
end process seq_proc;
end architecture rtl ;

View File

@ -0,0 +1,57 @@
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.NUMERIC_STD.all;
use IEEE.MATH_REAL.all;
library gan_ganimede;
use gan_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(CEIL(LOG2(real(WORD_SIZE) / real(8))));
type manager_word_t is record
address: std_logic_vector(21 downto 0);
size: std_logic_vector(3 downto 0);
command: std_logic_vector(2 downto 0);
reserved: std_logic_vector(WORD_SIZE - 1 - (22 + 4 + 3) downto 0);
end record manager_word_t;
constant empty_word : std_logic_vector(WORD_SIZE - 1 downto 0) := (others => '0');
constant mem_words : natural := 64;
constant address_mask : std_logic_vector(WORD_SIZE - 1 downto 0) := std_logic_vector(to_unsigned(mem_words - 1, 32));
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";
-- 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_word_reset_val : manager_word_t := (
address => (others =>'0'),
size => (others => '0'),
command => (others => '0'),
reserved => (others => '0')
);
constant manager_state_reset_val : manager_state_t := ((others => manager_word_reset_val), manager_word_reset_val);
type socbridge_driver_to_manager_t is record
address : std_logic_vector(WORD_SIZE - 1 downto 0);
data : std_logic_vector(WORD_SIZE - 1 downto 0);
valid: std_logic;
end record socbridge_driver_to_manager_t;
type manager_to_socbridge_driver_t is record
data : std_logic_vector(WORD_SIZE - 1 downto 0);
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 gan_ganimede;
use gan_ganimede.io_types.all;
library gan_manager;
use gan_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', done => '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 gan_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

@ -1,22 +1,33 @@
library IEEE; library IEEE;
use IEEE.std_logic_1164.all; use IEEE.std_logic_1164.all;
use IEEE.NUMERIC_STD.all; use IEEE.NUMERIC_STD.all;
library ganimede; library gan_ganimede;
use ganimede.io_types.all; use gan_ganimede.io_types.all;
library socbridge; library gan_socbridge;
use socbridge.socbridge_driver_tb_pkg.all; use gan_socbridge.socbridge_driver_pkg.all;
library gan_manager;
use gan_manager.management_types.all;
library grlib;
use grlib.stdlib.all;
entity socbridge_driver is entity socbridge_driver is
generic(
MAX_PKT_SIZE : integer range 1 to 128 := 8;
BUFFER_SIZE : integer
);
port( port(
clk : in std_logic; clk : in std_logic;
rst : in std_logic; rst : in std_logic;
socbridge_clk : out std_logic;
controller_to_socbridge_driver : in controller_to_socbridge_driver_t; controller_to_socbridge_driver : in controller_to_socbridge_driver_t;
socbridge_driver_to_controller : out socbridge_driver_to_controller_t; socbridge_driver_to_controller : out socbridge_driver_to_controller_t;
manager_to_socbridge_driver : in manager_to_socbridge_driver_t;
socbridge_driver_to_manager : out socbridge_driver_to_manager_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,339 +35,516 @@ 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_t;
signal trans_next_state : translator_state_t; signal trans_read_next_state : ctrl_inst_state_t;
signal trans_write_next_state : ctrl_inst_state_t;
--- FSM COMMUNICATION ---
--- MANAGEMENT COMMUNICATION ---
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.clk <= ext_to_socbridge_driver.control(1);
ext_to_socbridge_driver_rec.parity <= ext_to_socbridge_driver.control(0);
-- Helpful Bindings -- comb_proc: process(ext_to_socbridge_driver_rec, 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 controller_to_socbridge_driver, st, trans_st)
-- Not sure that the two process method is helping here: if this was a normal variable curr_response_bits : std_logic_vector(4 downto 0);
-- signal assignment there would be no confusion. variable local_next_rx_transaction : transaction_t;
-- in the case ... <= ext_to_socbridge_driver_rec we get variable local_next_tx_transaction : transaction_t;
-- curr_resp | ext_to_socbridge_driver_rec | ext_to_socbridge_driver variable local_next_data_out : std_logic_vector(interface_inst.socbridge.payload_width - 1 downto 0);
-- 00000 | 00000000 | 00001001
-- 00000 | 00001001 | 00001001
-- 00001 | 00001001 | 00001001
-- 00001 | 00001001 | 00001001
--
-- but in the case ... <= ext_to_socbridge_driver we get
-- curr_resp | ext_to_socbridge_driver_rec | ext_to_socbridge_driver
-- 00000 | 00000000 | 00001001
-- 00001 | 00001001 | 00001001
-- 00001 | 00001001 | 00001001
-- 00001 | 00001001 | 00001001
with curr_response_bits select
curr_response <= WRITE_ACK when "00001",
WRITE_ACK when "00101",
READ_RESPONSE when "01000",
READ_RESPONSE when "01100",
NO_OP when others;
comb_proc: process(ext_to_socbridge_driver, buffer_to_socbridge_driver, curr_response, st, controller_to_socbridge_driver, trans_st)
begin begin
-- Outputs -- DEFAULT VALUES
socbridge_driver_to_ext <= create_io_type_out_from_ext_protocol(st.socbridge_driver_to_ext_reg); -- Helpful Bindings --
with trans_st.curr_state select ext_to_socbridge_driver_rec.data <= ext_to_socbridge_driver.payload;
socbridge_driver_to_controller.is_active <= '0' when IDLE, ext_to_socbridge_driver_rec.clk <= ext_to_socbridge_driver.control(1);
'1' when others; ext_to_socbridge_driver_rec.parity <= ext_to_socbridge_driver.control(0);
socbridge_clk <= ext_to_socbridge_driver_rec.clk;
socbridge_driver_to_ip.used_slots <= 0;
next_rx_data_size <= 2 ** to_integer(unsigned(ext_to_socbridge_driver_rec.data(2 downto 0)));
curr_response_bits := ext_to_socbridge_driver_rec.data(7 downto 3);
-- Set helper var to current transaction seen at the input.
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.read.state = IDLE then
socbridge_driver_to_controller.is_reading <= '0';
else
socbridge_driver_to_controller.is_reading <= '1';
end if;
if trans_st.write.state = IDLE then
socbridge_driver_to_controller.is_writing <= '0';
else
socbridge_driver_to_controller.is_writing <= '1';
end if;
--- State Transition Diagram --- --- Next State Assignments ---
-- --- ### TX NEXT STATE ASSIGNMENTS ### ---
-- case st.tx_state is
--
-- +-----+
-- | |
-- \|/ /--+
-- 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;
when TX_HEADER =>
-- The header only takes one word (cycle) to transmit.
-- Continue to body or address directly afterwards.
if st.curr_cmd = WRITE_ADD then
next_state <= ADDR1;
else
next_state <= TX_BODY;
end if;
when TX_BODY =>
-- Here we want to stay in TX_BODY for the duration of a packet.
if st.write_stage = 0 then
next_state <= TX_ACK;
else
next_state <= TX_BODY;
end if;
when TX_ACK =>
-- Wait for write acknowledgement.
if curr_response = WRITE_ACK then
next_state <= IDLE;
else
next_state <= TX_ACK;
end if;
when RX_HEADER =>
-- The header only takes one word (cycle) to transmit.
-- Continue to awaiting response directly afterwards.
if st.curr_cmd = READ_ADD then
next_state <= ADDR1;
else
next_state <= RX_RESPONSE;
end if;
when RX_RESPONSE =>
-- Wait for read response.
if curr_response = READ_RESPONSE then
next_state <= RX_BODY;
else
next_state <= RX_RESPONSE;
end if;
when RX_BODY =>
-- Here we want to stay in RX_BODY for the duration of a packet.
if st.read_stage = 0 then
next_state <= IDLE;
else
next_state <= RX_BODY;
end if;
when ADDR1 =>
-- Transmits the entire address and returns to the appropriate
next_state <= ADDR2;
when ADDR2 =>
next_state <= ADDR3;
when ADDR3 =>
next_state <= ADDR4;
when ADDR4 =>
if st.curr_cmd = WRITE or st.curr_cmd = WRITE_ADD then
next_state <= TX_BODY;
else
next_state <= RX_RESPONSE;
end if;
end case;
--- Combinatorial output based on current state ---
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 =>
if st.curr_cmd = WRITE or st.curr_cmd = WRITE_ADD then
socbridge_driver_to_ext_data_cmd := get_cmd_bits(st.curr_cmd) & get_size_bits(st.curr_cmd_size);
elsif st.curr_cmd = READ or st.curr_cmd = READ_ADD then
socbridge_driver_to_ext_data_cmd := get_cmd_bits(st.curr_cmd) & get_size_bits(st.curr_cmd_size);
else
end if;
when TX_HEADER =>
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;
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 =>
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);
when ADDR4 =>
if st.curr_cmd = WRITE_ADD then
socbridge_driver_to_buffer.is_full_out <= '0';
socbridge_driver_to_ext_data_cmd := buffer_to_socbridge_driver.payload;
report integer'image(to_integer(signed(socbridge_driver_to_ext_data_cmd))) & " "& integer'image(to_integer(signed(buffer_to_socbridge_driver.payload)));
end if;
end case;
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 ---
--- Next state assignment
case trans_st.curr_state is
when IDLE => when IDLE =>
if trans_st.curr_inst.request = '1' then if (local_next_tx_transaction = WRITE or local_next_tx_transaction = WRITE_ADD) and not st.write_in_flight then
trans_next_state <= SEND; next_tx_state <= TX_HEADER;
elsif (local_next_tx_transaction = READ or local_next_tx_transaction = READ_ADD) and not st.read_in_flight then
next_tx_state <= TX_HEADER;
elsif local_next_tx_transaction = READ_RESPONSE or local_next_tx_transaction = WRITE_ACK then
next_tx_state <= TX_HEADER;
else else
trans_next_state <= IDLE; next_tx_state <= IDLE;
end if;
when TX_HEADER =>
-- Commands
if st.tx_transaction = WRITE_ADD or st.tx_transaction = READ_ADD then
next_tx_state <= ADDR1;
elsif st.tx_transaction = WRITE then
next_tx_state <= TX_W_BODY;
elsif st.tx_transaction = READ then
next_tx_state <= IDLE;
-- Responses
elsif st.tx_transaction = READ_RESPONSE then
next_tx_state <= TX_R_BODY;
else
next_tx_state <= IDLE;
end if;
when TX_R_BODY =>
if st.tx_stage <= 1 then
next_tx_state <= IDLE;
else
next_tx_state <= TX_R_BODY;
end if;
when ADDR1 =>
next_tx_state <= ADDR2;
when ADDR2 =>
next_tx_state <= ADDR3;
when ADDR3 =>
next_tx_state <= ADDR4;
when ADDR4 =>
if st.tx_transaction = READ_ADD then
next_tx_state <= IDLE;
elsif st.tx_transaction = WRITE_ADD then
next_tx_state <= TX_W_BODY;
else
next_tx_state <= IDLE;
end if;
when TX_W_BODY =>
if st.tx_stage <= 1 then
next_tx_state <= IDLE;
else
next_tx_state <= TX_W_BODY;
end if;
end case;
--- Next State Assignment Of RX FSM ---
case st.rx_state is
when IDLE =>
if local_next_rx_transaction /= NO_OP then
next_rx_state <= RX_HEADER;
else
next_rx_state <= IDLE;
end if;
when RX_HEADER =>
-- Commands
if st.rx_transaction = WRITE_ADD or st.rx_transaction = READ_ADD then
next_rx_state <= ADDR1;
elsif st.rx_transaction = WRITE then
next_rx_state <= RX_W_BODY;
elsif st.rx_transaction = READ then
next_rx_state <= RX_AWAIT;
-- Responses
elsif st.rx_transaction = READ_RESPONSE then
next_rx_state <= RX_R_BODY;
elsif local_next_rx_transaction /= NO_OP then
next_rx_state <= RX_HEADER;
else
next_rx_state <= IDLE;
end if;
when RX_R_BODY =>
if st.rx_stage <= 1 then
if local_next_rx_transaction /= NO_OP then
next_rx_state <= RX_HEADER;
else
next_rx_state <= IDLE;
end if;
else
next_rx_state <= RX_R_BODY;
end if;
when ADDR1 =>
next_rx_state <= ADDR2;
when ADDR2 =>
next_rx_state <= ADDR3;
when ADDR3 =>
next_rx_state <= ADDR4;
when ADDR4 =>
if st.rx_transaction = READ_ADD then
next_rx_state <= RX_AWAIT;
elsif st.rx_transaction = WRITE_ADD then
next_rx_state <= RX_W_BODY;
else
next_rx_state <= IDLE; -- Potentially superfluous safety
end if;
when RX_W_BODY =>
if st.rx_stage <= 1 then
next_rx_state <= RX_AWAIT;
else
next_rx_state <= RX_W_BODY;
end if;
when RX_AWAIT =>
-- Wait for TX FSM to send a response
if (st.rx_transaction = WRITE_ADD or st.rx_transaction = WRITE)
and st.tx_transaction = WRITE_ACK then
next_rx_state <= IDLE;
elsif (st.rx_transaction = READ_ADD or st.rx_transaction = READ)
and st.tx_transaction = READ_RESPONSE and st.tx_stage = 1 then
next_rx_state <= IDLE;
else
next_rx_state <= RX_AWAIT;
end if;
end case;
--- Combinatorial output based on current state ---
local_next_data_out := (others => '0');
socbridge_driver_to_ip.ready <= '0';
--- ### TX_STATE BASED OUTPUT ### ---
case st.tx_state is
when IDLE =>
when TX_HEADER =>
if st.tx_transaction = WRITE_ACK or st.tx_transaction = READ_RESPONSE then
local_next_data_out := get_header_bits(st.tx_transaction, st.rx_transaction) & get_size_bits(st.rx_data_size);
else
local_next_data_out := get_header_bits(st.tx_transaction, st.rx_transaction) & get_size_bits(st.tx_data_size);
end if;
if st.tx_transaction = WRITE then
socbridge_driver_to_ip.ready <= '1';
end if;
when TX_W_BODY =>
if st.tx_stage > 1 then
socbridge_driver_to_ip.ready <= '1';
end if;
if st.tx_stage > 0 then
if ip_to_socbridge_driver.fifo.valid = '1' then
local_next_data_out := ip_to_socbridge_driver.fifo.data;
else
local_next_data_out := (others => '0');
end if;
end if;
when TX_R_BODY =>
if st.tx_stage > 0 then
local_next_data_out := st.manager_data((((st.tx_stage - 1) mod 4) + 1) * 8 - 1 downto ((((st.tx_stage - 1) mod 4) + 1) - 1) * 8);
end if;
when ADDR1 =>
local_next_data_out := st.tx_addr(31 downto 24);
when ADDR2 =>
local_next_data_out := st.tx_addr(23 downto 16);
when ADDR3 =>
local_next_data_out := st.tx_addr(15 downto 8);
when ADDR4 =>
local_next_data_out := st.tx_addr(7 downto 0);
if st.tx_transaction = WRITE_ADD then
socbridge_driver_to_ip.ready <= '1';
end if;
end case;
--- ### RX_STATE BASED OUTPUT ### ---
socbridge_driver_to_manager.valid <= '0';
socbridge_driver_to_manager.data <= st.manager_data;
socbridge_driver_to_manager.address <= st.manager_addr;
socbridge_driver_to_ip.valid <= '0';
socbridge_driver_to_ip.data <= st.ext_to_socbridge_driver_reg.data;
case st.rx_state is
when RX_W_BODY =>
if st.rx_stage mod 4 = 0 and st.rx_stage /= st.rx_data_size then
socbridge_driver_to_manager.valid <= '1';
end if;
when RX_R_BODY =>
socbridge_driver_to_ip.valid <= '1';
when RX_AWAIT =>
if st.rx_transaction = WRITE or st.rx_transaction = WRITE_ADD then
socbridge_driver_to_manager.valid <= '1';
end if;
when others =>
end case;
next_parity_out <= calc_parity(local_next_data_out);
--- TRANSLATOR ---
--- Next state assignment
case trans_st.write.state is
when IDLE =>
if st.rx_transaction = READ or st.rx_transaction = READ_ADD
or st.rx_transaction = WRITE or st.rx_transaction = WRITE_ADD then
trans_write_next_state <= IDLE;
elsif trans_st.write.inst.request = '1' and (ip_to_socbridge_driver.fifo.used_slots >= MAX_PKT_SIZE
or ip_to_socbridge_driver.flush = '1') then
trans_write_next_state <= SEND;
else
trans_write_next_state <= IDLE;
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.tx_transaction = WRITE or st.tx_transaction = WRITE_ADD then
trans_next_state <= SEND_ACCEPTED; trans_write_next_state <= SEND_ACCEPTED;
else else
trans_next_state <= SEND; trans_write_next_state <= SEND;
end if; end if;
-- Transisitonal state to decrement counter in transition between SEND and AWAIT. -- Transisitonal state to decrement counter in transition between SEND and AWAIT.
when SEND_ACCEPTED => when SEND_ACCEPTED =>
trans_next_state <= AWAIT; trans_write_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.write.inst.access_count <= MAX_PKT_SIZE and not st.write_in_flight then
trans_next_state <= IDLE; trans_write_next_state <= IDLE;
elsif st.curr_state = IDLE then elsif ip_to_socbridge_driver.fifo.used_slots = 0 and ip_to_socbridge_driver.flush = '1'
trans_next_state <= SEND; and not st.write_in_flight then
trans_write_next_state <= IDLE;
elsif not st.write_in_flight and (ip_to_socbridge_driver.fifo.used_slots >= MAX_PKT_SIZE
or ip_to_socbridge_driver.flush = '1') then
trans_write_next_state <= SEND;
else else
trans_next_state <= AWAIT; trans_write_next_state <= AWAIT;
end if;
end case;
case trans_st.read.state is
when IDLE =>
if next_rx_transaction = READ or next_rx_transaction = READ_ADD
or next_rx_transaction = WRITE or next_rx_transaction = WRITE_ADD then
trans_read_next_state <= IDLE;
elsif st.rx_transaction = READ or st.rx_transaction = READ_ADD
or st.rx_transaction = WRITE or st.rx_transaction = WRITE_ADD then
trans_read_next_state <= IDLE;
elsif trans_st.read.inst.request = '1' and BUFFER_SIZE - ip_to_socbridge_driver.read_fifo.used_slots > 2*MAX_PKT_SIZE then
trans_read_next_state <= SEND;
else
trans_read_next_state <= IDLE;
end if;
-- Wait for driver to go idle and send next instruction. Then enter AWAIT
when SEND =>
if st.tx_transaction = READ or st.tx_transaction = READ_ADD then
trans_read_next_state <= SEND_ACCEPTED;
else
trans_read_next_state <= SEND;
end if;
-- Transisitonal state to decrement counter in transition between SEND and AWAIT.
when SEND_ACCEPTED =>
trans_read_next_state <= AWAIT;
-- Wait for driver to finish current instruction, then reenter SEND
when AWAIT =>
if trans_st.read.inst.access_count <= MAX_PKT_SIZE and not st.read_in_flight then
trans_read_next_state <= IDLE;
elsif ip_to_socbridge_driver.flush = '1'and not st.read_in_flight then
trans_read_next_state <= IDLE;
elsif not st.read_in_flight and BUFFER_SIZE - ip_to_socbridge_driver.read_fifo.used_slots > 2*MAX_PKT_SIZE then
trans_read_next_state <= SEND;
else
trans_read_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;
case trans_st.curr_state is if trans_st.read.state = IDLE and trans_st.write.state = IDLE and st.rx_state = RX_AWAIT then
when IDLE => if (st.rx_transaction = WRITE or st.rx_transaction = WRITE_ADD) and manager_to_socbridge_driver.ready = '1' then
when SEND => local_next_tx_transaction := WRITE_ACK;
if trans_st.is_first_word = '1' then elsif (st.rx_transaction = READ or st.rx_transaction = READ_ADD) and manager_to_socbridge_driver.valid = '1' then
if trans_st.curr_inst.instruction = READ then next_tx_data_size <= st.rx_data_size;
next_cmd <= READ_ADD; local_next_tx_transaction := READ_RESPONSE;
elsif trans_st.curr_inst.instruction = WRITE then end if;
next_cmd <= WRITE_ADD; elsif trans_st.read.state = SEND
end if; and not ((st.last_sent_transaction = READ or st.last_sent_transaction = READ_ADD) and trans_st.write.state = SEND) then
else if trans_st.read.is_first_word = '1' then
if trans_st.curr_inst.instruction = READ then local_next_tx_transaction := READ_ADD;
next_cmd <= READ; else
elsif trans_st.curr_inst.instruction = WRITE then local_next_tx_transaction := READ;
next_cmd <= WRITE; end if;
end if; if trans_st.read.inst.access_count > MAX_PKT_SIZE then
end if; next_tx_data_size <= MAX_PKT_SIZE;
elsif trans_st.read.inst.access_count > 0 then
if trans_st.curr_inst.seq_mem_access_count > 128 then next_tx_data_size <= trans_st.read.inst.access_count;
next_cmd_size <= 128; else
elsif trans_st.curr_inst.seq_mem_access_count > 0 then next_tx_data_size <= 0;
next_cmd_size <= trans_st.curr_inst.seq_mem_access_count; end if;
else elsif trans_st.write.state = SEND and not st.read_in_flight then
next_cmd_size <= 0; if trans_st.write.is_first_word = '1' then
end if; local_next_tx_transaction := WRITE_ADD;
when others => else
end case; local_next_tx_transaction := WRITE;
end if;
if trans_st.write.inst.access_count > MAX_PKT_SIZE then
next_tx_data_size <= MAX_PKT_SIZE;
elsif trans_st.write.inst.access_count > 0 then
next_tx_data_size <= trans_st.write.inst.access_count;
else
next_tx_data_size <= 0;
end if;
end if;
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)
begin begin
if(rst = '1') then if(rst = '1') then
st.ext_to_socbridge_driver_reg.data <= (others => '0'); st <= st_reset_vec;
st.socbridge_driver_to_ext_reg.data <= (others => '0');
st.socbridge_driver_to_ext_reg.clk <= '0';
st.socbridge_driver_to_ext_reg.parity <= '1';
st.curr_state <= IDLE;
st.write_stage <= 0;
st.read_stage <= 0;
st.curr_cmd <= NO_OP;
st.curr_cmd_size <= 0;
st.curr_addr <= (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; -- PARITY CHECK NOT IMPLEMENTED, REMOVING
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.tx_state <= next_tx_state;
case st.curr_state is st.rx_state <= next_rx_state;
case st.tx_state is
when IDLE => when IDLE =>
st.curr_cmd <= next_cmd; if ip_to_socbridge_driver.flush = '1' then
st.curr_cmd_size <= next_cmd_size; st.last_sent_transaction <= NO_OP;
st.curr_addr <= trans_st.curr_inst.address; end if;
if next_cmd_size > 0 then if (next_tx_transaction = WRITE or next_tx_transaction = WRITE_ADD
st.write_stage <= next_cmd_size - 1; or next_tx_transaction = READ or next_tx_transaction = READ_ADD) then
st.read_stage <= next_cmd_size - 1; if not st.read_in_flight or not st.write_in_flight then
st.tx_transaction <= next_tx_transaction;
st.tx_data_size <= next_tx_data_size;
else
st.tx_transaction <= NO_OP;
st.tx_data_size <= 0;
end if;
else
st.tx_transaction <= next_tx_transaction;
st.tx_data_size <= next_tx_data_size;
end if;
if next_tx_transaction = WRITE_ADD or next_tx_transaction = WRITE
or next_tx_transaction = READ_RESPONSE then
st.tx_addr <= trans_st.write.inst.address;
st.tx_stage <= next_tx_data_size;
else
st.tx_addr <= trans_st.read.inst.address;
st.tx_stage <= 0;
end if; end if;
when TX_HEADER => when TX_HEADER =>
when TX_BODY => if st.tx_transaction = WRITE or st.tx_transaction = WRITE_ADD then
if st.write_stage > 0 then st.last_sent_transaction <= st.tx_transaction;
st.write_stage <= st.write_stage - 1; if not (st.rx_state = RX_HEADER and st.rx_transaction = WRITE_ACK) then
st.write_in_flight <= true;
end if;
elsif st.tx_transaction = READ or st.tx_transaction = READ_ADD then
st.last_sent_transaction <= st.tx_transaction;
if not (st.rx_state = RX_HEADER and st.rx_transaction = READ_RESPONSE) then
st.read_in_flight <= true;
end if;
end if; end if;
when TX_ACK => when TX_W_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 => end if;
when RX_BODY => when TX_R_BODY =>
if st.read_stage > 0 then if st.tx_stage > 0 then
st.read_stage <= st.read_stage - 1; st.tx_stage <= st.tx_stage - 1;
end if;
when others =>
end case;
case st.rx_state is
when IDLE =>
st.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.rx_transaction = WRITE_ACK then
if not (st.tx_state = TX_HEADER and (st.tx_transaction = WRITE or st.tx_transaction = WRITE_ADD)) then
st.write_in_flight <= false;
end if;
if next_rx_transaction /= NO_OP then
st.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;
end if;
elsif st.rx_transaction = READ_RESPONSE then
if not (st.tx_state = TX_HEADER and (st.tx_transaction = READ or st.tx_transaction = READ_ADD)) then
st.read_in_flight <= false;
end if;
end if;
when RX_R_BODY =>
if st.rx_stage > 0 then
st.rx_stage <= st.rx_stage - 1;
end if;
if next_rx_transaction /= NO_OP and st.rx_stage <= 1 then
st.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;
end if;
when RX_W_BODY =>
if st.rx_stage > 0 then
st.rx_stage <= st.rx_stage - 1;
st.manager_data((((st.rx_stage - 1) mod 4) + 1) * 8 - 1 downto ((((st.rx_stage - 1) mod 4) + 1) - 1) * 8) <= st.ext_to_socbridge_driver_reg.data;
end if;
if (st.rx_stage - 2) mod 4 = 0 and st.rx_data_size - st.rx_stage > 4 then
st.manager_addr <= std_logic_vector(to_unsigned(to_integer(unsigned(st.manager_addr) + 4), 32));
end if;
when RX_AWAIT =>
st.manager_data <= manager_to_socbridge_driver.data;
if st.tx_transaction = READ_RESPONSE or st.tx_transaction = WRITE_ACK then
if (st.rx_transaction = READ or st.rx_transaction = READ_ADD) and (st.tx_stage - 2) mod 4 = 0 then
st.manager_addr <= std_logic_vector(to_unsigned(to_integer(unsigned(st.manager_addr) + 4), 32));
elsif (st.rx_transaction = WRITE or st.rx_transaction = WRITE_ADD) and (st.rx_stage - 2) mod 4 = 0 then
st.manager_addr <= std_logic_vector(to_unsigned(to_integer(unsigned(st.manager_addr) + 4), 32));
end if;
end if;
when ADDR1 =>
if st.rx_transaction = READ_ADD then
st.manager_addr(31 downto 24) <= st.ext_to_socbridge_driver_reg.data;
else else
st.curr_cmd <= NO_OP; st.manager_addr(31 downto 24) <= st.ext_to_socbridge_driver_reg.data;
st.curr_cmd_size <= 0; end if;
when ADDR2 =>
if st.rx_transaction = READ_ADD then
st.manager_addr(23 downto 16) <= st.ext_to_socbridge_driver_reg.data;
else
st.manager_addr(23 downto 16) <= st.ext_to_socbridge_driver_reg.data;
end if;
when ADDR3 =>
if st.rx_transaction = READ_ADD then
st.manager_addr(15 downto 8) <= st.ext_to_socbridge_driver_reg.data;
else
st.manager_addr(15 downto 8) <= st.ext_to_socbridge_driver_reg.data;
end if;
when ADDR4 =>
if st.rx_transaction = READ_ADD then
st.manager_addr(7 downto 0) <= st.ext_to_socbridge_driver_reg.data;
else
st.manager_addr(7 downto 0) <= st.ext_to_socbridge_driver_reg.data;
end if; end if;
when others => when others =>
end case; end case;
end if; end if;
@ -364,32 +552,81 @@ begin
--- TRANSLATOR --- --- TRANSLATOR ---
if(rst = '1') then if(rst = '1') then
trans_st.curr_state <= IDLE; trans_st <= translator_reset_vec;
trans_st.curr_inst.request <= '0'; elsif(rising_edge(ext_to_socbridge_driver_rec.clk)) then
trans_st.curr_inst.address <= (others => '0'); trans_st.read.state <= trans_read_next_state;
trans_st.curr_inst.seq_mem_access_count <= 0; trans_st.write.state <= trans_write_next_state;
trans_st.curr_inst.instruction <= NO_OP; case trans_st.write.state is
trans_st.is_first_word <= '1';
elsif(rising_edge(clk)) then
trans_st.curr_state <= trans_next_state;
case trans_st.curr_state is
when IDLE => when IDLE =>
if controller_to_socbridge_driver.request = '1' then if controller_to_socbridge_driver.request = '1' and controller_to_socbridge_driver.instruction = WRITE
trans_st.curr_inst <= controller_to_socbridge_driver; and trans_st.write.inst.request = '0' then
trans_st.write.inst.request <= controller_to_socbridge_driver.request;
trans_st.write.inst.address <= controller_to_socbridge_driver.address;
trans_st.write.inst.access_count <= controller_to_socbridge_driver.seq_mem_access_count;
else else
end if; end if;
trans_st.is_first_word <= '1'; trans_st.write.is_first_word <= '1';
when SEND => when SEND =>
when SEND_ACCEPTED => if trans_st.write.inst.access_count mod 256 = 0 then
trans_st.curr_inst.seq_mem_access_count <= trans_st.curr_inst.seq_mem_access_count - 128; trans_st.write.is_first_word <= '1';
when AWAIT => elsif st.last_sent_transaction = READ or st.last_sent_transaction = READ_ADD
if trans_st.curr_inst.seq_mem_access_count <= 0 and st.curr_state = IDLE then or next_tx_transaction = READ or next_tx_transaction = READ_ADD then
trans_st.curr_inst.request <= '0'; trans_st.write.is_first_word <= '1';
trans_st.curr_inst.address <= (others => '0'); else
trans_st.curr_inst.seq_mem_access_count <= 0; trans_st.write.is_first_word <= '0';
trans_st.curr_inst.instruction <= NO_OP; end if;
when SEND_ACCEPTED =>
trans_st.write.inst.access_count <= trans_st.write.inst.access_count - MAX_PKT_SIZE;
trans_st.write.inst.address <= std_logic_vector(unsigned(trans_st.write.inst.address) + MAX_PKT_SIZE);
when AWAIT =>
if ((ip_to_socbridge_driver.fifo.used_slots = 0 and ip_to_socbridge_driver.flush = '1')
or trans_st.write.inst.access_count <= 0)
and st.tx_state = TX_W_BODY then
trans_st.write.inst <= ctrl_inst_reset_vec;
end if;
if trans_st.write.inst.access_count mod 256 = 0 then
trans_st.write.is_first_word <= '1';
elsif st.last_sent_transaction = READ or st.last_sent_transaction = READ_ADD
or next_tx_transaction = READ or next_tx_transaction = READ_ADD then
trans_st.write.is_first_word <= '1';
else
trans_st.write.is_first_word <= '0';
end if;
when others =>
end case;
case trans_st.read.state is
when IDLE =>
if controller_to_socbridge_driver.request = '1' and controller_to_socbridge_driver.instruction = READ then
trans_st.read.inst.request <= controller_to_socbridge_driver.request;
trans_st.read.inst.address <= controller_to_socbridge_driver.address;
trans_st.read.inst.access_count <= controller_to_socbridge_driver.seq_mem_access_count;
else
end if;
trans_st.read.is_first_word <= '1';
when SEND =>
if trans_st.read.inst.access_count mod 256 = 0 then
trans_st.read.is_first_word <= '1';
elsif st.last_sent_transaction = WRITE or st.last_sent_transaction = WRITE_ADD
or next_tx_transaction = WRITE or next_tx_transaction = WRITE_ADD then
trans_st.read.is_first_word <= '1';
else
trans_st.read.is_first_word <= '0';
end if;
when SEND_ACCEPTED =>
trans_st.read.inst.access_count <= trans_st.read.inst.access_count - MAX_PKT_SIZE;
trans_st.read.inst.address <= std_logic_vector(unsigned(trans_st.read.inst.address) + MAX_PKT_SIZE);
when AWAIT =>
if (ip_to_socbridge_driver.flush = '1' or trans_st.read.inst.access_count <= 0) and st.tx_state = IDLE then
trans_st.read.inst <= ctrl_inst_reset_vec;
end if;
if trans_st.read.inst.access_count mod 256 = 0 then
trans_st.read.is_first_word <= '1';
elsif st.last_sent_transaction = WRITE or st.last_sent_transaction = WRITE_ADD
or next_tx_transaction = WRITE or next_tx_transaction = WRITE_ADD then
trans_st.read.is_first_word <= '1';
else
trans_st.read.is_first_word <= '0';
end if; end if;
trans_st.is_first_word <= '0';
when others => when others =>
end case; end case;
end if; end if;

View File

@ -0,0 +1,220 @@
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
use IEEE.MATH_REAL.all;
library gan_ganimede;
use gan_ganimede.io_types.all;
package socbridge_driver_pkg is
subtype command_size_t is integer range 0 to 128;
constant MAX_IN_FLIGHT : integer := 1;
type transaction_t is
(NO_OP, WRITE_ADD, WRITE, READ_ADD, READ, P_ERR, WRITE_ACK, READ_RESPONSE);
type rx_state_t is
(IDLE, ADDR1, ADDR2, ADDR3, ADDR4, RX_AWAIT,
RX_R_BODY, RX_HEADER, RX_W_BODY);
type tx_state_t is
(IDLE, ADDR1, ADDR2, ADDR3, ADDR4,
TX_HEADER, TX_W_BODY, TX_R_BODY);
--- TRANSLATOR ---
type ctrl_inst_state_t is (IDLE, SEND, SEND_ACCEPTED, AWAIT);
type ctrl_inst_t is record
request : std_logic;
address : std_logic_vector(address_width - 1 downto 0);
access_count : integer;
end record ctrl_inst_t;
type ctrl_inst_state_rec_t is record
inst : ctrl_inst_t;
state : ctrl_inst_state_t;
is_first_word : std_logic;
end record ctrl_inst_state_rec_t;
type translator_state_t is record
read: ctrl_inst_state_rec_t;
write: ctrl_inst_state_rec_t;
end record translator_state_t;
type ext_protocol_t is record
data : std_logic_vector(interface_inst.socbridge.payload_width - 1 downto 0);
clk : std_logic;
parity : std_logic;
end record ext_protocol_t;
type state_rec_t is record
rx_transaction : transaction_t;
tx_transaction : transaction_t;
rx_state: rx_state_t;
tx_state: tx_state_t;
ext_to_socbridge_driver_reg, socbridge_driver_to_ext_reg : ext_protocol_t;
tx_stage, rx_stage : NATURAL;
tx_data_size, rx_data_size : integer;
tx_addr : std_logic_vector(31 downto 0);
read_in_flight : boolean;
write_in_flight : boolean;
last_sent_transaction : transaction_t;
manager_addr : std_logic_vector(31 downto 0);
manager_data : std_logic_vector(31 downto 0);
end record state_rec_t;
impure function calc_parity(
d : STD_LOGIC_VECTOR(interface_inst.socbridge.payload_width - 1 downto 0)
) return std_logic;
pure function create_io_type_out_from_ext_protocol(
input: ext_protocol_t
) return socbridge_driver_to_ext_t;
function to_string ( a: std_logic_vector) return string;
pure function get_header_bits(transaction : transaction_t; caused_by: transaction_t) return std_logic_vector;
pure function get_size_bits(size : command_size_t) return std_logic_vector;
pure function get_size_bits_sim(size : command_size_t) return std_logic_vector;
constant ctrl_inst_reset_vec : ctrl_inst_t := (
request => '0',
address => (others => '0'),
access_count => 0
);
constant translator_reset_vec : translator_state_t := (
read => (
state => IDLE,
inst => ctrl_inst_reset_vec,
is_first_word => '1'
),
write => (
state => IDLE,
inst => ctrl_inst_reset_vec,
is_first_word => '1'
)
);
constant ext_protocol_reset_vec : ext_protocol_t := (
data => (others => '0'),
clk => '0',
parity => '1'
);
constant st_reset_vec : state_rec_t := (
ext_to_socbridge_driver_reg => ext_protocol_reset_vec,
socbridge_driver_to_ext_reg => ext_protocol_reset_vec,
tx_state => IDLE,
rx_state => IDLE,
tx_stage => 0,
rx_stage => 0,
tx_transaction => NO_OP,
rx_transaction => NO_OP,
tx_data_size => 0,
rx_data_size => 0,
tx_addr => (others => '0'),
manager_addr => (others => '0'),
manager_data => (others => '0'),
read_in_flight => false,
write_in_flight => false,
last_sent_transaction => NO_OP
);
end package socbridge_driver_pkg;
package body socbridge_driver_pkg is
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;
impure function calc_parity(
d : STD_LOGIC_VECTOR(interface_inst.socbridge.payload_width - 1 downto 0)
) return std_logic is
variable parity : std_logic;
begin
parity := d(0);
for x in integer'(1) to d'length - 1 loop
parity := parity xor d(x);
end loop;
return not parity;
end function;
pure function create_io_type_out_from_ext_protocol(
input : ext_protocol_t
) return socbridge_driver_to_ext_t is
variable val : socbridge_driver_to_ext_t;
begin
val.payload:= input.data;
val.control(1) := input.clk;
val.control(0) := input.parity;
return val;
end function;
pure function get_header_bits(transaction : transaction_t; caused_by : transaction_t)
return std_logic_vector is
variable val : std_logic_vector(4 downto 0);
begin
val := "11111";
if transaction = NO_OP then
val := "00000";
elsif transaction = WRITE_ADD then
val := "10000";
elsif transaction = WRITE then
val := "10100";
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;
end function;
pure function get_size_bits(size: command_size_t)
return std_logic_vector is
variable val : std_logic_vector(2 downto 0);
begin
if size > 2**6 then
val := "111";
elsif size > 2**5 then
val := "110";
elsif size > 2**4 then
val := "101";
elsif size > 2**3 then
val := "100";
elsif size > 2**2 then
val := "011";
elsif size > 2**1 then
val := "010";
elsif size > 2**0 then
val := "001";
elsif size >= 0 then
val := "000";
end if;
return val;
end function;
pure function get_size_bits_sim(size: command_size_t)
return std_logic_vector is
variable pow : integer;
variable val : std_logic_vector(2 downto 0);
begin
pow := integer(CEIL(sqrt(Real(size))));
val := std_logic_vector(TO_UNSIGNED(size - 1, 3));
return val;
end function;
end package body socbridge_driver_pkg;

View File

@ -1,11 +1,10 @@
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 gan_ganimede;
use work.socbridge_driver_tb_pkg.all; use gan_ganimede.io_types.all;
library ganimede; library gan_socbridge;
use ganimede.io_types.all;
library socbridge;
entity socbridge_driver_tb is entity socbridge_driver_tb is
@ -14,319 +13,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.ready <= '0';
buffer_to_socbridge_driver.write_enable_out <= '0'; ip_to_socbridge_driver.valid <= '1';
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.ready = '1';
wait until falling_edge(clk); ip_to_socbridge_driver.data <= 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

@ -1,156 +0,0 @@
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
use IEEE.MATH_REAL.all;
library ganimede;
use ganimede.io_types.all;
package socbridge_driver_tb_pkg is
subtype command_size_t is integer range 0 to 128;
type command_t is
(NO_OP, WRITE_ADD, WRITE, READ_ADD, READ, P_ERR);
type response_t is
(NO_OP, WRITE_ACK, READ_RESPONSE);
type state_t is
(IDLE, ADDR1, ADDR2, ADDR3, ADDR4,
TX_HEADER, TX_BODY, TX_ACK,
RX_HEADER, RX_RESPONSE, RX_BODY);
--- TRANSLATOR ---
type translator_state_t is (IDLE, SEND, SEND_ACCEPTED, AWAIT);
type translator_state_rec_t is record
curr_inst : controller_to_socbridge_driver_t;
curr_state : translator_state_t;
is_first_word : std_logic;
end record translator_state_rec_t;
type ext_protocol_t is record
data : std_logic_vector(interface_inst.socbridge.payload_width - 1 downto 0);
clk : std_logic;
parity : std_logic;
end record ext_protocol_t;
type state_rec_t is record
curr_state: state_t;
ext_to_socbridge_driver_reg, socbridge_driver_to_ext_reg : ext_protocol_t;
write_stage, read_stage : NATURAL;
curr_cmd : command_t;
curr_cmd_size: integer;
curr_addr : std_logic_vector(31 downto 0);
end record state_rec_t;
impure function calc_parity(
d : STD_LOGIC_VECTOR(interface_inst.socbridge.payload_width - 1 downto 0)
) return std_logic;
pure function create_io_type_out_from_ext_protocol(
input: ext_protocol_t
) return socbridge_driver_to_ext_t;
function to_string ( a: std_logic_vector) return string;
pure function get_cmd_bits(command : command_t) return std_logic_vector;
pure function get_size_bits(size : command_size_t) return std_logic_vector;
pure function get_size_bits_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;
package body socbridge_driver_tb_pkg is
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;
impure function calc_parity(
d : STD_LOGIC_VECTOR(interface_inst.socbridge.payload_width - 1 downto 0)
) return std_logic is
variable parity : std_logic;
begin
parity := d(0);
for x in integer'(1) to d'length - 1 loop
parity := parity xor d(x);
end loop;
return not parity;
end function;
pure function create_io_type_out_from_ext_protocol(
input : ext_protocol_t
) return socbridge_driver_to_ext_t is
variable val : socbridge_driver_to_ext_t;
begin
val.payload:= input.data;
val.control(1) := input.clk;
val.control(0) := input.parity;
return val;
end function;
pure function get_cmd_bits(command : command_t)
return std_logic_vector is
variable val : std_logic_vector(4 downto 0);
begin
with command select
val := "00000" when NO_OP,
"10000" when WRITE_ADD,
"10100" when WRITE,
"11000" when READ_ADD,
"11100" when READ,
"01001" when P_ERR,
"11111" when others;
return val;
end function;
pure function get_size_bits(size: command_size_t)
return std_logic_vector is
variable val : std_logic_vector(2 downto 0);
begin
if size > 2**6 then
val := "111";
elsif size > 2**5 then
val := "110";
elsif size > 2**4 then
val := "101";
elsif size > 2**3 then
val := "100";
elsif size > 2**2 then
val := "011";
elsif size > 2**1 then
val := "010";
elsif size > 2**0 then
val := "001";
elsif size >= 0 then
val := "000";
end if;
return val;
end function;
pure function get_size_bits_sim(size: command_size_t)
return std_logic_vector is
variable pow : integer;
variable val : std_logic_vector(2 downto 0);
begin
pow := integer(CEIL(sqrt(Real(size))));
val := std_logic_vector(TO_UNSIGNED(size - 1, 3));
return val;
end function;
end package body socbridge_driver_tb_pkg;

130
src/software/simple_test.c Normal file
View File

@ -0,0 +1,130 @@
#include <stdint.h>
#include <stdio.h>
#include <stdarg.h>
#include <sys/types.h>
#define debug(format, ...) printf("DEBUG - " format "\n",##__VA_ARGS__)
volatile u_int32_t ganimede_read_data[1024] __attribute__ ((aligned (1024)));
volatile u_int32_t ganimede_write_data[1024] __attribute__ ((aligned (1024)));
const uint32_t size_bias = 10;
enum OpType{ WRITE_ONE_SHOT, WRITE_LOOP, READ_ONE_SHOT, READ_LOOP };
int ceil_log2(unsigned long long x)
{
static const unsigned long long t[6] = {
0xFFFFFFFF00000000ull,
0x00000000FFFF0000ull,
0x000000000000FF00ull,
0x00000000000000F0ull,
0x000000000000000Cull,
0x0000000000000002ull
};
int y = (((x & (x - 1)) == 0) ? 0 : 1);
int j = 32;
int i;
for (i = 0; i < 6; i++) {
int k = (((x & t[i]) == 0) ? 0 : j);
y += k;
x >>= k;
j >>= 1;
}
return y;
}
// Address will forcibly floored to be aligned to KB.
// byteSize must be smaller than
u_int32_t create_ganimede_instruction(u_int32_t address, enum OpType optype, u_int32_t byteSize){
u_int32_t addressPart = (address & 0xfffffc00);
u_int32_t optypePart = 0x00000000;
u_int32_t byteSizePart = 0;
byteSize = byteSize > 1 << 25? 1<<25 :byteSize;
byteSizePart = ceil_log2(byteSize) - size_bias;
byteSizePart = (byteSizePart & 0xf) << 6;
switch (optype) {
case WRITE_ONE_SHOT: optypePart |= 0b001000; break;
case WRITE_LOOP: optypePart |= 0b011000; break;
case READ_ONE_SHOT: optypePart |= 0b000000; break;
case READ_LOOP: optypePart |= 0b010000; break;
}
return addressPart | optypePart | byteSizePart;
}
char* show_optype(u_int32_t optype){
switch ((optype & 0b111000) >> 3) {
case 0b001: return "WRITE_ONE_SHOT"; break;
case 0b011: return "WRITE_LOOP"; break;
case 0b000: return "READ_ONE_SHOT"; break;
case 0b010: return "READ_LOOP"; break;
}
return "UNKNOWN";
}
void print_gan_inst(u_int32_t inst){
int size = ((inst & 0b1111000000) >> 6) + size_bias;
if (size >= 30){
debug( "command vector is | address: %#011x\n"
" | operation: %s\n"
" | size: %d MB\n"
, inst & 0xfffffc00, show_optype(inst), 1 << (size - 30));
} else if (size >= 20){
debug( "command vector is | address: %#011x\n"
" | operation: %s\n"
" | size: %d MB\n"
, inst & 0xfffffc00, show_optype(inst), 1 << (size - 20));
} else if(size >= 10){
debug( "command vector is | address: %#011x\n"
" | operation: %s\n"
" | size: %d KB\n"
, inst & 0xfffffc00, show_optype(inst), 1 << (size - 10));
} else {
debug( "command vector is | address: %#011x\n"
" | operation: %s\n"
" | size: %d B\n"
, inst & 0xfffffc00, show_optype(inst), 1 << size);
}
}
int main(){
volatile u_int32_t* data_ptr = (u_int32_t*) 0x10000000;
volatile u_int32_t* cfg_ptr = (u_int32_t*) 0x80000d00;
//for(int i = 0; i < 10; i++){
// ((int*) (0x80000000))[i] = 0x12345678 + i;
//}
printf("\n");
debug("Initializing socbridge and GANIMEDE");
debug("setting socbridge config");
// Setting omaxsz = 7 and orxqen = true
cfg_ptr[0] = 0x0001bfff;
cfg_ptr[1] = 0x00000000;
debug("setting parif config.");
cfg_ptr[4] = 0x00000071;
cfg_ptr[5] = 0x00001002;
debug("initializing test data to read");
for(int i = 0; i < sizeof(ganimede_read_data)/sizeof(u_int32_t); i++){
ganimede_read_data[i] = i;
}
debug("Finished initializing\n");
debug("Sending commands to GANIMEDE");
debug("creating and sending a read instruction");
int readInst = create_ganimede_instruction((u_int32_t) &ganimede_read_data[0], READ_ONE_SHOT, 1024 );
print_gan_inst(readInst);
//data_ptr[0] = readInst;
debug("creating and sending a write instruction");
int writeInst = create_ganimede_instruction((u_int32_t) &ganimede_write_data[0], WRITE_ONE_SHOT, 1024);
print_gan_inst(writeInst);
//data_ptr[1] = writeInst;
debug("Finished sending commands\n");
return 0;
}

View File

@ -2,16 +2,34 @@
standard = "1993" 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 = [ gan_ganimede.files = [
'ganimede/io_type_pkg.vhd' 'ganimede/io_type_pkg.vhd',
'ganimede/ganimede.vhd'
] ]
socbridge.files = [ gan_socbridge.files = [
'socbridge/*.vhd' 'socbridge/*.vhd'
] ]
gan_dummy_ip.files = [
controller.files = [ 'dummy_ip/*.vhd'
]
gan_controller.files = [
'controller/*.vhd', 'controller/*.vhd',
] ]
gan_manager.files = [
'manager/*.vhd',
]
gan_buffer.files = [
'fifo_buffer/*.vhd',
]
grlib.files = [
'grlib-com-nx-2024.4-b4295/lib/grlib/**/*.vhd',
]
techmap.files = [
'grlib-com-nx-2024.4-b4295/lib/techmap/**/*.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