1
0
mirror of https://github.com/corundum/corundum.git synced 2025-01-30 08:32:52 +08:00

Add example design for DE10-Agilex

Signed-off-by: Alex Forencich <alex@alexforencich.com>
This commit is contained in:
Alex Forencich 2022-07-13 00:31:59 -07:00
parent c5382f5e7f
commit dbcd211ce1
17 changed files with 5657 additions and 0 deletions

View File

@ -0,0 +1,19 @@
# Verilog PCIe Terasic DE10-Agilex Example Design
## Introduction
This example design targets the Terasic DE10-Agilex.
The design implements the PCIe AXI lite master module, the PCIe AXI master module, and the PCIe DMA module. A very simple Linux driver is included to test the FPGA design.
* FPGA: AGFB014R24B2E2V
## How to build
Run `make` to build. Ensure that the Intel Quartus Pro components are in PATH.
Run `make` to build the driver. Ensure the headers for the running kernel are installed, otherwise the driver cannot be compiled.
## How to test
Run `make program` to program the DE10-Agilex with Quartus Pro. Then load the driver with `insmod example.ko`. Check dmesg for the output.

View File

@ -0,0 +1,179 @@
###################################################################
#
# Makefile for Intel Quartus Prime Pro
#
# Alex Forencich
#
###################################################################
#
# Parameters:
# FPGA_TOP - Top module name
# FPGA_FAMILY - FPGA family (e.g. Stratix 10 DX)
# FPGA_DEVICE - FPGA device (e.g. 1SD280PT2F55E1VG)
# SYN_FILES - space-separated list of source files
# IP_FILES - space-separated list of IP files
# IP_TCL_FILES - space-separated list of TCL files for qsys-script
# QSF_FILES - space-separated list of settings files
# SDC_FILES - space-separated list of timing constraint files
#
# Example:
#
# FPGA_TOP = fpga
# FPGA_FAMILY = "Stratix 10 DX"
# FPGA_DEVICE = 1SD280PT2F55E1VG
# SYN_FILES = rtl/fpga.v
# QSF_FILES = fpga.qsf
# SDC_FILES = fpga.sdc
# include ../common/quartus_pro.mk
#
###################################################################
# phony targets
.PHONY: clean fpga
# output files to hang on to
.PRECIOUS: %.sof %.ipregen.rpt %.syn.rpt %.fit.rpt %.asm.rpt %.sta.rpt
.SECONDARY:
# any project specific settings
CONFIG ?= config.mk
-include ../$(CONFIG)
SYN_FILES_REL = $(patsubst %, ../%, $(SYN_FILES))
IP_FILES_REL = $(patsubst %, ../%, $(IP_FILES))
IP_FILES_INT = $(patsubst %, ip/%, $(notdir $(IP_FILES)))
IP_TCL_FILES_REL = $(patsubst %, ../%, $(IP_TCL_FILES))
IP_TCL_FILES_INT = $(patsubst %, ip/%, $(notdir $(IP_TCL_FILES)))
IP_TCL_FILES_IP_INT = $(patsubst %.tcl, ip/%.ip, $(notdir $(IP_TCL_FILES)))
ifdef QSF_FILES
QSF_FILES_REL = $(patsubst %, ../%, $(QSF_FILES))
else
QSF_FILES_REL = ../$(FPGA_TOP).qsf
endif
SDC_FILES_REL = $(patsubst %, ../%, $(SDC_FILES))
ASSIGNMENT_FILES = $(FPGA_TOP).qpf $(FPGA_TOP).qsf
###################################################################
# Main Targets
#
# all: build everything
# clean: remove output files and database
###################################################################
all: fpga
fpga: $(FPGA_TOP).sof
quartus: $(FPGA_TOP).qpf
quartus $(FPGA_TOP).qpf
tmpclean:
-rm -rf defines.v
-rm -rf *.rpt *.summary *.done *.smsg *.chg smart.log *.htm *.eqn *.pin *.qsf *.qpf *.sld *.txt *.qws *.stp
-rm -rf ip db qdb incremental_db reconfig_mif tmp-clearbox synth_dumps .qsys_edit
clean: tmpclean
-rm -rf *.sof *.pof *.jdi *.jic *.map
distclean: clean
-rm -rf rev
syn: smart.log output_files/$(PROJECT).syn.rpt
fit: smart.log output_files/$(PROJECT).fit.rpt
asm: smart.log output_files/$(PROJECT).asm.rpt
sta: smart.log output_files/$(PROJECT).sta.rpt
smart: smart.log
###################################################################
# Executable Configuration
###################################################################
IP_ARGS = --run_default_mode_op
SYN_ARGS = --read_settings_files=on --write_settings_files=off
FIT_ARGS = --read_settings_files=on --write_settings_files=off
ASM_ARGS = --read_settings_files=on --write_settings_files=off
STA_ARGS =
###################################################################
# Target implementations
###################################################################
STAMP = echo done >
define COPY_IP_RULE
$(patsubst %, ip/%, $(notdir $(1))): $(1)
@mkdir -p ip
@cp -pv $(1) ip/
endef
$(foreach l,$(IP_FILES_REL) $(IP_TCL_FILES_REL),$(eval $(call COPY_IP_RULE,$(l))))
define TCL_IP_GEN_RULE
$(patsubst %.tcl, %.ip, $(1)): $(1)
cd ip && qsys-script --script=$(notdir $(1))
endef
$(foreach l,$(IP_TCL_FILES_INT),$(eval $(call TCL_IP_GEN_RULE,$(l))))
%.ipregen.rpt: $(FPGA_TOP).qpf $(IP_FILES_INT) $(IP_TCL_FILES_IP_INT)
quartus_ipgenerate $(IP_ARGS) $(FPGA_TOP)
%.syn.rpt: syn.chg %.ipregen.rpt $(SYN_FILES_REL)
quartus_syn $(SYN_ARGS) $(FPGA_TOP)
%.fit.rpt: fit.chg %.syn.rpt $(SDC_FILES_REL)
quartus_fit $(FIT_ARGS) $(FPGA_TOP)
%.sta.rpt: sta.chg %.fit.rpt
quartus_sta $(STA_ARGS) $(FPGA_TOP)
%.asm.rpt: asm.chg %.sta.rpt
quartus_asm $(ASM_ARGS) $(FPGA_TOP)
mkdir -p rev
EXT=sof; COUNT=100; \
while [ -e rev/$*_rev$$COUNT.$$EXT ]; \
do let COUNT=COUNT+1; done; \
cp $*.$$EXT rev/$*_rev$$COUNT.$$EXT; \
echo "Output: rev/$*_rev$$COUNT.$$EXT";
%.sof: smart.log %.asm.rpt
smart.log: $(ASSIGNMENT_FILES)
quartus_sh --determine_smart_action $(FPGA_TOP) > smart.log
###################################################################
# Project initialization
###################################################################
$(ASSIGNMENT_FILES): $(QSF_FILES_REL) $(IP_FILES_INT) $(IP_TCL_FILES_IP_INT)
rm -f $(FPGA_TOP).qsf
quartus_sh --prepare -f $(FPGA_FAMILY) -d $(FPGA_DEVICE) -t $(FPGA_TOP) $(FPGA_TOP)
echo >> $(FPGA_TOP).qsf
echo >> $(FPGA_TOP).qsf
echo "# Source files" >> $(FPGA_TOP).qsf
for x in $(SYN_FILES_REL) $(IP_FILES_INT) $(IP_TCL_FILES_IP_INT); do \
case $${x##*.} in \
v|V) echo set_global_assignment -name VERILOG_FILE $$x >> $(FPGA_TOP).qsf ;;\
vhd|VHD) echo set_global_assignment -name VHDL_FILE $$x >> $(FPGA_TOP).qsf ;;\
qip|QIP) echo set_global_assignment -name QIP_FILE $$x >> $(FPGA_TOP).qsf ;;\
ip|IP) echo set_global_assignment -name IP_FILE $$x >> $(FPGA_TOP).qsf ;;\
*) echo set_global_assignment -name SOURCE_FILE $$x >> $(FPGA_TOP).qsf ;;\
esac; \
done
echo >> $(FPGA_TOP).qsf
echo "# SDC files" >> $(FPGA_TOP).qsf
for x in $(SDC_FILES_REL); do echo set_global_assignment -name SDC_FILE $$x >> $(FPGA_TOP).qsf; done
for x in $(QSF_FILES_REL); do printf "\n#\n# Included QSF file $$x\n#\n" >> $(FPGA_TOP).qsf; cat $$x >> $(FPGA_TOP).qsf; done
syn.chg:
$(STAMP) syn.chg
fit.chg:
$(STAMP) fit.chg
sta.chg:
$(STAMP) sta.chg
asm.chg:
$(STAMP) asm.chg

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,58 @@
# Timing constraints for the Terasic DE10-Agilex FPGA development board
set_time_format -unit ns -decimal_places 3
# Clock constraints
create_clock -period 10.000 -name {clk_100_b2a} [ get_ports {clk_100_b2a} ]
create_clock -period 20.000 -name {clk_50_b3a} [ get_ports {clk_50_b3a} ]
create_clock -period 20.000 -name {clk_50_b3c} [ get_ports {clk_50_b3c} ]
create_clock -period 32.552 -name {clk_30m72} [ get_ports {clk_30m72} ]
create_clock -period 20.000 -name {clk_from_si5397a_0} [ get_ports {clk_from_si5397a_p[0]} ]
create_clock -period 20.000 -name {clk_from_si5397a_1} [ get_ports {clk_from_si5397a_p[1]} ]
create_clock -period 10.000 -name {pcie_refclk_0} [ get_ports {pcie_refclk_p[0]} ]
create_clock -period 10.000 -name {pcie_refclk_1} [ get_ports {pcie_refclk_p[1]} ]
create_clock -period 6.400 -name {qsfpdda_refclk} [ get_ports {qsfpdda_refclk_p} ]
create_clock -period 6.400 -name {qsfpddb_refclk} [ get_ports {qsfpddb_refclk_p} ]
create_clock -period 6.400 -name {qsfpddrsv_refclk} [ get_ports {qsfpddrsv_refclk_p} ]
create_clock -period 30.000 -name {ddr4a_refclk} [ get_ports {ddr4a_refclk_p} ]
create_clock -period 30.000 -name {ddr4b_refclk} [ get_ports {ddr4b_refclk_p} ]
create_clock -period 30.000 -name {ddr4c_refclk} [ get_ports {ddr4c_refclk_p} ]
create_clock -period 30.000 -name {ddr4d_refclk} [ get_ports {ddr4d_refclk_p} ]
derive_clock_uncertainty
set_clock_groups -asynchronous -group [ get_clocks {clk_100_b2a} ]
set_clock_groups -asynchronous -group [ get_clocks {clk_50_b3a} ]
set_clock_groups -asynchronous -group [ get_clocks {clk_50_b3c} ]
set_clock_groups -asynchronous -group [ get_clocks {clk_30m72} ]
set_clock_groups -asynchronous -group [ get_clocks {clk_from_si5397a_0} ]
set_clock_groups -asynchronous -group [ get_clocks {clk_from_si5397a_1} ]
set_clock_groups -asynchronous -group [ get_clocks {pcie_refclk_0} ]
set_clock_groups -asynchronous -group [ get_clocks {pcie_refclk_1} ]
set_clock_groups -asynchronous -group [ get_clocks {qsfpdda_refclk} ]
set_clock_groups -asynchronous -group [ get_clocks {qsfpddb_refclk} ]
set_clock_groups -asynchronous -group [ get_clocks {qsfpddrsv_refclk} ]
set_clock_groups -asynchronous -group [ get_clocks {ddr4a_refclk} ]
set_clock_groups -asynchronous -group [ get_clocks {ddr4b_refclk} ]
set_clock_groups -asynchronous -group [ get_clocks {ddr4c_refclk} ]
set_clock_groups -asynchronous -group [ get_clocks {ddr4d_refclk} ]
# JTAG constraints
# create_clock -name {altera_reserved_tck} -period 40.800 {altera_reserved_tck}
# set_clock_groups -asynchronous -group [get_clocks {altera_reserved_tck}]
# IO constraints
set_false_path -from "cpu_resetn"
set_false_path -from "button[*]"
set_false_path -from "sw[*]"
set_false_path -to "led[*]"
set_false_path -to "led_bracket[*]"
set_false_path -from "pcie_perst_n"

