add cursed BRAM core implementation

This commit is contained in:
Fischer Moseley 2023-04-10 14:38:29 -04:00
parent 1710da6f87
commit 12f498dc9a
8 changed files with 1002 additions and 0 deletions

View File

@ -31,6 +31,13 @@ auto_gen:
# Functional Simulation
functional_sim: io_core_tb logic_analyzer_tb bit_fifo_tb bridge_rx_tb bridge_tx_tb lut_ram_tb
bram_core_tb:
iverilog -g2012 -o sim.out -y src/manta \
test/functional_sim/bram_core_tb/bram_core_tb.sv \
test/functional_sim/bram_core_tb/bram_core.v
vvp sim.out
rm sim.out
io_core_tb:
iverilog -g2012 -o sim.out -y src/manta \
test/functional_sim/io_core_tb/io_core_tb.sv \

View File

@ -0,0 +1,301 @@
import atexit
import getopt
import os
import subprocess
import signal
import sys
import time
import pathlib
import platform
progname = sys.argv[0]
diagnostics = False
quiet = False
verbose = False
port = 80
machine = "eecs-digital-56.mit.edu"
projectdir = "."
of = "obj"
p = False
user = "builder"
outfile = f"{of}/out.bit"
logfile = f"{of}/build.log"
synthrpt = [
"report_timing",
"report_timing_summary",
"report_utilization",
]
placerpt = synthrpt.copy()
placerpt.extend(["report_clock_utilization"])
routerpt = [
"report_drc",
"report_power",
"report_route_status",
"report_timing",
"report_timing_summary",
]
usagestr = f"""
{progname}: build SystemVerilog code remotely for 2022 6.205 labs
usage: {progname} [-dqv] [-m machine] [-p projectdir] [-o dir]
options:
-d: emit additional diagnostics during synthesis/implementation
-q: quiet: do not generate any vivado logs except for errors.
-v: be verbose (for debugging stuffs / if you see a bug)
-m: override the DNS name queried to perform the build. use with care.
-p: build the project located in projectdir (default is '.')
-o: set the output products directory (default is {of})
"""
def debuglog(s):
if verbose:
print(s)
def usage():
print(usagestr)
sys.exit(1)
def getargs():
global diagnostics
global quiet
global machine
global logfile
global outfile
global projectdir
global of
global verbose
try:
opts, args = getopt.getopt(sys.argv[1:], "dm:o:p:qv")
except getopt.GetoptError as err:
print(err)
usage()
if args:
usage()
for o, v in opts:
if o == "-d":
diagnostics = True
elif o == "-q":
quiet = True
elif o == "-m":
machine = v
elif o == "-p":
projectdir = v
elif o == "-o":
of = v
elif o == "-v":
verbose = True
else:
print(f"unrecognized option {o}")
usage()
outfile = f"{of}/out.bit"
logfile = f"{of}/build.log"
def make_posix(path):
return str(pathlib.Path(path).as_posix())
def regfiles():
ftt = {}
debuglog(f"projectdir is {projectdir}")
for dirpath, subdirs, files in os.walk(projectdir):
if (
"src" not in dirpath
and "xdc" not in dirpath
and "data" not in dirpath
and "ip" not in dirpath
):
continue
if dirpath.startswith("./"):
dirpath = dirpath[2:]
for file in files:
fpath = os.path.join(dirpath, file)
debuglog(f"considering {fpath}")
fpath = make_posix(fpath)
if file.lower().endswith(".v"):
ftt[fpath] = "source"
elif file.lower().endswith(".sv"):
ftt[fpath] = "source"
elif file.lower().endswith(".vh"):
ftt[fpath] = "source"
elif file.lower().endswith(".svh"):
ftt[fpath] = "source"
elif file.lower().endswith(".xdc"):
ftt[fpath] = "xdc"
elif file.lower().endswith(".mem"):
ftt[fpath] = "mem"
elif file.lower().endswith(".xci"):
ftt[fpath] = "ip"
elif file.lower().endswith(".prj"):
ftt[fpath] = "mig"
debuglog(f"elaborated file list {ftt}")
return ftt
# messages are newline delineated per lab-bs.1
# utilize this to cheat a little bit
def spqsend(p, msg):
debuglog(f"writing {len(msg)} bytes over the wire")
debuglog(f"full message: {msg}")
p.stdin.write(msg + b"\n")
p.stdin.flush()
def spsend(p, msg):
debuglog(f"running {msg}")
p.stdin.write((msg + "\n").encode())
p.stdin.flush()
def sprecv(p):
l = p.stdout.readline().decode()
debuglog(f"got {l}")
return l
def xsprecv(p):
l = sprecv(p)
if l.startswith("ERR"):
print("received unexpected server error!")
print(l)
sys.exit(1)
return l
def spstart(xargv):
debuglog(f"spawning {xargv}")
p = subprocess.PIPE
return subprocess.Popen(xargv, stdin=p, stdout=p, stderr=p)
def copyfiles(p, ftt):
for f, t in ftt.items():
fsize = os.path.getsize(f)
with open(f, "rb") as fd:
spsend(p, f"write {f} {fsize}")
time.sleep(0.1) # ?
spqsend(p, fd.read())
xsprecv(p)
spsend(p, f"type {f} {t}")
xsprecv(p)
# size message returns ... %zu bytes
def readfile(p, file, targetfile):
spsend(p, f"size {file}")
size = int(xsprecv(p).split()[-2])
spsend(p, f"read {file}")
with open(targetfile, "wb+") as fd:
fd.write(p.stdout.read(size))
xsprecv(p)
def build(p):
cmd = "build"
if diagnostics:
cmd += " -d"
if quiet:
cmd += " -q"
cmd += f" obj"
print(f"Output target will be {outfile}")
spsend(p, cmd)
print("Building your code ... (this may take a while, be patient)")
result = sprecv(p)
if result.startswith("ERR"):
print("Something went wrong!")
else:
readfile(p, "obj/out.bit", outfile)
print(f"Build succeeded, output at {outfile}")
readfile(p, "obj/build.log", logfile)
print(f"Log file available at {logfile}")
if diagnostics:
for rpt in synthrpt:
readfile(p, f"obj/synthrpt_{rpt}.rpt", f"{of}/synthrpt_{rpt}.rpt")
for rpt in placerpt:
readfile(p, f"obj/placerpt_{rpt}.rpt", f"{of}/placerpt_{rpt}.rpt")
for rpt in routerpt:
readfile(p, f"obj/routerpt_{rpt}.rpt", f"{of}/routerpt_{rpt}.rpt")
print(f"Diagnostics available in {of}")
def main():
global p
getargs()
ftt = regfiles()
if not os.path.isdir(of):
print(f"output path {of} does not exist! create it or use -o?")
usage()
if platform.system() == "Darwin" or platform.system() == "Linux":
xargv = [
"ssh",
"-p",
f"{port}",
"-o",
"StrictHostKeyChecking=no",
"-o",
"UserKnownHostsFile=/dev/null",
]
elif platform.system() == "Windows":
xargv = [
"ssh",
"-p",
f"{port}",
"-o",
"StrictHostKeyChecking=no",
"-o",
"UserKnownHostsFile=nul",
]
else:
raise RuntimeError(
"Your OS is not recognized, unsure of how to format SSH command."
)
xargv.append(f"{user}@{machine}")
p = spstart(xargv)
spsend(p, "help")
result = xsprecv(p)
debuglog(result)
copyfiles(p, ftt)
build(p)
spsend(p, "exit")
p.wait()
if __name__ == "__main__":
try:
main()
except (Exception, KeyboardInterrupt) as e:
if p:
debuglog("killing ssh")
os.kill(p.pid, signal.SIGINT)
p.wait()
raise e