View File

@ -0,0 +1,51 @@
# FPGA settings
FPGA_TOP = fpga
FPGA_FAMILY = "Agilex"
FPGA_DEVICE = AGFB014R24A2E2VR0
# Files for synthesis
SYN_FILES = rtl/fpga.v
SYN_FILES += rtl/fpga_core.v
SYN_FILES += rtl/sync_reset.v
SYN_FILES += rtl/sync_signal.v
SYN_FILES += rtl/common/example_core_pcie_ptile.v
SYN_FILES += rtl/common/example_core_pcie.v
SYN_FILES += rtl/common/example_core.v
SYN_FILES += rtl/common/axi_ram.v
SYN_FILES += lib/pcie/rtl/pcie_ptile_if.v
SYN_FILES += lib/pcie/rtl/pcie_ptile_if_rx.v
SYN_FILES += lib/pcie/rtl/pcie_ptile_if_tx.v
SYN_FILES += lib/pcie/rtl/pcie_ptile_cfg.v
SYN_FILES += lib/pcie/rtl/pcie_axil_master.v
SYN_FILES += lib/pcie/rtl/pcie_axi_master.v
SYN_FILES += lib/pcie/rtl/pcie_axi_master_rd.v
SYN_FILES += lib/pcie/rtl/pcie_axi_master_wr.v
SYN_FILES += lib/pcie/rtl/pcie_tlp_demux_bar.v
SYN_FILES += lib/pcie/rtl/pcie_tlp_demux.v
SYN_FILES += lib/pcie/rtl/pcie_tlp_mux.v
SYN_FILES += lib/pcie/rtl/pcie_tlp_fifo.v
SYN_FILES += lib/pcie/rtl/pcie_tlp_fifo_raw.v
SYN_FILES += lib/pcie/rtl/pcie_tlp_fifo_mux.v
SYN_FILES += lib/pcie/rtl/pcie_msix.v
SYN_FILES += lib/pcie/rtl/dma_if_pcie.v
SYN_FILES += lib/pcie/rtl/dma_if_pcie_rd.v
SYN_FILES += lib/pcie/rtl/dma_if_pcie_wr.v
SYN_FILES += lib/pcie/rtl/dma_psdpram.v
SYN_FILES += lib/pcie/rtl/priority_encoder.v
SYN_FILES += lib/pcie/rtl/pulse_merge.v
# IP files
IP_TCL_FILES += ip/reset_release.tcl
IP_TCL_FILES += ip/pcie.tcl
# QSF files
QSF_FILES = fpga.qsf
# SDC files
SDC_FILES = fpga.sdc
include ../common/quartus_pro.mk
program: fpga
quartus_pgm --no_banner --mode=jtag -o "P;$(FPGA_TOP).sof@1"

View File

@ -0,0 +1,51 @@
# FPGA settings
FPGA_TOP = fpga
FPGA_FAMILY = "Agilex"
FPGA_DEVICE = AGFB014R24B2E2V
# Files for synthesis
SYN_FILES = rtl/fpga.v
SYN_FILES += rtl/fpga_core.v
SYN_FILES += rtl/sync_reset.v
SYN_FILES += rtl/sync_signal.v
SYN_FILES += rtl/common/example_core_pcie_ptile.v
SYN_FILES += rtl/common/example_core_pcie.v
SYN_FILES += rtl/common/example_core.v
SYN_FILES += rtl/common/axi_ram.v
SYN_FILES += lib/pcie/rtl/pcie_ptile_if.v
SYN_FILES += lib/pcie/rtl/pcie_ptile_if_rx.v
SYN_FILES += lib/pcie/rtl/pcie_ptile_if_tx.v
SYN_FILES += lib/pcie/rtl/pcie_ptile_cfg.v
SYN_FILES += lib/pcie/rtl/pcie_axil_master.v
SYN_FILES += lib/pcie/rtl/pcie_axi_master.v
SYN_FILES += lib/pcie/rtl/pcie_axi_master_rd.v
SYN_FILES += lib/pcie/rtl/pcie_axi_master_wr.v
SYN_FILES += lib/pcie/rtl/pcie_tlp_demux_bar.v
SYN_FILES += lib/pcie/rtl/pcie_tlp_demux.v
SYN_FILES += lib/pcie/rtl/pcie_tlp_mux.v
SYN_FILES += lib/pcie/rtl/pcie_tlp_fifo.v
SYN_FILES += lib/pcie/rtl/pcie_tlp_fifo_raw.v
SYN_FILES += lib/pcie/rtl/pcie_tlp_fifo_mux.v
SYN_FILES += lib/pcie/rtl/pcie_msix.v
SYN_FILES += lib/pcie/rtl/dma_if_pcie.v
SYN_FILES += lib/pcie/rtl/dma_if_pcie_rd.v
SYN_FILES += lib/pcie/rtl/dma_if_pcie_wr.v
SYN_FILES += lib/pcie/rtl/dma_psdpram.v
SYN_FILES += lib/pcie/rtl/priority_encoder.v
SYN_FILES += lib/pcie/rtl/pulse_merge.v
# IP files
IP_TCL_FILES += ip/reset_release.tcl
IP_TCL_FILES += ip/pcie.tcl
# QSF files
QSF_FILES = fpga.qsf
# SDC files
SDC_FILES = fpga.sdc
include ../common/quartus_pro.mk
program: fpga
quartus_pgm --no_banner --mode=jtag -o "P;$(FPGA_TOP).sof@1"

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,52 @@
package require -exact qsys 21.3
# create the system "reset_release"
proc do_create_reset_release {} {
# create the system
create_system reset_release
set_project_property DEVICE {AGFB014R24B2E2V}
set_project_property DEVICE_FAMILY {Agilex}
set_project_property HIDE_FROM_IP_CATALOG {true}
set_use_testbench_naming_pattern 0 {}
# add HDL parameters
# add the components
add_instance s10_user_rst_clkgate_0 altera_s10_user_rst_clkgate
set_instance_parameter_value s10_user_rst_clkgate_0 {outputType} {Conduit Interface}
set_instance_property s10_user_rst_clkgate_0 AUTO_EXPORT true
# add wirelevel expressions
# preserve ports for debug
# add the exports
set_interface_property ninit_done EXPORT_OF s10_user_rst_clkgate_0.ninit_done
# set values for exposed HDL parameters
# set the the module properties
set_module_property BONUS_DATA {<?xml version="1.0" encoding="UTF-8"?>
<bonusData>
<element __value="s10_user_rst_clkgate_0">
<datum __value="_sortIndex" value="0" type="int" />
</element>
</bonusData>
}
set_module_property FILE {reset_release.ip}
set_module_property GENERATION_ID {0x00000000}
set_module_property NAME {reset_release}
# save the system
sync_sysinfo_parameters
save_system reset_release
}
proc do_set_exported_interface_sysinfo_parameters {} {
}
# create all the systems, from bottom up
do_create_reset_release
# set system info parameters on exported interface, from bottom up
do_set_exported_interface_sysinfo_parameters

View File

@ -0,0 +1 @@
../../../../

View File

@ -0,0 +1 @@
../lib/pcie/example/common/rtl/

View File

@ -0,0 +1,93 @@
/*
Copyright (c) 2014-2018 Alex Forencich
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
// Language: Verilog-2001
`resetall
`timescale 1 ns / 1 ps
`default_nettype none
/*
* Synchronizes switch and button inputs with a slow sampled shift register
*/
module debounce_switch #(
parameter WIDTH=1, // width of the input and output signals
parameter N=3, // length of shift register
parameter RATE=125000 // clock division factor
)(
input wire clk,
input wire rst,
input wire [WIDTH-1:0] in,
output wire [WIDTH-1:0] out
);
reg [23:0] cnt_reg = 24'd0;
reg [N-1:0] debounce_reg[WIDTH-1:0];
reg [WIDTH-1:0] state;
/*
* The synchronized output is the state register
*/
assign out = state;
integer k;
always @(posedge clk or posedge rst) begin
if (rst) begin
cnt_reg <= 0;
state <= 0;
for (k = 0; k < WIDTH; k = k + 1) begin
debounce_reg[k] <= 0;
end
end else begin
if (cnt_reg < RATE) begin
cnt_reg <= cnt_reg + 24'd1;
end else begin
cnt_reg <= 24'd0;
end
if (cnt_reg == 24'd0) begin
for (k = 0; k < WIDTH; k = k + 1) begin
debounce_reg[k] <= {debounce_reg[k][N-2:0], in[k]};
end
end
for (k = 0; k < WIDTH; k = k + 1) begin
if (|debounce_reg[k] == 0) begin
state[k] <= 0;
end else if (&debounce_reg[k] == 1) begin
state[k] <= 1;
end else begin
state[k] <= state[k];
end
end
end
end
endmodule
`resetall

View File

@ -0,0 +1,331 @@
/*
Copyright (c) 2022 Alex Forencich
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
// Language: Verilog 2001
`resetall
`timescale 1ns / 1ps
`default_nettype none
/*
* FPGA top-level module
*/
module fpga (
/*
* Clock: 50 MHz, 100 MHz
* Reset: Push button, active low
*/
// input wire clk_100_b2a,
// input wire clk_50_b3a,
// input wire clk_50_b3c,
// input wire cpu_reset_n,
/*
* GPIO
*/
input wire [1:0] button,
input wire [1:0] sw,
output wire [3:0] led,
output wire [3:0] led_bracket,
/*
* PCIe: gen 4 x16
*/
output wire [15:0] pcie_tx_p,
output wire [15:0] pcie_tx_n,
input wire [15:0] pcie_rx_p,
input wire [15:0] pcie_rx_n,
input wire [1:0] pcie_refclk_p,
input wire pcie_perst_n,
/*
* Ethernet: QSFP-DD
*/
// output wire [7:0] qsfpdda_tx_p,
// output wire [7:0] qsfpdda_tx_n,
// input wire [7:0] qsfpdda_rx_p,
// input wire [7:0] qsfpdda_rx_n,
// output wire [7:0] qsfpddb_tx_p,
// output wire [7:0] qsfpddb_tx_n,
// input wire [7:0] qsfpddb_rx_p,
// input wire [7:0] qsfpddb_rx_n,
input wire qsfpdda_refclk_p
// input wire qsfpddb_refclk_p,
// input wire qsfpddrsv_refclk_p,
// output wire qsfpdda_initmode,
// input wire qsfpdda_interrupt_n,
// input wire qsfpdda_mod_prs_n,
// output wire qsfpdda_mod_sel_n,
// output wire qsfpdda_rst_n,
// inout wire qsfpdda_scl,
// inout wire qsfpdda_sda,
// output wire qsfpddb_initmode,
// input wire qsfpddb_interrupt_n,
// input wire qsfpddb_mod_prs_n,
// output wire qsfpddb_mod_sel_n,
// output wire qsfpddb_rst_n,
// inout wire qsfpddb_scl,
// inout wire qsfpddb_sda
);
parameter SEG_COUNT = 2;
parameter SEG_DATA_WIDTH = 256;
parameter SEG_EMPTY_WIDTH = $clog2(SEG_DATA_WIDTH/32);
parameter SEG_HDR_WIDTH = 128;
parameter SEG_PRFX_WIDTH = 32;
parameter TX_SEQ_NUM_WIDTH = 6;
parameter PCIE_TAG_COUNT = 256;
parameter BAR0_APERTURE = 24;
parameter BAR2_APERTURE = 24;
parameter BAR4_APERTURE = 16;
// Clock and reset
wire ninit_done;
reset_release reset_release_inst (
.ninit_done (ninit_done)
);
// wire clk_100mhz = clk_sys_100m_p;
// wire rst_100mhz;
// sync_reset #(
// .N(20)
// )
// sync_reset_100mhz_inst (
// .clk(clk_100mhz),
// .rst(!cpu_resetn || ninit_done),
// .out(rst_100mhz)
// );
wire coreclkout_hip;
wire reset_status_n;
wire clk = coreclkout_hip;
wire rst = !reset_status_n;
wire [SEG_COUNT*SEG_DATA_WIDTH-1:0] rx_st_data;
wire [SEG_COUNT*SEG_EMPTY_WIDTH-1:0] rx_st_empty;
wire [SEG_COUNT-1:0] rx_st_sop;
wire [SEG_COUNT-1:0] rx_st_eop;
wire [SEG_COUNT-1:0] rx_st_valid;
wire rx_st_ready;
wire [SEG_COUNT*SEG_HDR_WIDTH-1:0] rx_st_hdr;
wire [SEG_COUNT*SEG_PRFX_WIDTH-1:0] rx_st_tlp_prfx;
wire [SEG_COUNT-1:0] rx_st_vf_active = 0;
wire [SEG_COUNT*3-1:0] rx_st_func_num = 0;
wire [SEG_COUNT*11-1:0] rx_st_vf_num = 0;
wire [SEG_COUNT*3-1:0] rx_st_bar_range;
wire [SEG_COUNT-1:0] rx_st_tlp_abort;
wire [SEG_COUNT*SEG_DATA_WIDTH-1:0] tx_st_data;
wire [SEG_COUNT-1:0] tx_st_sop;
wire [SEG_COUNT-1:0] tx_st_eop;
wire [SEG_COUNT-1:0] tx_st_valid;
wire tx_st_ready;
wire [SEG_COUNT-1:0] tx_st_err;
wire [SEG_COUNT*SEG_HDR_WIDTH-1:0] tx_st_hdr;
wire [SEG_COUNT*SEG_PRFX_WIDTH-1:0] tx_st_tlp_prfx;
wire [11:0] rx_buffer_limit;
wire [1:0] rx_buffer_limit_tdm_idx;
wire [15:0] tx_cdts_limit;
wire [2:0] tx_cdts_limit_tdm_idx;
wire [15:0] tl_cfg_ctl;
wire [4:0] tl_cfg_add;
wire [2:0] tl_cfg_func;
pcie (
.p0_rx_st_ready_i(rx_st_ready),
.p0_rx_st_sop_o(rx_st_sop),
.p0_rx_st_eop_o(rx_st_eop),
.p0_rx_st_data_o(rx_st_data),
.p0_rx_st_valid_o(rx_st_valid),
.p0_rx_st_empty_o(rx_st_empty),
.p0_rx_st_hdr_o(rx_st_hdr),
.p0_rx_st_tlp_prfx_o(rx_st_tlp_prfx),
.p0_rx_st_bar_range_o(rx_st_bar_range),
.p0_rx_st_tlp_abort_o(rx_st_tlp_abort),
.p0_rx_par_err_o(),
.p0_tx_st_sop_i(tx_st_sop),
.p0_tx_st_eop_i(tx_st_eop),
.p0_tx_st_data_i(tx_st_data),
.p0_tx_st_valid_i(tx_st_valid),
.p0_tx_st_err_i(tx_st_err),
.p0_tx_st_ready_o(tx_st_ready),
.p0_tx_st_hdr_i(tx_st_hdr),
.p0_tx_st_tlp_prfx_i(tx_st_tlp_prfx),
.p0_tx_par_err_o(),
.p0_tx_cdts_limit_o(tx_cdts_limit),
.p0_tx_cdts_limit_tdm_idx_o(tx_cdts_limit_tdm_idx),
.p0_tl_cfg_func_o(tl_cfg_func),
.p0_tl_cfg_add_o(tl_cfg_add),
.p0_tl_cfg_ctl_o(tl_cfg_ctl),
.p0_dl_timer_update_o(),
.p0_reset_status_n(reset_status_n),
.p0_pin_perst_n(),
.p0_link_up_o(),
.p0_dl_up_o(),
.p0_surprise_down_err_o(),
.p0_ltssm_state_o(),
.rx_n_in0(pcie_rx_n[0]),
.rx_n_in1(pcie_rx_n[1]),
.rx_n_in2(pcie_rx_n[2]),
.rx_n_in3(pcie_rx_n[3]),
.rx_n_in4(pcie_rx_n[4]),
.rx_n_in5(pcie_rx_n[5]),
.rx_n_in6(pcie_rx_n[6]),
.rx_n_in7(pcie_rx_n[7]),
.rx_n_in8(pcie_rx_n[8]),
.rx_n_in9(pcie_rx_n[9]),
.rx_n_in10(pcie_rx_n[10]),
.rx_n_in11(pcie_rx_n[11]),
.rx_n_in12(pcie_rx_n[12]),
.rx_n_in13(pcie_rx_n[13]),
.rx_n_in14(pcie_rx_n[14]),
.rx_n_in15(pcie_rx_n[15]),
.rx_p_in0(pcie_rx_p[0]),
.rx_p_in1(pcie_rx_p[1]),
.rx_p_in2(pcie_rx_p[2]),
.rx_p_in3(pcie_rx_p[3]),
.rx_p_in4(pcie_rx_p[4]),
.rx_p_in5(pcie_rx_p[5]),
.rx_p_in6(pcie_rx_p[6]),
.rx_p_in7(pcie_rx_p[7]),
.rx_p_in8(pcie_rx_p[8]),
.rx_p_in9(pcie_rx_p[9]),
.rx_p_in10(pcie_rx_p[10]),
.rx_p_in11(pcie_rx_p[11]),
.rx_p_in12(pcie_rx_p[12]),
.rx_p_in13(pcie_rx_p[13]),
.rx_p_in14(pcie_rx_p[14]),
.rx_p_in15(pcie_rx_p[15]),
.tx_n_out0(pcie_tx_n[0]),
.tx_n_out1(pcie_tx_n[1]),
.tx_n_out2(pcie_tx_n[2]),
.tx_n_out3(pcie_tx_n[3]),
.tx_n_out4(pcie_tx_n[4]),
.tx_n_out5(pcie_tx_n[5]),
.tx_n_out6(pcie_tx_n[6]),
.tx_n_out7(pcie_tx_n[7]),
.tx_n_out8(pcie_tx_n[8]),
.tx_n_out9(pcie_tx_n[9]),
.tx_n_out10(pcie_tx_n[10]),
.tx_n_out11(pcie_tx_n[11]),
.tx_n_out12(pcie_tx_n[12]),
.tx_n_out13(pcie_tx_n[13]),
.tx_n_out14(pcie_tx_n[14]),
.tx_n_out15(pcie_tx_n[15]),
.tx_p_out0(pcie_tx_p[0]),
.tx_p_out1(pcie_tx_p[1]),
.tx_p_out2(pcie_tx_p[2]),
.tx_p_out3(pcie_tx_p[3]),
.tx_p_out4(pcie_tx_p[4]),
.tx_p_out5(pcie_tx_p[5]),
.tx_p_out6(pcie_tx_p[6]),
.tx_p_out7(pcie_tx_p[7]),
.tx_p_out8(pcie_tx_p[8]),
.tx_p_out9(pcie_tx_p[9]),
.tx_p_out10(pcie_tx_p[10]),
.tx_p_out11(pcie_tx_p[11]),
.tx_p_out12(pcie_tx_p[12]),
.tx_p_out13(pcie_tx_p[13]),
.tx_p_out14(pcie_tx_p[14]),
.tx_p_out15(pcie_tx_p[15]),
.coreclkout_hip(coreclkout_hip),
.refclk0(pcie_refclk_p[0]),
.refclk1(pcie_refclk_p[1]),
.pin_perst_n(pcie_perst_n),
.ninit_done(ninit_done)
);
fpga_core #(
.SEG_COUNT(SEG_COUNT),
.SEG_DATA_WIDTH(SEG_DATA_WIDTH),
.SEG_EMPTY_WIDTH(SEG_EMPTY_WIDTH),
.SEG_HDR_WIDTH(SEG_HDR_WIDTH),
.SEG_PRFX_WIDTH(SEG_PRFX_WIDTH),
.TX_SEQ_NUM_WIDTH(TX_SEQ_NUM_WIDTH),
.PCIE_TAG_COUNT(PCIE_TAG_COUNT),
.BAR0_APERTURE(BAR0_APERTURE),
.BAR2_APERTURE(BAR2_APERTURE),
.BAR4_APERTURE(BAR4_APERTURE)
)
fpga_core_inst (
.clk(clk),
.rst(rst),
/*
* GPIO
*/
.button(button),
.sw(sw),
.led(led),
.led_bracket(led_bracket),
/*
* P-Tile RX AVST interface
*/
.rx_st_data(rx_st_data),
.rx_st_empty(rx_st_empty),
.rx_st_sop(rx_st_sop),
.rx_st_eop(rx_st_eop),
.rx_st_valid(rx_st_valid),
.rx_st_ready(rx_st_ready),
.rx_st_hdr(rx_st_hdr),
.rx_st_tlp_prfx(rx_st_tlp_prfx),
.rx_st_vf_active(rx_st_vf_active),
.rx_st_func_num(rx_st_func_num),
.rx_st_vf_num(rx_st_vf_num),
.rx_st_bar_range(rx_st_bar_range),
.rx_st_tlp_abort(rx_st_tlp_abort),
.tx_st_data(tx_st_data),
.tx_st_sop(tx_st_sop),
.tx_st_eop(tx_st_eop),
.tx_st_valid(tx_st_valid),
.tx_st_ready(tx_st_ready),
.tx_st_err(tx_st_err),
.tx_st_hdr(tx_st_hdr),
.tx_st_tlp_prfx(tx_st_tlp_prfx),
.rx_buffer_limit(rx_buffer_limit),
.rx_buffer_limit_tdm_idx(rx_buffer_limit_tdm_idx),
.tx_cdts_limit(tx_cdts_limit),
.tx_cdts_limit_tdm_idx(tx_cdts_limit_tdm_idx),
.tl_cfg_ctl(tl_cfg_ctl),
.tl_cfg_add(tl_cfg_add),
.tl_cfg_func(tl_cfg_func)
);
endmodule
`resetall

View File

@ -0,0 +1,175 @@
/*
Copyright (c) 2022 Alex Forencich
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
// Language: Verilog 2001
`resetall
`timescale 1ns / 1ps
`default_nettype none
/*
* FPGA core logic
*/
module fpga_core #
(
parameter SEG_COUNT = 2,
parameter SEG_DATA_WIDTH = 256,
parameter SEG_EMPTY_WIDTH = $clog2(SEG_DATA_WIDTH/32),
parameter SEG_HDR_WIDTH = 128,
parameter SEG_PRFX_WIDTH = 32,
parameter TX_SEQ_NUM_WIDTH = 6,
parameter PCIE_TAG_COUNT = 256,
parameter BAR0_APERTURE = 24,
parameter BAR2_APERTURE = 24,
parameter BAR4_APERTURE = 16
)
(
input wire clk,
input wire rst,
/*
* GPIO
*/
input wire [1:0] button,
input wire [1:0] sw,
output wire [3:0] led,
output wire [3:0] led_bracket,
/*
* P-Tile RX AVST interface
*/
input wire [SEG_COUNT*SEG_DATA_WIDTH-1:0] rx_st_data,
input wire [SEG_COUNT*SEG_EMPTY_WIDTH-1:0] rx_st_empty,
input wire [SEG_COUNT-1:0] rx_st_sop,
input wire [SEG_COUNT-1:0] rx_st_eop,
input wire [SEG_COUNT-1:0] rx_st_valid,
output wire rx_st_ready,
input wire [SEG_COUNT*SEG_HDR_WIDTH-1:0] rx_st_hdr,
input wire [SEG_COUNT*SEG_PRFX_WIDTH-1:0] rx_st_tlp_prfx,
input wire [SEG_COUNT-1:0] rx_st_vf_active,
input wire [SEG_COUNT*3-1:0] rx_st_func_num,
input wire [SEG_COUNT*11-1:0] rx_st_vf_num,
input wire [SEG_COUNT*3-1:0] rx_st_bar_range,
input wire [SEG_COUNT-1:0] rx_st_tlp_abort,
output wire [SEG_COUNT*SEG_DATA_WIDTH-1:0] tx_st_data,
output wire [SEG_COUNT-1:0] tx_st_sop,
output wire [SEG_COUNT-1:0] tx_st_eop,
output wire [SEG_COUNT-1:0] tx_st_valid,
input wire tx_st_ready,
output wire [SEG_COUNT-1:0] tx_st_err,
output wire [SEG_COUNT*SEG_HDR_WIDTH-1:0] tx_st_hdr,
output wire [SEG_COUNT*SEG_PRFX_WIDTH-1:0] tx_st_tlp_prfx,
output wire [11:0] rx_buffer_limit,
output wire [1:0] rx_buffer_limit_tdm_idx,
input wire [15:0] tx_cdts_limit,
input wire [2:0] tx_cdts_limit_tdm_idx,
input wire [15:0] tl_cfg_ctl,
input wire [4:0] tl_cfg_add,
input wire [2:0] tl_cfg_func
);
assign led = 0;
assign led_bracket = 0;
example_core_pcie_ptile #(
.SEG_COUNT(SEG_COUNT),
.SEG_DATA_WIDTH(SEG_DATA_WIDTH),
.SEG_EMPTY_WIDTH(SEG_EMPTY_WIDTH),
.SEG_HDR_WIDTH(SEG_HDR_WIDTH),
.SEG_PRFX_WIDTH(SEG_PRFX_WIDTH),
.IMM_ENABLE(1),
.IMM_WIDTH(32),
.TX_SEQ_NUM_WIDTH(TX_SEQ_NUM_WIDTH),
.TX_SEQ_NUM_ENABLE(1),
.PCIE_TAG_COUNT(PCIE_TAG_COUNT),
.READ_OP_TABLE_SIZE(PCIE_TAG_COUNT),
.READ_TX_LIMIT(2**TX_SEQ_NUM_WIDTH),
.READ_TX_FC_ENABLE(0),
.WRITE_OP_TABLE_SIZE(2**TX_SEQ_NUM_WIDTH),
.WRITE_TX_LIMIT(2**TX_SEQ_NUM_WIDTH),
.WRITE_TX_FC_ENABLE(0),
.BAR0_APERTURE(BAR0_APERTURE),
.BAR2_APERTURE(BAR2_APERTURE),
.BAR4_APERTURE(BAR4_APERTURE)
)
core_inst (
.clk(clk),
.rst(rst),
/*
* P-Tile RX AVST interface
*/
.rx_st_data(rx_st_data),
.rx_st_empty(rx_st_empty),
.rx_st_sop(rx_st_sop),
.rx_st_eop(rx_st_eop),
.rx_st_valid(rx_st_valid),
.rx_st_ready(rx_st_ready),
.rx_st_hdr(rx_st_hdr),
.rx_st_tlp_prfx(rx_st_tlp_prfx),
.rx_st_vf_active(rx_st_vf_active),
.rx_st_func_num(rx_st_func_num),
.rx_st_vf_num(rx_st_vf_num),
.rx_st_bar_range(rx_st_bar_range),
.rx_st_tlp_abort(rx_st_tlp_abort),
/*
* P-Tile TX AVST interface
*/
.tx_st_data(tx_st_data),
.tx_st_sop(tx_st_sop),
.tx_st_eop(tx_st_eop),
.tx_st_valid(tx_st_valid),
.tx_st_ready(tx_st_ready),
.tx_st_err(tx_st_err),
.tx_st_hdr(tx_st_hdr),
.tx_st_tlp_prfx(tx_st_tlp_prfx),
/*
* P-Tile RX flow control
*/
.rx_buffer_limit(rx_buffer_limit),
.rx_buffer_limit_tdm_idx(rx_buffer_limit_tdm_idx),
/*
* P-Tile TX flow control
*/
.tx_cdts_limit(tx_cdts_limit),
.tx_cdts_limit_tdm_idx(tx_cdts_limit_tdm_idx),
/*
* P-Tile configuration interface
*/
.tl_cfg_ctl(tl_cfg_ctl),
.tl_cfg_add(tl_cfg_add),
.tl_cfg_func(tl_cfg_func)
);
endmodule
`resetall

View File

@ -0,0 +1,61 @@
/*
Copyright (c) 2014-2020 Alex Forencich
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
// Language: Verilog-2001
`resetall
`timescale 1ns / 1ps
`default_nettype none
/*
* Synchronizes an active-high asynchronous reset signal to a given clock by
* using a pipeline of N registers.
*/
module sync_reset #
(
// depth of synchronizer
parameter N = 2
)
(
input wire clk,
input wire rst,
output wire out
);
(* srl_style = "register" *)
reg [N-1:0] sync_reg = {N{1'b1}};
assign out = sync_reg[N-1];
always @(posedge clk or posedge rst) begin
if (rst) begin
sync_reg <= {N{1'b1}};
end else begin
sync_reg <= {sync_reg[N-2:0], 1'b0};
end
end
endmodule
`resetall

View File

@ -0,0 +1,62 @@
/*
Copyright (c) 2014-2018 Alex Forencich
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
// Language: Verilog-2001
`resetall
`timescale 1 ns / 1 ps
`default_nettype none
/*
* Synchronizes an asyncronous signal to a given clock by using a pipeline of
* two registers.
*/
module sync_signal #(
parameter WIDTH=1, // width of the input and output signals
parameter N=2 // depth of synchronizer
)(
input wire clk,
input wire [WIDTH-1:0] in,
output wire [WIDTH-1:0] out
);
reg [WIDTH-1:0] sync_reg[N-1:0];
/*
* The synchronized output is the last register in the pipeline.
*/
assign out = sync_reg[N-1];
integer k;
always @(posedge clk) begin
sync_reg[0] <= in;
for (k = 1; k < N; k = k + 1) begin
sync_reg[k] <= sync_reg[k-1];
end
end
endmodule
`resetall

View File

@ -0,0 +1,120 @@
# Copyright (c) 2022 Alex Forencich
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
TOPLEVEL_LANG = verilog
SIM ?= icarus
WAVES ?= 0
COCOTB_HDL_TIMEUNIT = 1ns
COCOTB_HDL_TIMEPRECISION = 1ps
DUT = fpga_core
TOPLEVEL = $(DUT)
MODULE = test_$(DUT)
VERILOG_SOURCES += ../../rtl/$(DUT).v
VERILOG_SOURCES += ../../rtl/common/example_core_pcie_ptile.v
VERILOG_SOURCES += ../../rtl/common/example_core_pcie.v
VERILOG_SOURCES += ../../rtl/common/example_core.v
VERILOG_SOURCES += ../../rtl/common/axi_ram.v
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_ptile_if.v
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_ptile_if_rx.v
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_ptile_if_tx.v
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_ptile_cfg.v
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_axil_master.v
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_axi_master.v
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_axi_master_rd.v
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_axi_master_wr.v
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_tlp_demux_bar.v
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_tlp_demux.v
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_tlp_mux.v
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_tlp_fifo.v
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_tlp_fifo_raw.v
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_tlp_fifo_mux.v
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_msix.v
VERILOG_SOURCES += ../../lib/pcie/rtl/dma_if_pcie.v
VERILOG_SOURCES += ../../lib/pcie/rtl/dma_if_pcie_rd.v
VERILOG_SOURCES += ../../lib/pcie/rtl/dma_if_pcie_wr.v
VERILOG_SOURCES += ../../lib/pcie/rtl/dma_psdpram.v
VERILOG_SOURCES += ../../lib/pcie/rtl/priority_encoder.v
VERILOG_SOURCES += ../../lib/pcie/rtl/pulse_merge.v
# module parameters
export PARAM_SEG_COUNT ?= 2
export PARAM_SEG_DATA_WIDTH ?= 256
export PARAM_SEG_EMPTY_WIDTH ?= $(shell python -c "print((($(PARAM_SEG_DATA_WIDTH)//32)-1).bit_length())" )
export PARAM_SEG_HDR_WIDTH ?= 128
export PARAM_SEG_PRFX_WIDTH ?= 32
export PARAM_TX_SEQ_NUM_WIDTH ?= 6
export PARAM_PCIE_TAG_COUNT ?= 64
export PARAM_BAR0_APERTURE ?= 24
export PARAM_BAR2_APERTURE ?= 24
export PARAM_BAR4_APERTURE ?= 16
ifeq ($(SIM), icarus)
PLUSARGS += -fst
COMPILE_ARGS += -P $(TOPLEVEL).SEG_COUNT=$(PARAM_SEG_COUNT)
COMPILE_ARGS += -P $(TOPLEVEL).SEG_DATA_WIDTH=$(PARAM_SEG_DATA_WIDTH)
COMPILE_ARGS += -P $(TOPLEVEL).SEG_EMPTY_WIDTH=$(PARAM_SEG_EMPTY_WIDTH)
COMPILE_ARGS += -P $(TOPLEVEL).SEG_HDR_WIDTH=$(PARAM_SEG_HDR_WIDTH)
COMPILE_ARGS += -P $(TOPLEVEL).SEG_PRFX_WIDTH=$(PARAM_SEG_PRFX_WIDTH)
COMPILE_ARGS += -P $(TOPLEVEL).TX_SEQ_NUM_WIDTH=$(PARAM_TX_SEQ_NUM_WIDTH)
COMPILE_ARGS += -P $(TOPLEVEL).PCIE_TAG_COUNT=$(PARAM_PCIE_TAG_COUNT)
COMPILE_ARGS += -P $(TOPLEVEL).BAR0_APERTURE=$(PARAM_BAR0_APERTURE)
COMPILE_ARGS += -P $(TOPLEVEL).BAR2_APERTURE=$(PARAM_BAR2_APERTURE)
COMPILE_ARGS += -P $(TOPLEVEL).BAR4_APERTURE=$(PARAM_BAR4_APERTURE)
ifeq ($(WAVES), 1)
VERILOG_SOURCES += iverilog_dump.v
COMPILE_ARGS += -s iverilog_dump
endif
else ifeq ($(SIM), verilator)
COMPILE_ARGS += -Wno-SELRANGE -Wno-WIDTH
COMPILE_ARGS += -GSEG_COUNT=$(PARAM_SEG_COUNT)
COMPILE_ARGS += -GSEG_DATA_WIDTH=$(PARAM_SEG_DATA_WIDTH)
COMPILE_ARGS += -GSEG_EMPTY_WIDTH=$(PARAM_SEG_EMPTY_WIDTH)
COMPILE_ARGS += -GSEG_HDR_WIDTH=$(PARAM_SEG_HDR_WIDTH)
COMPILE_ARGS += -GSEG_PRFX_WIDTH=$(PARAM_SEG_PRFX_WIDTH)
COMPILE_ARGS += -GTX_SEQ_NUM_WIDTH=$(PARAM_TX_SEQ_NUM_WIDTH)
COMPILE_ARGS += -GPCIE_TAG_COUNT=$(PARAM_PCIE_TAG_COUNT)
COMPILE_ARGS += -GBAR0_APERTURE=$(PARAM_BAR0_APERTURE)
COMPILE_ARGS += -GBAR2_APERTURE=$(PARAM_BAR2_APERTURE)
COMPILE_ARGS += -GBAR4_APERTURE=$(PARAM_BAR4_APERTURE)
ifeq ($(WAVES), 1)
COMPILE_ARGS += --trace-fst
endif
endif
include $(shell cocotb-config --makefiles)/Makefile.sim
iverilog_dump.v:
echo 'module iverilog_dump();' > $@
echo 'initial begin' >> $@
echo ' $$dumpfile("$(TOPLEVEL).fst");' >> $@
echo ' $$dumpvars(0, $(TOPLEVEL));' >> $@
echo 'end' >> $@
echo 'endmodule' >> $@
clean::
@rm -rf iverilog_dump.v
@rm -rf dump.fst $(TOPLEVEL).fst

View File

@ -0,0 +1,530 @@
"""
Copyright (c) 2022 Alex Forencich
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
"""
import logging
import os
import cocotb_test.simulator
import cocotb
from cocotb.log import SimLog
from cocotb.triggers import RisingEdge, FallingEdge, Timer
from cocotbext.pcie.core import RootComplex
from cocotbext.pcie.intel.ptile import PTilePcieDevice, PTileRxBus, PTileTxBus
class TB(object):
def __init__(self, dut):
self.dut = dut
self.log = SimLog("cocotb.tb")
self.log.setLevel(logging.DEBUG)
# PCIe
self.rc = RootComplex()
self.dev = PTilePcieDevice(
# configuration options
pcie_generation=3,
# pcie_link_width=2,
# pld_clk_frequency=250e6,
pf_count=1,
max_payload_size=512,
enable_extended_tag=True,
pf0_msi_enable=False,
pf0_msi_count=1,
pf1_msi_enable=False,
pf1_msi_count=1,
pf2_msi_enable=False,
pf2_msi_count=1,
pf3_msi_enable=False,
pf3_msi_count=1,
pf0_msix_enable=False,
pf0_msix_table_size=63,
pf0_msix_table_bir=4,
pf0_msix_table_offset=0x00000000,
pf0_msix_pba_bir=4,
pf0_msix_pba_offset=0x00008000,
pf1_msix_enable=False,
pf1_msix_table_size=0,
pf1_msix_table_bir=0,
pf1_msix_table_offset=0x00000000,
pf1_msix_pba_bir=0,
pf1_msix_pba_offset=0x00000000,
pf2_msix_enable=False,
pf2_msix_table_size=0,
pf2_msix_table_bir=0,
pf2_msix_table_offset=0x00000000,
pf2_msix_pba_bir=0,
pf2_msix_pba_offset=0x00000000,
pf3_msix_enable=False,
pf3_msix_table_size=0,
pf3_msix_table_bir=0,
pf3_msix_table_offset=0x00000000,
pf3_msix_pba_bir=0,
pf3_msix_pba_offset=0x00000000,
# signals
# Clock and reset
reset_status=dut.rst,
# reset_status_n=dut.reset_status_n,
coreclkout_hip=dut.clk,
# refclk0=dut.refclk0,
# refclk1=dut.refclk1,
# pin_perst_n=dut.pin_perst_n,
# RX interface
rx_bus=PTileRxBus.from_prefix(dut, "rx_st"),
# rx_par_err=dut.rx_par_err,
# TX interface
tx_bus=PTileTxBus.from_prefix(dut, "tx_st"),
# tx_par_err=dut.tx_par_err,
# RX flow control
rx_buffer_limit=dut.rx_buffer_limit,
rx_buffer_limit_tdm_idx=dut.rx_buffer_limit_tdm_idx,
# TX flow control
tx_cdts_limit=dut.tx_cdts_limit,
tx_cdts_limit_tdm_idx=dut.tx_cdts_limit_tdm_idx,
# Power management and hard IP status interface
# link_up=dut.link_up,
# dl_up=dut.dl_up,
# surprise_down_err=dut.surprise_down_err,
# ltssm_state=dut.ltssm_state,
# pm_state=dut.pm_state,
# pm_dstate=dut.pm_dstate,
# apps_pm_xmt_pme=dut.apps_pm_xmt_pme,
# app_req_retry_en=dut.app_req_retry_en,
# Interrupt interface
# app_int=dut.app_int,
# msi_pnd_func=dut.msi_pnd_func,
# msi_pnd_byte=dut.msi_pnd_byte,
# msi_pnd_addr=dut.msi_pnd_addr,
# Error interface
# serr_out=dut.serr_out,
# hip_enter_err_mode=dut.hip_enter_err_mode,
# app_err_valid=dut.app_err_valid,
# app_err_hdr=dut.app_err_hdr,
# app_err_info=dut.app_err_info,
# app_err_func_num=dut.app_err_func_num,
# Completion timeout interface
# cpl_timeout=dut.cpl_timeout,
# cpl_timeout_avmm_clk=dut.cpl_timeout_avmm_clk,
# cpl_timeout_avmm_address=dut.cpl_timeout_avmm_address,
# cpl_timeout_avmm_read=dut.cpl_timeout_avmm_read,
# cpl_timeout_avmm_readdata=dut.cpl_timeout_avmm_readdata,
# cpl_timeout_avmm_readdatavalid=dut.cpl_timeout_avmm_readdatavalid,
# cpl_timeout_avmm_write=dut.cpl_timeout_avmm_write,
# cpl_timeout_avmm_writedata=dut.cpl_timeout_avmm_writedata,
# cpl_timeout_avmm_waitrequest=dut.cpl_timeout_avmm_waitrequest,
# Configuration output
tl_cfg_func=dut.tl_cfg_func,
tl_cfg_add=dut.tl_cfg_add,
tl_cfg_ctl=dut.tl_cfg_ctl,
# dl_timer_update=dut.dl_timer_update,
# Configuration intercept interface
# cii_req=dut.cii_req,
# cii_hdr_poisoned=dut.cii_hdr_poisoned,
# cii_hdr_first_be=dut.cii_hdr_first_be,
# cii_func_num=dut.cii_func_num,
# cii_wr_vf_active=dut.cii_wr_vf_active,
# cii_vf_num=dut.cii_vf_num,
# cii_wr=dut.cii_wr,
# cii_addr=dut.cii_addr,
# cii_dout=dut.cii_dout,
# cii_override_en=dut.cii_override_en,
# cii_override_din=dut.cii_override_din,
# cii_halt=dut.cii_halt,
# Hard IP reconfiguration interface
# hip_reconfig_clk=dut.hip_reconfig_clk,
# hip_reconfig_address=dut.hip_reconfig_address,
# hip_reconfig_read=dut.hip_reconfig_read,
# hip_reconfig_readdata=dut.hip_reconfig_readdata,
# hip_reconfig_readdatavalid=dut.hip_reconfig_readdatavalid,
# hip_reconfig_write=dut.hip_reconfig_write,
# hip_reconfig_writedata=dut.hip_reconfig_writedata,
# hip_reconfig_waitrequest=dut.hip_reconfig_waitrequest,
# Page request service
# prs_event_valid=dut.prs_event_valid,
# prs_event_func=dut.prs_event_func,
# prs_event=dut.prs_event,
# SR-IOV (VF error)
# vf_err_ur_posted_s0=dut.vf_err_ur_posted_s0,
# vf_err_ur_posted_s1=dut.vf_err_ur_posted_s1,
# vf_err_ur_posted_s2=dut.vf_err_ur_posted_s2,
# vf_err_ur_posted_s3=dut.vf_err_ur_posted_s3,
# vf_err_func_num_s0=dut.vf_err_func_num_s0,
# vf_err_func_num_s1=dut.vf_err_func_num_s1,
# vf_err_func_num_s2=dut.vf_err_func_num_s2,
# vf_err_func_num_s3=dut.vf_err_func_num_s3,
# vf_err_ca_postedreq_s0=dut.vf_err_ca_postedreq_s0,
# vf_err_ca_postedreq_s1=dut.vf_err_ca_postedreq_s1,
# vf_err_ca_postedreq_s2=dut.vf_err_ca_postedreq_s2,
# vf_err_ca_postedreq_s3=dut.vf_err_ca_postedreq_s3,
# vf_err_vf_num_s0=dut.vf_err_vf_num_s0,
# vf_err_vf_num_s1=dut.vf_err_vf_num_s1,
# vf_err_vf_num_s2=dut.vf_err_vf_num_s2,
# vf_err_vf_num_s3=dut.vf_err_vf_num_s3,
# vf_err_poisonedwrreq_s0=dut.vf_err_poisonedwrreq_s0,
# vf_err_poisonedwrreq_s1=dut.vf_err_poisonedwrreq_s1,
# vf_err_poisonedwrreq_s2=dut.vf_err_poisonedwrreq_s2,
# vf_err_poisonedwrreq_s3=dut.vf_err_poisonedwrreq_s3,
# vf_err_poisonedcompl_s0=dut.vf_err_poisonedcompl_s0,
# vf_err_poisonedcompl_s1=dut.vf_err_poisonedcompl_s1,
# vf_err_poisonedcompl_s2=dut.vf_err_poisonedcompl_s2,
# vf_err_poisonedcompl_s3=dut.vf_err_poisonedcompl_s3,
# user_vfnonfatalmsg_func_num=dut.user_vfnonfatalmsg_func_num,
# user_vfnonfatalmsg_vfnum=dut.user_vfnonfatalmsg_vfnum,
# user_sent_vfnonfatalmsg=dut.user_sent_vfnonfatalmsg,
# vf_err_overflow=dut.vf_err_overflow,
# FLR
# flr_rcvd_pf=dut.flr_rcvd_pf,
# flr_rcvd_vf=dut.flr_rcvd_vf,
# flr_rcvd_pf_num=dut.flr_rcvd_pf_num,
# flr_rcvd_vf_num=dut.flr_rcvd_vf_num,
# flr_completed_pf=dut.flr_completed_pf,
# flr_completed_vf=dut.flr_completed_vf,
# flr_completed_pf_num=dut.flr_completed_pf_num,
# flr_completed_vf_num=dut.flr_completed_vf_num,
# VirtIO
# virtio_pcicfg_vfaccess=dut.virtio_pcicfg_vfaccess,
# virtio_pcicfg_vfnum=dut.virtio_pcicfg_vfnum,
# virtio_pcicfg_pfnum=dut.virtio_pcicfg_pfnum,
# virtio_pcicfg_bar=dut.virtio_pcicfg_bar,
# virtio_pcicfg_length=dut.virtio_pcicfg_length,
# virtio_pcicfg_baroffset=dut.virtio_pcicfg_baroffset,
# virtio_pcicfg_cfgdata=dut.virtio_pcicfg_cfgdata,
# virtio_pcicfg_cfgwr=dut.virtio_pcicfg_cfgwr,
# virtio_pcicfg_cfgrd=dut.virtio_pcicfg_cfgrd,
# virtio_pcicfg_appvfnum=dut.virtio_pcicfg_appvfnum,
# virtio_pcicfg_apppfnum=dut.virtio_pcicfg_apppfnum,
# virtio_pcicfg_rdack=dut.virtio_pcicfg_rdack,
# virtio_pcicfg_rdbe=dut.virtio_pcicfg_rdbe,
# virtio_pcicfg_data=dut.virtio_pcicfg_data,
)
# self.dev.log.setLevel(logging.DEBUG)
self.rc.make_port().connect(self.dev)
self.dev.functions[0].configure_bar(0, 2**len(dut.core_inst.core_pcie_inst.axil_ctrl_awaddr))
self.dev.functions[0].configure_bar(2, 2**len(dut.core_inst.core_pcie_inst.axi_ram_awaddr))
async def init(self):
await FallingEdge(self.dut.rst)
await Timer(100, 'ns')
await self.rc.enumerate()
dev = self.rc.find_device(self.dev.functions[0].pcie_id)
await dev.enable_device()
await dev.set_master()
await dev.alloc_irq_vectors(32, 32)
@cocotb.test()
async def run_test(dut):
tb = TB(dut)
await tb.init()
mem = tb.rc.mem_pool.alloc_region(16*1024*1024)
mem_base = mem.get_absolute_address(0)
dev = tb.rc.find_device(tb.dev.functions[0].pcie_id)
dev_pf0_bar0 = dev.bar_window[0]
dev_pf0_bar2 = dev.bar_window[2]
tb.log.info("Test memory write to BAR 2")
test_data = b'\x11\x22\x33\x44'
await dev_pf0_bar2.write(0, test_data)
await Timer(100, 'ns')
tb.log.info("Test memory read from BAR 2")
val = await dev_pf0_bar2.read(0, len(test_data), timeout=1000)
tb.log.info("Read data: %s", val)
assert val == test_data
tb.log.info("Test DMA")
# write packet data
mem[0:1024] = bytearray([x % 256 for x in range(1024)])
# enable DMA
await dev_pf0_bar0.write_dword(0x000000, 1)
# enable interrupts
await dev_pf0_bar0.write_dword(0x000008, 0x3)
# write pcie read descriptor
await dev_pf0_bar0.write_dword(0x000100, (mem_base+0x0000) & 0xffffffff)
await dev_pf0_bar0.write_dword(0x000104, (mem_base+0x0000 >> 32) & 0xffffffff)
await dev_pf0_bar0.write_dword(0x000108, 0x100)
await dev_pf0_bar0.write_dword(0x000110, 0x400)
await dev_pf0_bar0.write_dword(0x000114, 0xAA)
await Timer(2000, 'ns')
# read status
val = await dev_pf0_bar0.read_dword(0x000118)
tb.log.info("Status: 0x%x", val)
assert val == 0x800000AA
# write pcie write descriptor
await dev_pf0_bar0.write_dword(0x000200, (mem_base+0x1000) & 0xffffffff)
await dev_pf0_bar0.write_dword(0x000204, (mem_base+0x1000 >> 32) & 0xffffffff)
await dev_pf0_bar0.write_dword(0x000208, 0x100)
await dev_pf0_bar0.write_dword(0x000210, 0x400)
await dev_pf0_bar0.write_dword(0x000214, 0x55)
await Timer(2000, 'ns')
# read status
val = await dev_pf0_bar0.read_dword(0x000218)
tb.log.info("Status: 0x%x", val)
assert val == 0x80000055
tb.log.info("%s", mem.hexdump_str(0x1000, 64))
assert mem[0:1024] == mem[0x1000:0x1000+1024]
tb.log.info("Test immediate write")
# write pcie write descriptor
await dev_pf0_bar0.write_dword(0x000200, (mem_base+0x1000) & 0xffffffff)
await dev_pf0_bar0.write_dword(0x000204, (mem_base+0x1000 >> 32) & 0xffffffff)
await dev_pf0_bar0.write_dword(0x000208, 0x44332211)
await dev_pf0_bar0.write_dword(0x000210, 0x4)
await dev_pf0_bar0.write_dword(0x000214, 0x800000AA)
await Timer(2000, 'ns')
# read status
val = await dev_pf0_bar0.read_dword(0x000218)
tb.log.info("Status: 0x%x", val)
assert val == 0x800000AA
tb.log.info("%s", mem.hexdump_str(0x1000, 64))
assert mem[0x1000:0x1000+4] == b'\x11\x22\x33\x44'
tb.log.info("Test DMA block operations")
region_len = 0x2000
src_offset = 0x0000
dest_offset = 0x4000
block_size = 256
block_stride = block_size
block_count = 32
# write packet data
mem[src_offset:src_offset+region_len] = bytearray([x % 256 for x in range(region_len)])
# enable DMA
await dev_pf0_bar0.write_dword(0x000000, 1)
# disable interrupts
await dev_pf0_bar0.write_dword(0x000008, 0)
# configure operation (read)
# DMA base address
await dev_pf0_bar0.write_dword(0x001080, (mem_base+src_offset) & 0xffffffff)
await dev_pf0_bar0.write_dword(0x001084, (mem_base+src_offset >> 32) & 0xffffffff)
# DMA offset address
await dev_pf0_bar0.write_dword(0x001088, 0)
await dev_pf0_bar0.write_dword(0x00108c, 0)
# DMA offset mask
await dev_pf0_bar0.write_dword(0x001090, region_len-1)
await dev_pf0_bar0.write_dword(0x001094, 0)
# DMA stride
await dev_pf0_bar0.write_dword(0x001098, block_stride)
await dev_pf0_bar0.write_dword(0x00109c, 0)
# RAM base address
await dev_pf0_bar0.write_dword(0x0010c0, 0)
await dev_pf0_bar0.write_dword(0x0010c4, 0)
# RAM offset address
await dev_pf0_bar0.write_dword(0x0010c8, 0)
await dev_pf0_bar0.write_dword(0x0010cc, 0)
# RAM offset mask
await dev_pf0_bar0.write_dword(0x0010d0, region_len-1)
await dev_pf0_bar0.write_dword(0x0010d4, 0)
# RAM stride
await dev_pf0_bar0.write_dword(0x0010d8, block_stride)
await dev_pf0_bar0.write_dword(0x0010dc, 0)
# clear cycle count
await dev_pf0_bar0.write_dword(0x001008, 0)
await dev_pf0_bar0.write_dword(0x00100c, 0)
# block length
await dev_pf0_bar0.write_dword(0x001010, block_size)
# block count
await dev_pf0_bar0.write_dword(0x001018, block_count)
await dev_pf0_bar0.write_dword(0x00101c, 0)
# start
await dev_pf0_bar0.write_dword(0x001000, 1)
for k in range(10):
cnt = await dev_pf0_bar0.read_dword(0x001018)
await Timer(1000, 'ns')
if cnt == 0:
break
# configure operation (write)
# DMA base address
await dev_pf0_bar0.write_dword(0x001180, (mem_base+dest_offset) & 0xffffffff)
await dev_pf0_bar0.write_dword(0x001184, (mem_base+dest_offset >> 32) & 0xffffffff)
# DMA offset address
await dev_pf0_bar0.write_dword(0x001188, 0)
await dev_pf0_bar0.write_dword(0x00118c, 0)
# DMA offset mask
await dev_pf0_bar0.write_dword(0x001190, region_len-1)
await dev_pf0_bar0.write_dword(0x001194, 0)
# DMA stride
await dev_pf0_bar0.write_dword(0x001198, block_stride)
await dev_pf0_bar0.write_dword(0x00119c, 0)
# RAM base address
await dev_pf0_bar0.write_dword(0x0011c0, 0)
await dev_pf0_bar0.write_dword(0x0011c4, 0)
# RAM offset address
await dev_pf0_bar0.write_dword(0x0011c8, 0)
await dev_pf0_bar0.write_dword(0x0011cc, 0)
# RAM offset mask
await dev_pf0_bar0.write_dword(0x0011d0, region_len-1)
await dev_pf0_bar0.write_dword(0x0011d4, 0)
# RAM stride
await dev_pf0_bar0.write_dword(0x0011d8, block_stride)
await dev_pf0_bar0.write_dword(0x0011dc, 0)
# clear cycle count
await dev_pf0_bar0.write_dword(0x001108, 0)
await dev_pf0_bar0.write_dword(0x00110c, 0)
# block length
await dev_pf0_bar0.write_dword(0x001110, block_size)
# block count
await dev_pf0_bar0.write_dword(0x001118, block_count)
await dev_pf0_bar0.write_dword(0x00111c, 0)
# start
await dev_pf0_bar0.write_dword(0x001100, 1)
for k in range(10):
cnt = await dev_pf0_bar0.read_dword(0x001118)
await Timer(1000, 'ns')
if cnt == 0:
break
tb.log.info("%s", mem.hexdump_str(dest_offset, region_len))
assert mem[src_offset:src_offset+region_len] == mem[dest_offset:dest_offset+region_len]
await RisingEdge(dut.clk)
await RisingEdge(dut.clk)
# cocotb-test
tests_dir = os.path.dirname(__file__)
rtl_dir = os.path.abspath(os.path.join(tests_dir, '..', '..', 'rtl'))
lib_dir = os.path.abspath(os.path.join(rtl_dir, '..', 'lib'))
pcie_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'pcie', 'rtl'))
def test_fpga_core(request):
dut = "fpga_core"
module = os.path.splitext(os.path.basename(__file__))[0]
toplevel = dut
verilog_sources = [
os.path.join(rtl_dir, f"{dut}.v"),
os.path.join(rtl_dir, "common", "example_core_pcie_ptile.v"),
os.path.join(rtl_dir, "common", "example_core_pcie.v"),
os.path.join(rtl_dir, "common", "example_core.v"),
os.path.join(rtl_dir, "common", "axi_ram.v"),
os.path.join(pcie_rtl_dir, "pcie_ptile_if.v"),
os.path.join(pcie_rtl_dir, "pcie_ptile_if_rx.v"),
os.path.join(pcie_rtl_dir, "pcie_ptile_if_tx.v"),
os.path.join(pcie_rtl_dir, "pcie_ptile_cfg.v"),
os.path.join(pcie_rtl_dir, "pcie_axil_master.v"),
os.path.join(pcie_rtl_dir, "pcie_axi_master.v"),
os.path.join(pcie_rtl_dir, "pcie_axi_master_rd.v"),
os.path.join(pcie_rtl_dir, "pcie_axi_master_wr.v"),
os.path.join(pcie_rtl_dir, "pcie_tlp_demux_bar.v"),
os.path.join(pcie_rtl_dir, "pcie_tlp_demux.v"),
os.path.join(pcie_rtl_dir, "pcie_tlp_mux.v"),
os.path.join(pcie_rtl_dir, "pcie_tlp_fifo.v"),
os.path.join(pcie_rtl_dir, "pcie_tlp_fifo_raw.v"),
os.path.join(pcie_rtl_dir, "pcie_tlp_fifo_mux.v"),
os.path.join(pcie_rtl_dir, "pcie_msix.v"),
os.path.join(pcie_rtl_dir, "dma_if_pcie.v"),
os.path.join(pcie_rtl_dir, "dma_if_pcie_rd.v"),
os.path.join(pcie_rtl_dir, "dma_if_pcie_wr.v"),
os.path.join(pcie_rtl_dir, "dma_psdpram.v"),
os.path.join(pcie_rtl_dir, "priority_encoder.v"),
os.path.join(pcie_rtl_dir, "pulse_merge.v"),
]
parameters = {}
parameters['SEG_COUNT'] = 2
parameters['SEG_DATA_WIDTH'] = 256
parameters['SEG_EMPTY_WIDTH'] = (parameters['SEG_DATA_WIDTH'] // 32 - 1).bit_length()
parameters['SEG_HDR_WIDTH'] = 128
parameters['SEG_PRFX_WIDTH'] = 32
parameters['TX_SEQ_NUM_WIDTH'] = 6
parameters['PCIE_TAG_COUNT'] = 64
parameters['BAR0_APERTURE'] = 24
parameters['BAR2_APERTURE'] = 24
parameters['BAR4_APERTURE'] = 16
extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()}
sim_build = os.path.join(tests_dir, "sim_build",
request.node.name.replace('[', '-').replace(']', ''))
cocotb_test.simulator.run(
python_search=[tests_dir],
verilog_sources=verilog_sources,
toplevel=toplevel,
module=module,
parameters=parameters,
sim_build=sim_build,
extra_env=extra_env,
)