View File

@ -0,0 +1,51 @@
// Xilinx True Dual Port RAM, Read First, Dual Clock
// This code implements a parameterizable true dual port memory (both ports can read and write).
// The behavior of this RAM is when data is written, the prior memory contents at the write
// address are presented on the output port. If the output data is
// not needed during writes or the last read value is desired to be retained,
// it is suggested to use a no change RAM as it is more power efficient.
// If a reset or enable is not necessary, it may be tied off or removed from the code.
// Modified from the xilinx_true_dual_port_read_first_2_clock_ram verilog language template.
module dual_port_bram #(
parameter RAM_WIDTH = 0,
parameter RAM_DEPTH = 0
) (
input wire [$clog2(RAM_DEPTH-1)-1:0] addra,
input wire [$clog2(RAM_DEPTH-1)-1:0] addrb,
input wire [RAM_WIDTH-1:0] dina,
input wire [RAM_WIDTH-1:0] dinb,
input wire clka,
input wire clkb,
input wire wea,
input wire web,
output wire [RAM_WIDTH-1:0] douta,
output wire [RAM_WIDTH-1:0] doutb
);
reg [RAM_WIDTH-1:0] BRAM [RAM_DEPTH-1:0];
reg [RAM_WIDTH-1:0] ram_data_a = {RAM_WIDTH{1'b0}};
reg [RAM_WIDTH-1:0] ram_data_b = {RAM_WIDTH{1'b0}};
always @(posedge clka) begin
if (wea) BRAM[addra] <= dina;
ram_data_a <= BRAM[addra];
end
always @(posedge clkb) begin
if (web) BRAM[addrb] <= dinb;
ram_data_b <= BRAM[addrb];
end
// Add a 2 clock cycle read latency to improve clock-to-out timing
reg [RAM_WIDTH-1:0] douta_reg = {RAM_WIDTH{1'b0}};
reg [RAM_WIDTH-1:0] doutb_reg = {RAM_WIDTH{1'b0}};
always @(posedge clka) douta_reg <= ram_data_a;
always @(posedge clkb) doutb_reg <= ram_data_b;
assign douta = douta_reg;
assign doutb = doutb_reg;
endmodule

View File

@ -0,0 +1,27 @@
`default_nettype none
`timescale 1ns / 1ps
module top_level (
input wire clk,
input wire [7:0] ja,
input wire [7:0] jb,
input wire [1:0] jc,
output logic [1:0] jd);
dual_port_bram #(.RAM_DEPTH(256), .RAM_WIDTH(2)) bram_0 (
.clka(clk),
.addra(ja),
.dina(jc),
.douta(),
.wea(1'b1),
.clkb(clk),
.addrb(jb),
.dinb(8'b0),
.doutb(jd),
.web(1'b0)
);
endmodule
`default_nettype wire

View File

@ -0,0 +1,260 @@
## R1.0 2019-08-27
## Updated by jodalyst in 2020-2022
## all inputs/outputs changed to lowercase; arrays start with zero.
## system clock renamed to clk
## ja, jb, jc, jd renamed to 0-7
## xa port renamed 0-3
## seven segments renamed to a,b,c,d,e,f,dp
## This file is a general .xdc for the Nexys4 DDR Rev. C
## To use it in a project:
## - uncomment the lines corresponding to used pins
## - rename the used ports (in each line, after get_ports) according to the top level signal names in the project
## Clock signal - uncomment _both_ of these lines to create clk_100mhz
set_property -dict { PACKAGE_PIN E3 IOSTANDARD LVCMOS33 } [get_ports { clk }]; #IO_L12P_T1_MRCC_35 Sch=clk
create_clock -add -name sys_clk_pin -period 10.00 -waveform {0 5} [get_ports {clk}];
##Switches
# set_property -dict { PACKAGE_PIN J15 IOSTANDARD LVCMOS33 } [get_ports { sw[0] }]; #IO_L24N_T3_RS0_15 Sch=sw[0]
# set_property -dict { PACKAGE_PIN L16 IOSTANDARD LVCMOS33 } [get_ports { sw[1] }]; #IO_L3N_T0_DQS_EMCCLK_14 Sch=sw[1]
# set_property -dict { PACKAGE_PIN M13 IOSTANDARD LVCMOS33 } [get_ports { sw[2] }]; #IO_L6N_T0_D08_VREF_14 Sch=sw[2]
# set_property -dict { PACKAGE_PIN R15 IOSTANDARD LVCMOS33 } [get_ports { sw[3] }]; #IO_L13N_T2_MRCC_14 Sch=sw[3]
# set_property -dict { PACKAGE_PIN R17 IOSTANDARD LVCMOS33 } [get_ports { sw[4] }]; #IO_L12N_T1_MRCC_14 Sch=sw[4]
# set_property -dict { PACKAGE_PIN T18 IOSTANDARD LVCMOS33 } [get_ports { sw[5] }]; #IO_L7N_T1_D10_14 Sch=sw[5]
# set_property -dict { PACKAGE_PIN U18 IOSTANDARD LVCMOS33 } [get_ports { sw[6] }]; #IO_L17N_T2_A13_D29_14 Sch=sw[6]
# set_property -dict { PACKAGE_PIN R13 IOSTANDARD LVCMOS33 } [get_ports { sw[7] }]; #IO_L5N_T0_D07_14 Sch=sw[7]
# set_property -dict { PACKAGE_PIN T8 IOSTANDARD LVCMOS18 } [get_ports { sw[8] }]; #IO_L24N_T3_34 Sch=sw[8]
# set_property -dict { PACKAGE_PIN U8 IOSTANDARD LVCMOS18 } [get_ports { sw[9] }]; #IO_25_34 Sch=sw[9]
# set_property -dict { PACKAGE_PIN R16 IOSTANDARD LVCMOS33 } [get_ports { sw[10] }]; #IO_L15P_T2_DQS_RDWR_B_14 Sch=sw[10]
# set_property -dict { PACKAGE_PIN T13 IOSTANDARD LVCMOS33 } [get_ports { sw[11] }]; #IO_L23P_T3_A03_D19_14 Sch=sw[11]
# set_property -dict { PACKAGE_PIN H6 IOSTANDARD LVCMOS33 } [get_ports { sw[12] }]; #IO_L24P_T3_35 Sch=sw[12]
# set_property -dict { PACKAGE_PIN U12 IOSTANDARD LVCMOS33 } [get_ports { sw[13] }]; #IO_L20P_T3_A08_D24_14 Sch=sw[13]
# set_property -dict { PACKAGE_PIN U11 IOSTANDARD LVCMOS33 } [get_ports { sw[14] }]; #IO_L19N_T3_A09_D25_VREF_14 Sch=sw[14]
# set_property -dict { PACKAGE_PIN V10 IOSTANDARD LVCMOS33 } [get_ports { sw[15] }]; #IO_L21P_T3_DQS_14 Sch=sw[15]
## LEDs
# set_property -dict { PACKAGE_PIN H17 IOSTANDARD LVCMOS33 } [get_ports { led[0] }]; #IO_L18P_T2_A24_15 Sch=led[0]
# set_property -dict { PACKAGE_PIN K15 IOSTANDARD LVCMOS33 } [get_ports { led[1] }]; #IO_L24P_T3_RS1_15 Sch=led[1]
# set_property -dict { PACKAGE_PIN J13 IOSTANDARD LVCMOS33 } [get_ports { led[2] }]; #IO_L17N_T2_A25_15 Sch=led[2]
# set_property -dict { PACKAGE_PIN N14 IOSTANDARD LVCMOS33 } [get_ports { led[3] }]; #IO_L8P_T1_D11_14 Sch=led[3]
# set_property -dict { PACKAGE_PIN R18 IOSTANDARD LVCMOS33 } [get_ports { led[4] }]; #IO_L7P_T1_D09_14 Sch=led[4]
# set_property -dict { PACKAGE_PIN V17 IOSTANDARD LVCMOS33 } [get_ports { led[5] }]; #IO_L18N_T2_A11_D27_14 Sch=led[5]
# set_property -dict { PACKAGE_PIN U17 IOSTANDARD LVCMOS33 } [get_ports { led[6] }]; #IO_L17P_T2_A14_D30_14 Sch=led[6]
# set_property -dict { PACKAGE_PIN U16 IOSTANDARD LVCMOS33 } [get_ports { led[7] }]; #IO_L18P_T2_A12_D28_14 Sch=led[7]
# set_property -dict { PACKAGE_PIN V16 IOSTANDARD LVCMOS33 } [get_ports { led[8] }]; #IO_L16N_T2_A15_D31_14 Sch=led[8]
# set_property -dict { PACKAGE_PIN T15 IOSTANDARD LVCMOS33 } [get_ports { led[9] }]; #IO_L14N_T2_SRCC_14 Sch=led[9]
# set_property -dict { PACKAGE_PIN U14 IOSTANDARD LVCMOS33 } [get_ports { led[10] }]; #IO_L22P_T3_A05_D21_14 Sch=led[10]
# set_property -dict { PACKAGE_PIN T16 IOSTANDARD LVCMOS33 } [get_ports { led[11] }]; #IO_L15N_T2_DQS_DOUT_CSO_B_14 Sch=led[11]
# set_property -dict { PACKAGE_PIN V15 IOSTANDARD LVCMOS33 } [get_ports { led[12] }]; #IO_L16P_T2_CSI_B_14 Sch=led[12]
# set_property -dict { PACKAGE_PIN V14 IOSTANDARD LVCMOS33 } [get_ports { led[13] }]; #IO_L22N_T3_A04_D20_14 Sch=led[13]
# set_property -dict { PACKAGE_PIN V12 IOSTANDARD LVCMOS33 } [get_ports { led[14] }]; #IO_L20N_T3_A07_D23_14 Sch=led[14]
# set_property -dict { PACKAGE_PIN V11 IOSTANDARD LVCMOS33 } [get_ports { led[15] }]; #IO_L21N_T3_DQS_A06_D22_14 Sch=led[15]
# set_property -dict { PACKAGE_PIN R12 IOSTANDARD LVCMOS33 } [get_ports { led16_b }]; #IO_L5P_T0_D06_14 Sch=led16_b
# set_property -dict { PACKAGE_PIN M16 IOSTANDARD LVCMOS33 } [get_ports { led16_g }]; #IO_L10P_T1_D14_14 Sch=led16_g
# set_property -dict { PACKAGE_PIN N15 IOSTANDARD LVCMOS33 } [get_ports { led16_r }]; #IO_L11P_T1_SRCC_14 Sch=led16_r
# set_property -dict { PACKAGE_PIN G14 IOSTANDARD LVCMOS33 } [get_ports { led17_b }]; #IO_L15N_T2_DQS_ADV_B_15 Sch=led17_b
# set_property -dict { PACKAGE_PIN R11 IOSTANDARD LVCMOS33 } [get_ports { led17_g }]; #IO_0_14 Sch=led17_g
# set_property -dict { PACKAGE_PIN N16 IOSTANDARD LVCMOS33 } [get_ports { led17_r }]; #IO_L11N_T1_SRCC_14 Sch=led17_r
##7 segment display
# set_property -dict { PACKAGE_PIN T10 IOSTANDARD LVCMOS33 } [get_ports { ca }]; #IO_L24N_T3_A00_D16_14 Sch=ca
# set_property -dict { PACKAGE_PIN R10 IOSTANDARD LVCMOS33 } [get_ports { cb }]; #IO_25_14 Sch=cb
# set_property -dict { PACKAGE_PIN K16 IOSTANDARD LVCMOS33 } [get_ports { cc }]; #IO_25_15 Sch=cc
# set_property -dict { PACKAGE_PIN K13 IOSTANDARD LVCMOS33 } [get_ports { cd }]; #IO_L17P_T2_A26_15 Sch=cd
# set_property -dict { PACKAGE_PIN P15 IOSTANDARD LVCMOS33 } [get_ports { ce }]; #IO_L13P_T2_MRCC_14 Sch=ce
# set_property -dict { PACKAGE_PIN T11 IOSTANDARD LVCMOS33 } [get_ports { cf }]; #IO_L19P_T3_A10_D26_14 Sch=cf
# set_property -dict { PACKAGE_PIN L18 IOSTANDARD LVCMOS33 } [get_ports { cg }]; #IO_L4P_T0_D04_14 Sch=cg
# set_property -dict { PACKAGE_PIN H15 IOSTANDARD LVCMOS33 } [get_ports { dp }]; #IO_L19N_T3_A21_VREF_15 Sch=dp
# set_property -dict { PACKAGE_PIN J17 IOSTANDARD LVCMOS33 } [get_ports { an[0] }]; #IO_L23P_T3_FOE_B_15 Sch=an[0]
# set_property -dict { PACKAGE_PIN J18 IOSTANDARD LVCMOS33 } [get_ports { an[1] }]; #IO_L23N_T3_FWE_B_15 Sch=an[1]
# set_property -dict { PACKAGE_PIN T9 IOSTANDARD LVCMOS33 } [get_ports { an[2] }]; #IO_L24P_T3_A01_D17_14 Sch=an[2]
# set_property -dict { PACKAGE_PIN J14 IOSTANDARD LVCMOS33 } [get_ports { an[3] }]; #IO_L19P_T3_A22_15 Sch=an[3]
# set_property -dict { PACKAGE_PIN P14 IOSTANDARD LVCMOS33 } [get_ports { an[4] }]; #IO_L8N_T1_D12_14 Sch=an[4]
# set_property -dict { PACKAGE_PIN T14 IOSTANDARD LVCMOS33 } [get_ports { an[5] }]; #IO_L14P_T2_SRCC_14 Sch=an[5]
# set_property -dict { PACKAGE_PIN K2 IOSTANDARD LVCMOS33 } [get_ports { an[6] }]; #IO_L23P_T3_35 Sch=an[6]
# set_property -dict { PACKAGE_PIN U13 IOSTANDARD LVCMOS33 } [get_ports { an[7] }]; #IO_L23N_T3_A02_D18_14 Sch=an[7]
##Buttons
# set_property -dict { PACKAGE_PIN C12 IOSTANDARD LVCMOS33 } [get_ports { cpu_resetn }]; #IO_L3P_T0_DQS_AD1P_15 Sch=cpu_resetn
# set_property -dict { PACKAGE_PIN N17 IOSTANDARD LVCMOS33 } [get_ports { btnc }]; #IO_L9P_T1_DQS_14 Sch=btnc
# set_property -dict { PACKAGE_PIN M18 IOSTANDARD LVCMOS33 } [get_ports { btnu }]; #IO_L4N_T0_D05_14 Sch=btnu
# set_property -dict { PACKAGE_PIN P17 IOSTANDARD LVCMOS33 } [get_ports { btnl }]; #IO_L12P_T1_MRCC_14 Sch=btnl
# set_property -dict { PACKAGE_PIN M17 IOSTANDARD LVCMOS33 } [get_ports { btnr }]; #IO_L10N_T1_D15_14 Sch=btnr
# set_property -dict { PACKAGE_PIN P18 IOSTANDARD LVCMOS33 } [get_ports { btnd }]; #IO_L9N_T1_DQS_D13_14 Sch=btnd
##Pmod Headers
##Pmod Header JA
set_property -dict { PACKAGE_PIN C17 IOSTANDARD LVCMOS33 } [get_ports { ja[0] }]; #IO_L20N_T3_A19_15 Sch=ja[1]
set_property -dict { PACKAGE_PIN D18 IOSTANDARD LVCMOS33 } [get_ports { ja[1] }]; #IO_L21N_T3_DQS_A18_15 Sch=ja[2]
set_property -dict { PACKAGE_PIN E18 IOSTANDARD LVCMOS33 } [get_ports { ja[2] }]; #IO_L21P_T3_DQS_15 Sch=ja[3]
set_property -dict { PACKAGE_PIN G17 IOSTANDARD LVCMOS33 } [get_ports { ja[3] }]; #IO_L18N_T2_A23_15 Sch=ja[4]
set_property -dict { PACKAGE_PIN D17 IOSTANDARD LVCMOS33 } [get_ports { ja[4] }]; #IO_L16N_T2_A27_15 Sch=ja[7]
set_property -dict { PACKAGE_PIN E17 IOSTANDARD LVCMOS33 } [get_ports { ja[5] }]; #IO_L16P_T2_A28_15 Sch=ja[8]
set_property -dict { PACKAGE_PIN F18 IOSTANDARD LVCMOS33 } [get_ports { ja[6] }]; #IO_L22N_T3_A16_15 Sch=ja[9]
set_property -dict { PACKAGE_PIN G18 IOSTANDARD LVCMOS33 } [get_ports { ja[7] }]; #IO_L22P_T3_A17_15 Sch=ja[10]
##Pmod Header JB
set_property -dict { PACKAGE_PIN D14 IOSTANDARD LVCMOS33 } [get_ports { jb[0] }]; #IO_L1P_T0_AD0P_15 Sch=jb[1]
set_property -dict { PACKAGE_PIN F16 IOSTANDARD LVCMOS33 } [get_ports { jb[1] }]; #IO_L14N_T2_SRCC_15 Sch=jb[2]
set_property -dict { PACKAGE_PIN G16 IOSTANDARD LVCMOS33 } [get_ports { jb[2] }]; #IO_L13N_T2_MRCC_15 Sch=jb[3]
set_property -dict { PACKAGE_PIN H14 IOSTANDARD LVCMOS33 } [get_ports { jb[3] }]; #IO_L15P_T2_DQS_15 Sch=jb[4]
set_property -dict { PACKAGE_PIN E16 IOSTANDARD LVCMOS33 } [get_ports { jb[4] }]; #IO_L11N_T1_SRCC_15 Sch=jb[7]
set_property -dict { PACKAGE_PIN F13 IOSTANDARD LVCMOS33 } [get_ports { jb[5] }]; #IO_L5P_T0_AD9P_15 Sch=jb[8]
set_property -dict { PACKAGE_PIN G13 IOSTANDARD LVCMOS33 } [get_ports { jb[6] }]; #IO_0_15 Sch=jb[9]
set_property -dict { PACKAGE_PIN H16 IOSTANDARD LVCMOS33 } [get_ports { jb[7] }]; #IO_L13P_T2_MRCC_15 Sch=jb[10]
##Pmod Header JC
set_property -dict { PACKAGE_PIN K1 IOSTANDARD LVCMOS33 } [get_ports { jc[0] }]; #IO_L23N_T3_35 Sch=jc[1]
set_property -dict { PACKAGE_PIN F6 IOSTANDARD LVCMOS33 } [get_ports { jc[1] }]; #IO_L19N_T3_VREF_35 Sch=jc[2]
# set_property -dict { PACKAGE_PIN J2 IOSTANDARD LVCMOS33 } [get_ports { jc[2] }]; #IO_L22N_T3_35 Sch=jc[3]
# set_property -dict { PACKAGE_PIN G6 IOSTANDARD LVCMOS33 } [get_ports { jc[3] }]; #IO_L19P_T3_35 Sch=jc[4]
# set_property -dict { PACKAGE_PIN E7 IOSTANDARD LVCMOS33 } [get_ports { jc[4] }]; #IO_L6P_T0_35 Sch=jc[7]
# set_property -dict { PACKAGE_PIN J3 IOSTANDARD LVCMOS33 } [get_ports { jc[5] }]; #IO_L22P_T3_35 Sch=jc[8]
# set_property -dict { PACKAGE_PIN J4 IOSTANDARD LVCMOS33 } [get_ports { jc[6] }]; #IO_L21P_T3_DQS_35 Sch=jc[9]
# set_property -dict { PACKAGE_PIN E6 IOSTANDARD LVCMOS33 } [get_ports { jc[7] }]; #IO_L5P_T0_AD13P_35 Sch=jc[10]
##Pmod Header JD
set_property -dict { PACKAGE_PIN H4 IOSTANDARD LVCMOS33 } [get_ports { jd[0] }]; #IO_L21N_T3_DQS_35 Sch=jd[1]
set_property -dict { PACKAGE_PIN H1 IOSTANDARD LVCMOS33 } [get_ports { jd[1] }]; #IO_L17P_T2_35 Sch=jd[2]
# set_property -dict { PACKAGE_PIN G1 IOSTANDARD LVCMOS33 } [get_ports { jd[2] }]; #IO_L17N_T2_35 Sch=jd[3]
# set_property -dict { PACKAGE_PIN G3 IOSTANDARD LVCMOS33 } [get_ports { jd[3] }]; #IO_L20N_T3_35 Sch=jd[4]
# set_property -dict { PACKAGE_PIN H2 IOSTANDARD LVCMOS33 } [get_ports { jd[4] }]; #IO_L15P_T2_DQS_35 Sch=jd[7]
# set_property -dict { PACKAGE_PIN G4 IOSTANDARD LVCMOS33 } [get_ports { jd[5] }]; #IO_L20P_T3_35 Sch=jd[8]
# set_property -dict { PACKAGE_PIN G2 IOSTANDARD LVCMOS33 } [get_ports { jd[6] }]; #IO_L15N_T2_DQS_35 Sch=jd[9]
# set_property -dict { PACKAGE_PIN F3 IOSTANDARD LVCMOS33 } [get_ports { jd[7] }]; #IO_L13N_T2_MRCC_35 Sch=jd[10]
##Pmod Header JXADC
#set_property -dict { PACKAGE_PIN A14 IOSTANDARD LVDS } [get_ports { xa_n[0] }]; #IO_L9N_T1_DQS_AD3N_15 Sch=xa_n[1]
#set_property -dict { PACKAGE_PIN A13 IOSTANDARD LVDS } [get_ports { xa_p[0] }]; #IO_L9P_T1_DQS_AD3P_15 Sch=xa_p[1]
#set_property -dict { PACKAGE_PIN A16 IOSTANDARD LVDS } [get_ports { xa_n[1] }]; #IO_L8N_T1_AD10N_15 Sch=xa_n[2]
#set_property -dict { PACKAGE_PIN A15 IOSTANDARD LVDS } [get_ports { xa_p[1] }]; #IO_L8P_T1_AD10P_15 Sch=xa_p[2]
#set_property -dict { PACKAGE_PIN B17 IOSTANDARD LVDS } [get_ports { xa_n[2] }]; #IO_L7N_T1_AD2N_15 Sch=xa_n[3]
#set_property -dict { PACKAGE_PIN B16 IOSTANDARD LVDS } [get_ports { xa_p[2] }]; #IO_L7P_T1_AD2P_15 Sch=xa_p[3]
#set_property -dict { PACKAGE_PIN A18 IOSTANDARD LVDS } [get_ports { xa_n[3] }]; #IO_L10N_T1_AD11N_15 Sch=xa_n[4]
#set_property -dict { PACKAGE_PIN B18 IOSTANDARD LVDS } [get_ports { xa_p[3] }]; #IO_L10P_T1_AD11P_15 Sch=xa_p[4]
##VGA Connector
#set_property -dict { PACKAGE_PIN A3 IOSTANDARD LVCMOS33 } [get_ports { vga_r[0] }]; #IO_L8N_T1_AD14N_35 Sch=vga_r[0]
#set_property -dict { PACKAGE_PIN B4 IOSTANDARD LVCMOS33 } [get_ports { vga_r[1] }]; #IO_L7N_T1_AD6N_35 Sch=vga_r[1]
#set_property -dict { PACKAGE_PIN C5 IOSTANDARD LVCMOS33 } [get_ports { vga_r[2] }]; #IO_L1N_T0_AD4N_35 Sch=vga_r[2]
#set_property -dict { PACKAGE_PIN A4 IOSTANDARD LVCMOS33 } [get_ports { vga_r[3] }]; #IO_L8P_T1_AD14P_35 Sch=vga_r[3]
#
#set_property -dict { PACKAGE_PIN C6 IOSTANDARD LVCMOS33 } [get_ports { vga_g[0] }]; #IO_L1P_T0_AD4P_35 Sch=vga_g[0]
#set_property -dict { PACKAGE_PIN A5 IOSTANDARD LVCMOS33 } [get_ports { vga_g[1] }]; #IO_L3N_T0_DQS_AD5N_35 Sch=vga_g[1]
#set_property -dict { PACKAGE_PIN B6 IOSTANDARD LVCMOS33 } [get_ports { vga_g[2] }]; #IO_L2N_T0_AD12N_35 Sch=vga_g[2]
#set_property -dict { PACKAGE_PIN A6 IOSTANDARD LVCMOS33 } [get_ports { vga_g[3] }]; #IO_L3P_T0_DQS_AD5P_35 Sch=vga_g[3]
#
#set_property -dict { PACKAGE_PIN B7 IOSTANDARD LVCMOS33 } [get_ports { vga_b[0] }]; #IO_L2P_T0_AD12P_35 Sch=vga_b[0]
#set_property -dict { PACKAGE_PIN C7 IOSTANDARD LVCMOS33 } [get_ports { vga_b[1] }]; #IO_L4N_T0_35 Sch=vga_b[1]
#set_property -dict { PACKAGE_PIN D7 IOSTANDARD LVCMOS33 } [get_ports { vga_b[2] }]; #IO_L6N_T0_VREF_35 Sch=vga_b[2]
#set_property -dict { PACKAGE_PIN D8 IOSTANDARD LVCMOS33 } [get_ports { vga_b[3] }]; #IO_L4P_T0_35 Sch=vga_b[3]
#set_property -dict { PACKAGE_PIN B11 IOSTANDARD LVCMOS33 } [get_ports { vga_hs }]; #IO_L4P_T0_15 Sch=vga_hs
#set_property -dict { PACKAGE_PIN B12 IOSTANDARD LVCMOS33 } [get_ports { vga_vs }]; #IO_L3N_T0_DQS_AD1N_15 Sch=vga_vs
##Micro SD Connector
#set_property -dict { PACKAGE_PIN E2 IOSTANDARD LVCMOS33 } [get_ports { sd_reset }]; #IO_L14P_T2_SRCC_35 Sch=sd_reset
#set_property -dict { PACKAGE_PIN A1 IOSTANDARD LVCMOS33 } [get_ports { sd_cd }]; #IO_L9N_T1_DQS_AD7N_35 Sch=sd_cd
#set_property -dict { PACKAGE_PIN B1 IOSTANDARD LVCMOS33 } [get_ports { sd_sck }]; #IO_L9P_T1_DQS_AD7P_35 Sch=sd_sck
#set_property -dict { PACKAGE_PIN C1 IOSTANDARD LVCMOS33 } [get_ports { sd_cmd }]; #IO_L16N_T2_35 Sch=sd_cmd
#set_property -dict { PACKAGE_PIN C2 IOSTANDARD LVCMOS33 } [get_ports { sd_dat[0] }]; #IO_L16P_T2_35 Sch=sd_dat[0]
#set_property -dict { PACKAGE_PIN E1 IOSTANDARD LVCMOS33 } [get_ports { sd_dat[1] }]; #IO_L18N_T2_35 Sch=sd_dat[1]
#set_property -dict { PACKAGE_PIN F1 IOSTANDARD LVCMOS33 } [get_ports { sd_dat[2] }]; #IO_L18P_T2_35 Sch=sd_dat[2]
#set_property -dict { PACKAGE_PIN D2 IOSTANDARD LVCMOS33 } [get_ports { sd_dat[3] }]; #IO_L14N_T2_SRCC_35 Sch=sd_dat[3]
##Accelerometer
#set_property -dict { PACKAGE_PIN E15 IOSTANDARD LVCMOS33 } [get_ports { acl_miso }]; #IO_L11P_T1_SRCC_15 Sch=acl_miso
#set_property -dict { PACKAGE_PIN F14 IOSTANDARD LVCMOS33 } [get_ports { acl_mosi }]; #IO_L5N_T0_AD9N_15 Sch=acl_mosi
#set_property -dict { PACKAGE_PIN F15 IOSTANDARD LVCMOS33 } [get_ports { acl_sclk }]; #IO_L14P_T2_SRCC_15 Sch=acl_sclk
#set_property -dict { PACKAGE_PIN D15 IOSTANDARD LVCMOS33 } [get_ports { acl_csn }]; #IO_L12P_T1_MRCC_15 Sch=acl_csn
#set_property -dict { PACKAGE_PIN B13 IOSTANDARD LVCMOS33 } [get_ports { acl_int[1] }]; #IO_L2P_T0_AD8P_15 Sch=acl_int[1]
#set_property -dict { PACKAGE_PIN C16 IOSTANDARD LVCMOS33 } [get_ports { acl_int[2] }]; #IO_L20P_T3_A20_15 Sch=acl_int[2]
##Temperature Sensor
#set_property -dict { PACKAGE_PIN C14 IOSTANDARD LVCMOS33 } [get_ports { tmp_scl }]; #IO_L1N_T0_AD0N_15 Sch=tmp_scl
#set_property -dict { PACKAGE_PIN C15 IOSTANDARD LVCMOS33 } [get_ports { tmp_sda }]; #IO_L12N_T1_MRCC_15 Sch=tmp_sda
#set_property -dict { PACKAGE_PIN D13 IOSTANDARD LVCMOS33 } [get_ports { tmp_int }]; #IO_L6N_T0_VREF_15 Sch=tmp_int
#set_property -dict { PACKAGE_PIN B14 IOSTANDARD LVCMOS33 } [get_ports { tmp_ct }]; #IO_L2N_T0_AD8N_15 Sch=tmp_ct
##Omnidirectional Microphone
#set_property -dict { PACKAGE_PIN J5 IOSTANDARD LVCMOS33 } [get_ports { m_clk }]; #IO_25_35 Sch=m_clk
#set_property -dict { PACKAGE_PIN H5 IOSTANDARD LVCMOS33 } [get_ports { m_data }]; #IO_L24N_T3_35 Sch=m_data
#set_property -dict { PACKAGE_PIN F5 IOSTANDARD LVCMOS33 } [get_ports { m_lrsel }]; #IO_0_35 Sch=m_lrsel
##PWM Audio Amplifier
#set_property -dict { PACKAGE_PIN A11 IOSTANDARD LVCMOS33 } [get_ports { aud_pwm }]; #IO_L4N_T0_15 Sch=aud_pwm
#set_property -dict { PACKAGE_PIN D12 IOSTANDARD LVCMOS33 } [get_ports { aud_sd }]; #IO_L6P_T0_15 Sch=aud_sd
##USB-RS232 Interface
# set_property -dict { PACKAGE_PIN C4 IOSTANDARD LVCMOS33 } [get_ports { uart_txd_in }]; #IO_L7P_T1_AD6P_35 Sch=uart_txd_in
# set_property -dict { PACKAGE_PIN D4 IOSTANDARD LVCMOS33 } [get_ports { uart_rxd_out }]; #IO_L11N_T1_SRCC_35 Sch=uart_rxd_out
#set_property -dict { PACKAGE_PIN D3 IOSTANDARD LVCMOS33 } [get_ports { uart_cts }]; #IO_L12N_T1_MRCC_35 Sch=uart_cts
#set_property -dict { PACKAGE_PIN E5 IOSTANDARD LVCMOS33 } [get_ports { uart_rts }]; #IO_L5N_T0_AD13N_35 Sch=uart_rts
##USB HID (PS/2)
#set_property -dict { PACKAGE_PIN F4 IOSTANDARD LVCMOS33 } [get_ports { ps2_clk }]; #IO_L13P_T2_MRCC_35 Sch=ps2_clk
#set_property -dict { PACKAGE_PIN B2 IOSTANDARD LVCMOS33 } [get_ports { ps2_data }]; #IO_L10N_T1_AD15N_35 Sch=ps2_data
##SMSC Ethernet PHY
#set_property -dict { PACKAGE_PIN C9 IOSTANDARD LVCMOS33 } [get_ports { eth_mdc }]; #IO_L11P_T1_SRCC_16 Sch=eth_mdc
#set_property -dict { PACKAGE_PIN A9 IOSTANDARD LVCMOS33 } [get_ports { eth_mdio }]; #IO_L14N_T2_SRCC_16 Sch=eth_mdio
# set_property -dict { PACKAGE_PIN B3 IOSTANDARD LVCMOS33 } [get_ports { eth_rstn }]; #IO_L10P_T1_AD15P_35 Sch=eth_rstn
# set_property -dict { PACKAGE_PIN D9 IOSTANDARD LVCMOS33 } [get_ports { eth_crsdv }]; #IO_L6N_T0_VREF_16 Sch=eth_crs/udv
#set_property -dict { PACKAGE_PIN C10 IOSTANDARD LVCMOS33 } [get_ports { eth_rxerr }]; #IO_L13N_T2_MRCC_16 Sch=eth_rxerr
# set_property -dict { PACKAGE_PIN C11 IOSTANDARD LVCMOS33 } [get_ports { eth_rxd[0] }]; #IO_L13P_T2_MRCC_16 Sch=eth_rxd[0]
# set_property -dict { PACKAGE_PIN D10 IOSTANDARD LVCMOS33 } [get_ports { eth_rxd[1] }]; #IO_L19N_T3_VREF_16 Sch=eth_rxd[1]
#set_property -dict { PACKAGE_PIN B9 IOSTANDARD LVCMOS33 } [get_ports { eth_txen }]; #IO_L11N_T1_SRCC_16 Sch=eth_txen
#set_property -dict { PACKAGE_PIN A10 IOSTANDARD LVCMOS33 } [get_ports { eth_txd[0] }]; #IO_L14P_T2_SRCC_16 Sch=eth_txd[0]
#set_property -dict { PACKAGE_PIN A8 IOSTANDARD LVCMOS33 } [get_ports { eth_txd[1] }]; #IO_L12N_T1_MRCC_16 Sch=eth_txd[1]
# set_property -dict { PACKAGE_PIN D5 IOSTANDARD LVCMOS33 } [get_ports { eth_refclk }]; #IO_L11P_T1_SRCC_35 Sch=eth_refclk
#set_property -dict { PACKAGE_PIN B8 IOSTANDARD LVCMOS33 } [get_ports { eth_intn }]; #IO_L12P_T1_MRCC_16 Sch=eth_intn
##Quad SPI Flash
#set_property -dict { PACKAGE_PIN K17 IOSTANDARD LVCMOS33 } [get_ports { qspi_dq[0] }]; #IO_L1P_T0_D00_MOSI_14 Sch=qspi_dq[0]
#set_property -dict { PACKAGE_PIN K18 IOSTANDARD LVCMOS33 } [get_ports { qspi_dq[1] }]; #IO_L1N_T0_D01_DIN_14 Sch=qspi_dq[1]
#set_property -dict { PACKAGE_PIN L14 IOSTANDARD LVCMOS33 } [get_ports { qspi_dq[2] }]; #IO_L2P_T0_D02_14 Sch=qspi_dq[2]
#set_property -dict { PACKAGE_PIN M14 IOSTANDARD LVCMOS33 } [get_ports { qspi_dq[3] }]; #IO_L2N_T0_D03_14 Sch=qspi_dq[3]
#set_property -dict { PACKAGE_PIN L13 IOSTANDARD LVCMOS33 } [get_ports { qspi_csn }]; #IO_L6P_T0_FCS_B_14 Sch=qspi_csn

View File

@ -25,6 +25,15 @@ module dual_port_bram #(
output wire [RAM_WIDTH-1:0] doutb
);
// The following code either initializes the memory values to a specified file or to all zeros to match hardware
generate
integer i;
initial begin
for (i = 0; i < RAM_DEPTH; i = i + 1)
BRAM[i] = {RAM_WIDTH{1'b0}};
end
endgenerate
reg [RAM_WIDTH-1:0] BRAM [RAM_DEPTH-1:0];
reg [RAM_WIDTH-1:0] ram_data_a = {RAM_WIDTH{1'b0}};
reg [RAM_WIDTH-1:0] ram_data_b = {RAM_WIDTH{1'b0}};

View File

@ -0,0 +1,197 @@
`default_nettype none
`timescale 1ns/1ps
module bram_core (
input wire clk,
// input port
input wire [15:0] addr_i,
input wire [15:0] wdata_i,
input wire [15:0] rdata_i,
input wire rw_i,
input wire valid_i,
// output port
output reg [15:0] addr_o,
output reg [15:0] wdata_o,
output reg [15:0] rdata_o,
output reg rw_o,
output reg valid_o,
// BRAM itself
input wire bram_clk,
input wire [ADDR_WIDTH-1:0] addr,
input wire [BRAM_WIDTH-1:0] din,
output reg [BRAM_WIDTH-1:0] dout,
input wire we);
parameter BASE_ADDR = 0;
// for now, let's pretend that this bram has a width of 33, and a depth of 256
// parameter BRAM_WIDTH = 0;
// parameter BRAM_DEPTH = 0;
parameter BRAM_WIDTH = 18;
parameter BRAM_DEPTH = 256;
localparam ADDR_WIDTH = $clog2(BRAM_DEPTH);
// Bus-Controlled side of BRAMs
reg [ADDR_WIDTH-1:0] addra_0 = 0;
reg [15:0] dina_0 = 0;
reg [15:0] douta_0;
reg wea_0 = 0;
reg [ADDR_WIDTH-1:0] addra_1 = 0;
reg [1:0] dina_1 = 0;
reg [1:0] douta_1;
reg wea_1 = 0;
// Pipelining
reg [15:0] addr_pipe_0 = 0;
reg [15:0] addr_pipe_1 = 0;
reg [15:0] addr_pipe_2 = 0;
reg [15:0] addr_pipe_3 = 0;
reg [15:0] wdata_pipe_0 = 0;
reg [15:0] wdata_pipe_1 = 0;
reg [15:0] wdata_pipe_2 = 0;
reg [15:0] wdata_pipe_3 = 0;
reg [15:0] rdata_pipe_0 = 0;
reg [15:0] rdata_pipe_1 = 0;
reg [15:0] rdata_pipe_2 = 0;
reg [15:0] rdata_pipe_3 = 0;
reg valid_pipe_0 = 0;
reg valid_pipe_1 = 0;
reg valid_pipe_2 = 0;
reg valid_pipe_3 = 0;
reg rw_pipe_0 = 0;
reg rw_pipe_1 = 0;
reg rw_pipe_2 = 0;
reg rw_pipe_3 = 0;
always @(posedge clk) begin
addr_pipe_0 <= addr_i;
wdata_pipe_0 <= wdata_i;
rdata_pipe_0 <= rdata_i;
valid_pipe_0 <= valid_i;
rw_pipe_0 <= rw_i;
addr_pipe_1 <= addr_pipe_0;
wdata_pipe_1 <= wdata_pipe_0;
rdata_pipe_1 <= rdata_pipe_0;
valid_pipe_1 <= valid_pipe_0;
rw_pipe_1 <= rw_pipe_0;
addr_pipe_2 <= addr_pipe_1;
wdata_pipe_2 <= wdata_pipe_1;
rdata_pipe_2 <= rdata_pipe_1;
valid_pipe_2 <= valid_pipe_1;
rw_pipe_2 <= rw_pipe_1;
addr_pipe_3 <= addr_pipe_2;
wdata_pipe_3 <= wdata_pipe_2;
rdata_pipe_3 <= rdata_pipe_2;
valid_pipe_3 <= valid_pipe_2;
rw_pipe_3 <= rw_pipe_2;
addr_o <= addr_pipe_3;
wdata_o <= wdata_pipe_3;
rdata_o <= rdata_pipe_3;
valid_o <= valid_pipe_3;
rw_o <= rw_pipe_3;
wea_0 <= 0;
wea_1 <= 0;
if( (valid_i) && (addr_i >= BASE_ADDR) && (addr_i <= BASE_ADDR + (2 * BRAM_DEPTH))) begin
// compute correct bram to talk to
case (addr_i % 2)
0: begin
wea_0 <= rw_i;
addra_0 <= (addr_i - BASE_ADDR) / 2;
dina_0 <= wdata_i;
rdata_o <= douta_0;
end
1: begin
wea_1 <= rw_i;
addra_1 <= (addr_i - BASE_ADDR) / 2;
dina_1 <= wdata_i[1:0];
rdata_o <= {14'b0, douta_1};
end
endcase
end
if( (valid_pipe_3) && (addr_pipe_3 >= BASE_ADDR) && (addr_pipe_3 <= BASE_ADDR + (2 * BRAM_DEPTH))) begin
// compute correct bram to talk to
case (addr_pipe_3 % 2)
0: begin
rdata_o <= douta_0;
end
1: begin
rdata_o <= {14'b0, douta_1};
end
endcase
end
end
// User-Controlled Side of BRAMs
reg [15:0] dinb_0;
reg [15:0] doutb_0;
reg [1:0] dinb_1;
reg [1:0] doutb_1;
assign dinb_0 = din[15:0];
assign dinb_1 = din[17:16];
assign dout = {doutb_1, doutb_0};
dual_port_bram #(
.RAM_WIDTH(16),
.RAM_DEPTH(BRAM_DEPTH)
) bram_0 (
// port A is controlled by the bus
.clka(clk),
.addra(addra_0),
.dina(dina_0),
.douta(douta_0),
.wea(wea_0),
// port B is exposed to the user
.clkb(bram_clk),
.addrb(addr),
.dinb(dinb_0),
.doutb(doutb_0),
.web(we));
dual_port_bram #(
.RAM_WIDTH(2),
.RAM_DEPTH(BRAM_DEPTH)
) bram_1 (
// port A is controlled by the bus
.clka(clk),
.addra(addra_1),
.dina(dina_1),
.douta(douta_1),
.wea(wea_1),
// port B is exposed to the user
.clkb(bram_clk),
.addrb(addr),
.dinb(dinb_1),
.doutb(doutb_1),
.web(we));
endmodule
`default_nettype wire

View File

@ -0,0 +1,150 @@
`default_nettype none
`define CP 10
`define HCP 5
task read_reg (
input [15:0] addr,
output [15:0] data,
input string desc
);
bram_core_tb.tb_bc_addr = addr;
bram_core_tb.tb_bc_rw = 0;
bram_core_tb.tb_bc_valid = 1;
#`CP
bram_core_tb.tb_bc_valid = 0;
while (!bram_core_tb.bc_tb_valid) #`CP;
data = bram_core_tb.bc_tb_rdata;
$display(" -> read 0x%h from addr 0x%h (%s)", data, addr, desc);
endtask
task write_reg(
input [15:0] addr,
input [15:0] data,
input string desc
);
bram_core_tb.tb_bc_addr = addr;
bram_core_tb.tb_bc_wdata = data;
bram_core_tb.tb_bc_rw = 1;
bram_core_tb.tb_bc_valid = 1;
#`CP
bram_core_tb.tb_bc_valid = 0;
while (!bram_core_tb.bc_tb_valid) #`CP;
$display(" -> wrote 0x%h to addr 0x%h (%s)", data, addr, desc);
endtask
task write_and_verify(
input [15:0] addr,
input [15:0] write_data,
input string desc
);
reg [15:0] read_data;
write_reg(addr, write_data, desc);
read_reg(addr, read_data, desc);
assert(read_data == write_data) else $error("data read does not match data written!");
endtask
module bram_core_tb;
// boilerplate
logic clk;
integer test_num;
reg [15:0] read_value;
// tb -> bram_core bus
logic [15:0] tb_bc_addr;
logic [15:0] tb_bc_wdata;
logic [15:0] tb_bc_rdata;
logic tb_bc_rw;
logic tb_bc_valid;
// bram_core -> tb bus
logic [15:0] bc_tb_addr;
logic [15:0] bc_tb_wdata;
logic [15:0] bc_tb_rdata;
logic bc_tb_rw;
logic bc_tb_valid;
// bram itself
logic [7:0] bram_user_addr = 0;
logic [17:0] bram_user_din = 0;
logic [17:0] bram_user_dout;
logic bram_user_we = 0;
bram_core bc (
.clk(clk),
// bus input port
.addr_i(tb_bc_addr),
.wdata_i(tb_bc_wdata),
.rdata_i(tb_bc_rdata),
.rw_i(tb_bc_rw),
.valid_i(tb_bc_valid),
// bus output port
.addr_o(bc_tb_addr),
.wdata_o(bc_tb_wdata),
.rdata_o(bc_tb_rdata),
.rw_o(bc_tb_rw),
.valid_o(bc_tb_valid),
// bram itself
.bram_clk(clk),
.addr(bram_user_addr),
.din(bram_user_din),
.dout(bram_user_dout),
.we(bram_user_we));
always begin
#`HCP
clk = !clk;
end
initial begin
$dumpfile("bram_core_tb.vcd");
$dumpvars(0, bram_core_tb);
// setup and reset
clk = 0;
test_num = 0;
tb_bc_addr = 0;
tb_bc_rdata = 0;
tb_bc_wdata = 0;
tb_bc_rw = 0;
tb_bc_valid = 0;
bram_user_addr = 0;
bram_user_din = 0;
bram_user_we = 0;
#`HCP
#(10*`CP);
/* ==== Test 1 Begin ==== */
$display("\n=== test 1: read/write from BRAM, verify ===");
test_num = 1;
//read_reg(0, read_value, "lmao");
write_and_verify(0, 4, "larry_op");
write_and_verify(1, 3, "larry_op");
// now query what's on the the user side at address 0
#(10*`CP);
/* ==== Test 1 End ==== */
$finish();
end
endmodule
`default_nettype wire