mirror of https://github.com/openXC7/prjxray.git
A minitest for ISERDES in NETWORKING SDR/DDR modes.
Signed-off-by: Maciej Kurc <mkurc@antmicro.com>
This commit is contained in:
parent
6d21194b56
commit
b878a2e651
|
|
@ -0,0 +1,38 @@
|
|||
SYNTH ?= vivado
|
||||
YOSYS = $(XRAY_DIR)/third_party/yosys/yosys
|
||||
PART = xc7a35tcsg324-1
|
||||
|
||||
clean:
|
||||
@find . -name "build-par.*" | xargs rm -rf
|
||||
@find . -name "build-syn.*" | xargs rm -rf
|
||||
@rm -f *.edif
|
||||
@rm -f *.bit
|
||||
@rm -f *.bin
|
||||
@rm -f *.log
|
||||
@rm -f *.dcp
|
||||
|
||||
help:
|
||||
@echo "Usage: make all [SYNTH=<vivado/yosys>]"
|
||||
|
||||
.PHONY: clean help
|
||||
|
||||
$(YOSYS):
|
||||
cd $(XRAY_DIR)/third_party/yosys && make config-gcc && make -j$(shell nproc)
|
||||
|
||||
ifeq ($(SYNTH), yosys)
|
||||
%.edif: %.v $(YOSYS)
|
||||
$(YOSYS) -p "read_verilog $< ; synth_xilinx -flatten -nosrl; write_edif -pvector bra -attrprop $@" -l $@.log
|
||||
|
||||
else ifeq ($(SYNTH), vivado)
|
||||
%.edif: %.v
|
||||
mkdir -p build-syn.$(basename $@)
|
||||
cd build-syn.$(basename $@) && env PROJECT_NAME=$(basename $@) $(XRAY_VIVADO) -mode batch -source ../syn.tcl -nojournal -log ../$@.log
|
||||
rm -rf *.backup.log
|
||||
|
||||
endif
|
||||
|
||||
%.bit: %.edif par.tcl
|
||||
mkdir -p build-par.$(basename $@)
|
||||
cd build-par.$(basename $@) && env PROJECT_NAME=$(basename $@) $(XRAY_VIVADO) -mode batch -source ../par.tcl -nojournal -log ../$@.log
|
||||
rm -rf *.backup.log
|
||||
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
# ISERDES minitest for SDR and DDR
|
||||
|
||||
This test allows to verify that ISEDRES is working on hardware. Tested modes are:
|
||||
- NETWORKING / SDR
|
||||
- NETWORKING / DDR
|
||||
|
||||
No chaining of two ISERDES bels.
|
||||
|
||||
The design uses JA, JB and JC connectors of the Basys 3 boards to output
|
||||
serialized data and then receive it using ISERDESes. There is a need to
|
||||
provide physical loopbacks of pins of those connectors. The clock is being
|
||||
routed internally.
|
||||
|
||||
The received data is compared against transmitted internally. Errors are
|
||||
indicated using LEDs.
|
||||
|
||||
The pinout (out, in):
|
||||
- JB.1, JB.7 - SDR, WIDTH=2
|
||||
- JB.2, JB.8 - SDR, WIDTH=3
|
||||
- JB.3, JB.9 - SDR, WIDTH=4
|
||||
- JB.4, JB.10 - SDR, WIDTH=5
|
||||
- JC.1, JC.7 - SDR, WIDTH=6
|
||||
- JC.2, JC.8 - SDR, WIDTH=7
|
||||
- JC.3, JC.9 - SDR, WIDTH=8
|
||||
- JC.4, JC.10 - DDR, WIDTH=4
|
||||
- JA.4, JA.10 - DDR, WIDTH=6
|
||||
- JA.3, JA.9 - DDR, WIDTH=8
|
||||
- JA.2 - Serialized data clock
|
||||
- JA.1 - Serialized data clock x2
|
||||
|
||||
LEDs indicate whether data is being received corectly. When a LED is lit then
|
||||
there is correct reception:
|
||||
- LED0 - SDR, WIDTH=2
|
||||
- LED1 - SDR, WIDTH=3
|
||||
- LED2 - SDR, WIDTH=4
|
||||
- LED3 - SDR, WIDTH=5
|
||||
- LED4 - SDR, WIDTH=6
|
||||
- LED5 - SDR, WIDTH=7
|
||||
- LED6 - SDR, WIDTH=8
|
||||
- LED7 - DDR, WIDTH=4
|
||||
- LED8 - DDR, WIDTH=5
|
||||
- LED9 - DDR, WIDTH=6
|
||||
- LED10 - Blinking
|
||||
|
|
@ -0,0 +1,72 @@
|
|||
create_clock -period 10.000 -name clk [get_ports clk]
|
||||
|
||||
set_property PACKAGE_PIN W5 [get_ports clk]
|
||||
|
||||
set_property PACKAGE_PIN B18 [get_ports rx]
|
||||
set_property PACKAGE_PIN A18 [get_ports tx]
|
||||
|
||||
set_property PACKAGE_PIN V17 [get_ports sw[ 0]]
|
||||
set_property PACKAGE_PIN V16 [get_ports sw[ 1]]
|
||||
set_property PACKAGE_PIN W16 [get_ports sw[ 2]]
|
||||
set_property PACKAGE_PIN W17 [get_ports sw[ 3]]
|
||||
set_property PACKAGE_PIN W15 [get_ports sw[ 4]]
|
||||
set_property PACKAGE_PIN V15 [get_ports sw[ 5]]
|
||||
set_property PACKAGE_PIN W14 [get_ports sw[ 6]]
|
||||
set_property PACKAGE_PIN W13 [get_ports sw[ 7]]
|
||||
set_property PACKAGE_PIN V2 [get_ports sw[ 8]]
|
||||
set_property PACKAGE_PIN T3 [get_ports sw[ 9]]
|
||||
set_property PACKAGE_PIN T2 [get_ports sw[10]]
|
||||
set_property PACKAGE_PIN R3 [get_ports sw[11]]
|
||||
set_property PACKAGE_PIN W2 [get_ports sw[12]]
|
||||
set_property PACKAGE_PIN U1 [get_ports sw[13]]
|
||||
set_property PACKAGE_PIN T1 [get_ports sw[14]]
|
||||
set_property PACKAGE_PIN R2 [get_ports sw[15]]
|
||||
|
||||
set_property PACKAGE_PIN U16 [get_ports led[ 0]]
|
||||
set_property PACKAGE_PIN E19 [get_ports led[ 1]]
|
||||
set_property PACKAGE_PIN U19 [get_ports led[ 2]]
|
||||
set_property PACKAGE_PIN V19 [get_ports led[ 3]]
|
||||
set_property PACKAGE_PIN W18 [get_ports led[ 4]]
|
||||
set_property PACKAGE_PIN U15 [get_ports led[ 5]]
|
||||
set_property PACKAGE_PIN U14 [get_ports led[ 6]]
|
||||
set_property PACKAGE_PIN V14 [get_ports led[ 7]]
|
||||
set_property PACKAGE_PIN V13 [get_ports led[ 8]]
|
||||
set_property PACKAGE_PIN V3 [get_ports led[ 9]]
|
||||
set_property PACKAGE_PIN W3 [get_ports led[10]]
|
||||
set_property PACKAGE_PIN U3 [get_ports led[11]]
|
||||
set_property PACKAGE_PIN P3 [get_ports led[12]]
|
||||
set_property PACKAGE_PIN N3 [get_ports led[13]]
|
||||
set_property PACKAGE_PIN P1 [get_ports led[14]]
|
||||
set_property PACKAGE_PIN L1 [get_ports led[15]]
|
||||
|
||||
set_property PACKAGE_PIN J1 [get_ports ja1]
|
||||
set_property PACKAGE_PIN L2 [get_ports ja2]
|
||||
set_property PACKAGE_PIN J2 [get_ports ja3]
|
||||
set_property PACKAGE_PIN G2 [get_ports ja4]
|
||||
set_property PACKAGE_PIN H1 [get_ports ja7]
|
||||
set_property PACKAGE_PIN K2 [get_ports ja8]
|
||||
set_property PACKAGE_PIN H2 [get_ports ja9]
|
||||
set_property PACKAGE_PIN G3 [get_ports ja10]
|
||||
|
||||
set_property PACKAGE_PIN A14 [get_ports jb1]
|
||||
set_property PACKAGE_PIN A16 [get_ports jb2]
|
||||
set_property PACKAGE_PIN B15 [get_ports jb3]
|
||||
set_property PACKAGE_PIN B16 [get_ports jb4]
|
||||
set_property PACKAGE_PIN A15 [get_ports jb7]
|
||||
set_property PACKAGE_PIN A17 [get_ports jb8]
|
||||
set_property PACKAGE_PIN C15 [get_ports jb9]
|
||||
set_property PACKAGE_PIN C16 [get_ports jb10]
|
||||
|
||||
set_property PACKAGE_PIN K17 [get_ports jc1]
|
||||
set_property PACKAGE_PIN M18 [get_ports jc2]
|
||||
set_property PACKAGE_PIN N17 [get_ports jc3]
|
||||
set_property PACKAGE_PIN P18 [get_ports jc4]
|
||||
set_property PACKAGE_PIN L17 [get_ports jc7]
|
||||
set_property PACKAGE_PIN M19 [get_ports jc8]
|
||||
set_property PACKAGE_PIN P17 [get_ports jc9]
|
||||
set_property PACKAGE_PIN R18 [get_ports jc10]
|
||||
|
||||
foreach port [get_ports] {
|
||||
set_property IOSTANDARD LVCMOS33 $port
|
||||
set_property SLEW FAST $port
|
||||
}
|
||||
|
|
@ -0,0 +1,266 @@
|
|||
`include "src/rom.v"
|
||||
`include "src/serializer.v"
|
||||
`include "src/transmitter.v"
|
||||
`include "src/receiver.v"
|
||||
`include "src/comparator.v"
|
||||
`include "src/trx_path.v"
|
||||
|
||||
`default_nettype none
|
||||
|
||||
// ============================================================================
|
||||
|
||||
module top
|
||||
(
|
||||
input wire clk,
|
||||
|
||||
input wire rx,
|
||||
output wire tx,
|
||||
|
||||
input wire [15:0] sw,
|
||||
output wire [15:0] led,
|
||||
|
||||
output wire ja1,
|
||||
output wire ja2,
|
||||
output wire ja3,
|
||||
output wire ja4,
|
||||
input wire ja7,
|
||||
input wire ja8,
|
||||
input wire ja9,
|
||||
input wire ja10,
|
||||
|
||||
output wire jb1,
|
||||
output wire jb2,
|
||||
output wire jb3,
|
||||
output wire jb4,
|
||||
input wire jb7,
|
||||
input wire jb8,
|
||||
input wire jb9,
|
||||
input wire jb10,
|
||||
|
||||
output wire jc1,
|
||||
output wire jc2,
|
||||
output wire jc3,
|
||||
output wire jc4,
|
||||
input wire jc7,
|
||||
input wire jc8,
|
||||
input wire jc9,
|
||||
input wire jc10
|
||||
);
|
||||
|
||||
// ============================================================================
|
||||
// Clock & reset
|
||||
// Divide the input clock to allow for less strict timing requirements.
|
||||
reg [3:0] rst_sr;
|
||||
reg [7:0] clk_ps;
|
||||
|
||||
initial rst_sr <= 4'hF;
|
||||
initial clk_ps <= 0;
|
||||
|
||||
always @(posedge clk)
|
||||
if (sw[0])
|
||||
rst_sr <= 4'hF;
|
||||
else
|
||||
rst_sr <= rst_sr >> 1;
|
||||
|
||||
always @(posedge clk)
|
||||
clk_ps <= clk_ps + 1;
|
||||
|
||||
wire CLK100 = clk;
|
||||
wire CLK = clk_ps[2];
|
||||
wire RST = rst_sr[0];
|
||||
|
||||
// ============================================================================
|
||||
// ISERDES test logic
|
||||
wire [9:0] error;
|
||||
wire [9:0] data;
|
||||
|
||||
wire s_clk;
|
||||
|
||||
// ........
|
||||
|
||||
trx_path #
|
||||
(
|
||||
.WIDTH (2),
|
||||
.MODE ("SDR")
|
||||
)
|
||||
path_sdr_2
|
||||
(
|
||||
.CLK (CLK),
|
||||
.RST (RST),
|
||||
.O_DAT (data[0]),
|
||||
.O_CLK (s_clk),
|
||||
.I_DAT (jb7),
|
||||
.ERROR (error[0])
|
||||
);
|
||||
|
||||
trx_path #
|
||||
(
|
||||
.WIDTH (3),
|
||||
.MODE ("SDR")
|
||||
)
|
||||
path_sdr_3
|
||||
(
|
||||
.CLK (CLK),
|
||||
.RST (RST),
|
||||
.O_DAT (data[1]),
|
||||
.I_DAT (jb8),
|
||||
.ERROR (error[1])
|
||||
);
|
||||
|
||||
trx_path #
|
||||
(
|
||||
.WIDTH (4),
|
||||
.MODE ("SDR")
|
||||
)
|
||||
path_sdr_4
|
||||
(
|
||||
.CLK (CLK),
|
||||
.RST (RST),
|
||||
.O_DAT (data[2]),
|
||||
.I_DAT (jb9),
|
||||
.ERROR (error[2])
|
||||
);
|
||||
|
||||
trx_path #
|
||||
(
|
||||
.WIDTH (5),
|
||||
.MODE ("SDR")
|
||||
)
|
||||
path_sdr_5
|
||||
(
|
||||
.CLK (CLK),
|
||||
.RST (RST),
|
||||
.O_DAT (data[3]),
|
||||
.I_DAT (jb10),
|
||||
.ERROR (error[3])
|
||||
);
|
||||
|
||||
// ........
|
||||
|
||||
trx_path #
|
||||
(
|
||||
.WIDTH (6),
|
||||
.MODE ("SDR")
|
||||
)
|
||||
path_sdr_6
|
||||
(
|
||||
.CLK (CLK),
|
||||
.RST (RST),
|
||||
.O_DAT (data[4]),
|
||||
.I_DAT (jc7),
|
||||
.ERROR (error[4])
|
||||
);
|
||||
|
||||
trx_path #
|
||||
(
|
||||
.WIDTH (7),
|
||||
.MODE ("SDR")
|
||||
)
|
||||
path_sdr_7
|
||||
(
|
||||
.CLK (CLK),
|
||||
.RST (RST),
|
||||
.O_DAT (data[5]),
|
||||
.I_DAT (jc8),
|
||||
.ERROR (error[5])
|
||||
);
|
||||
|
||||
trx_path #
|
||||
(
|
||||
.WIDTH (8),
|
||||
.MODE ("SDR")
|
||||
)
|
||||
path_sdr_8
|
||||
(
|
||||
.CLK (CLK),
|
||||
.RST (RST),
|
||||
.O_DAT (data[6]),
|
||||
.I_DAT (jc9),
|
||||
.ERROR (error[6])
|
||||
);
|
||||
|
||||
trx_path #
|
||||
(
|
||||
.WIDTH (4),
|
||||
.MODE ("DDR")
|
||||
)
|
||||
path_ddr_4
|
||||
(
|
||||
.CLK (CLK),
|
||||
.RST (RST),
|
||||
.O_DAT (data[7]),
|
||||
.I_DAT (jc10),
|
||||
.ERROR (error[7])
|
||||
);
|
||||
|
||||
// ........
|
||||
|
||||
trx_path #
|
||||
(
|
||||
.WIDTH (6),
|
||||
.MODE ("DDR")
|
||||
)
|
||||
path_ddr_6
|
||||
(
|
||||
.CLK (CLK),
|
||||
.RST (RST),
|
||||
.O_DAT (data[8]),
|
||||
.I_DAT (ja10),
|
||||
.ERROR (error[8])
|
||||
);
|
||||
|
||||
trx_path #
|
||||
(
|
||||
.WIDTH (8),
|
||||
.MODE ("DDR")
|
||||
)
|
||||
path_ddr_8
|
||||
(
|
||||
.CLK (CLK),
|
||||
.RST (RST),
|
||||
.O_DAT (data[9]),
|
||||
.I_DAT (ja9),
|
||||
.ERROR (error[9])
|
||||
);
|
||||
|
||||
// ============================================================================
|
||||
// Delay data by 1 cycle of the 100MHz clock to avoid race condition betweeen
|
||||
// serialized clock and data edges. We are not using IDELAY to compensate for
|
||||
// that in this design. In other words the data is delayed at the transmitter
|
||||
// side.
|
||||
|
||||
reg [9:0] data_dly;
|
||||
|
||||
always @(posedge CLK100)
|
||||
data_dly <= data;
|
||||
|
||||
// ============================================================================
|
||||
// I/O connections
|
||||
|
||||
reg [23:0] heartbeat_cnt;
|
||||
|
||||
always @(posedge CLK100)
|
||||
heartbeat_cnt <= heartbeat_cnt + 1;
|
||||
|
||||
|
||||
assign led[9: 0] = (RST) ? 9'd0 : ~error;
|
||||
assign led[ 10] = heartbeat_cnt[22];
|
||||
assign led[15:11] = 0;
|
||||
|
||||
assign jb1 = data_dly[0];
|
||||
assign jb2 = data_dly[1];
|
||||
assign jb3 = data_dly[2];
|
||||
assign jb4 = data_dly[3];
|
||||
|
||||
assign jc1 = data_dly[4];
|
||||
assign jc2 = data_dly[5];
|
||||
assign jc3 = data_dly[6];
|
||||
assign jc4 = data_dly[7];
|
||||
|
||||
assign ja4 = data_dly[8];
|
||||
assign ja3 = data_dly[9];
|
||||
|
||||
assign ja1 = CLK;
|
||||
assign ja2 = s_clk;
|
||||
|
||||
endmodule
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
create_project -force -name $env(PROJECT_NAME) -part xc7a35tcpg236-1
|
||||
|
||||
read_edif ../$env(PROJECT_NAME).edif
|
||||
|
||||
link_design -part xc7a35tcpg236-1
|
||||
source ../basys3.xdc
|
||||
|
||||
report_timing_summary -file top_timing_synth.rpt
|
||||
report_utilization -hierarchical -file top_utilization_hierarchical_synth.rpt
|
||||
report_utilization -file top_utilization_synth.rpt
|
||||
|
||||
opt_design
|
||||
place_design
|
||||
|
||||
report_utilization -hierarchical -file top_utilization_hierarchical_place.rpt
|
||||
report_utilization -file top_utilization_place.rpt
|
||||
report_io -file top_io.rpt
|
||||
report_control_sets -verbose -file top_control_sets.rpt
|
||||
report_clock_utilization -file top_clock_utilization.rpt
|
||||
|
||||
route_design
|
||||
#phys_opt_design
|
||||
|
||||
report_timing_summary -no_header -no_detailed_paths
|
||||
|
||||
write_checkpoint -force ../$env(PROJECT_NAME).dcp
|
||||
|
||||
set_property SEVERITY {Warning} [get_drc_checks UCIO-1]
|
||||
set_property SEVERITY {Warning} [get_drc_checks NSTD-1]
|
||||
|
||||
report_route_status -file top_route_status.rpt
|
||||
report_drc -file top_drc.rpt
|
||||
report_timing_summary -datasheet -max_paths 10 -file top_timing.rpt
|
||||
report_power -file top_power.rpt
|
||||
|
||||
write_bitstream -force ../$env(PROJECT_NAME).bit
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
`include "../src/rom.v"
|
||||
`include "../src/serializer.v"
|
||||
`include "../src/transmitter.v"
|
||||
`include "../src/receiver.v"
|
||||
`include "../src/comparator.v"
|
||||
`include "../src/trx_path.v"
|
||||
|
||||
`default_nettype none
|
||||
`timescale 1ns / 1ps
|
||||
|
||||
// ============================================================================
|
||||
|
||||
module tb;
|
||||
|
||||
// ============================================================================
|
||||
|
||||
reg CLK;
|
||||
initial CLK <= 1'b0;
|
||||
always #0.5 CLK <= !CLK;
|
||||
|
||||
reg [3:0] rst_sr;
|
||||
initial rst_sr <= 4'hF;
|
||||
always @(posedge CLK) rst_sr <= rst_sr >> 1;
|
||||
wire RST;
|
||||
assign RST = rst_sr[0];
|
||||
|
||||
// ============================================================================
|
||||
|
||||
initial begin
|
||||
$dumpfile("waveforms.vcd");
|
||||
$dumpvars;
|
||||
end
|
||||
|
||||
integer cycle_cnt;
|
||||
initial cycle_cnt <= 0;
|
||||
|
||||
always @(posedge CLK)
|
||||
if (!RST) cycle_cnt <= cycle_cnt + 1;
|
||||
|
||||
always @(posedge CLK)
|
||||
if (!RST && cycle_cnt >= 10000)
|
||||
$finish;
|
||||
|
||||
// ============================================================================
|
||||
wire s_dat;
|
||||
|
||||
trx_path #
|
||||
(
|
||||
.WIDTH (8),
|
||||
.MODE ("SDR")
|
||||
)
|
||||
trx_path
|
||||
(
|
||||
.CLK (CLK),
|
||||
.RST (RST),
|
||||
|
||||
.O_DAT (s_dat),
|
||||
.I_DAT (s_dat)
|
||||
);
|
||||
|
||||
endmodule
|
||||
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
# Check args
|
||||
if [ "$#" -ne 1 ]; then
|
||||
echo "Usage: run_vivado.sh <testbench file>"
|
||||
exit -1
|
||||
fi
|
||||
|
||||
# Check if testbench exists
|
||||
if [ ! -f $1 ]; then
|
||||
echo "Testbench $1 not found!"
|
||||
exit -1
|
||||
fi
|
||||
|
||||
# Create sources file
|
||||
cp sources.cf.template sources.cf
|
||||
echo $1 >> sources.cf
|
||||
|
||||
# Compile
|
||||
iverilog -v -c sources.cf -g2005 -s tb -o testbench.vvp
|
||||
|
||||
# Run
|
||||
vvp -v testbench.vvp
|
||||
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
# Check args
|
||||
if [ "$#" -ne 1 ]; then
|
||||
echo "Usage: run_vivado.sh <testbench file>"
|
||||
exit -1
|
||||
fi
|
||||
|
||||
# Check if testbench exists
|
||||
if [ ! -f $1 ]; then
|
||||
echo "Testbench $1 not found!"
|
||||
exit -1
|
||||
fi
|
||||
|
||||
# Run Vivado
|
||||
TESTBENCH_TITLE=$(basename $1 .v) ${XRAY_VIVADO} -mode batch -source sim.tcl -nojournal -verbose -log vivado.log
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
create_project -force -part xc7a35ticsg324-1L $::env(TESTBENCH_TITLE) $::env(TESTBENCH_TITLE)
|
||||
|
||||
read_verilog $::env(TESTBENCH_TITLE).v
|
||||
|
||||
set_property top tb [get_filesets sim_1]
|
||||
|
||||
synth_design -top tb -verbose
|
||||
|
||||
set_property xsim.simulate.log_all_signals true [get_filesets sim_1]
|
||||
set_property xsim.simulate.runtime 0 [get_filesets sim_1]
|
||||
|
||||
launch_simulation -verbose
|
||||
restart
|
||||
|
||||
open_vcd ../../../../waveforms.vcd
|
||||
|
||||
run -all
|
||||
|
||||
flush_vcd
|
||||
close_vcd
|
||||
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
../src/rom.v
|
||||
../src/serializer.v
|
||||
../src/transmitter.v
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
`default_nettype none
|
||||
`timescale 1ns / 1ps
|
||||
|
||||
// ============================================================================
|
||||
|
||||
module tb;
|
||||
|
||||
// ============================================================================
|
||||
|
||||
reg CLK;
|
||||
initial CLK <= 1'b0;
|
||||
always #0.5 CLK <= !CLK;
|
||||
|
||||
reg [3:0] rst_sr;
|
||||
initial rst_sr <= 4'hF;
|
||||
always @(posedge CLK) rst_sr <= rst_sr >> 1;
|
||||
wire RST;
|
||||
assign RST = rst_sr[0];
|
||||
|
||||
// ============================================================================
|
||||
|
||||
initial begin
|
||||
$dumpfile("waveforms.vcd");
|
||||
$dumpvars;
|
||||
end
|
||||
|
||||
integer cycle_cnt;
|
||||
initial cycle_cnt <= 0;
|
||||
|
||||
always @(posedge CLK)
|
||||
if (!RST) cycle_cnt <= cycle_cnt + 1;
|
||||
|
||||
always @(posedge CLK)
|
||||
if (!RST && cycle_cnt >= 100)
|
||||
$finish;
|
||||
|
||||
// ============================================================================
|
||||
wire o_stb;
|
||||
wire [7:0] o_dat;
|
||||
|
||||
wire s_clk;
|
||||
wire s_ce;
|
||||
wire s_dat;
|
||||
|
||||
transmitter #
|
||||
(
|
||||
.WIDTH (8),
|
||||
.MODE ("SDR")
|
||||
)
|
||||
transmitter
|
||||
(
|
||||
.CLK (CLK),
|
||||
.RST (RST),
|
||||
|
||||
.O_STB (o_stb),
|
||||
.O_DAT (o_dat),
|
||||
|
||||
.S_CLK (s_clk),
|
||||
.S_CE (s_ce),
|
||||
.S_DAT (s_dat)
|
||||
);
|
||||
|
||||
endmodule
|
||||
|
|
@ -0,0 +1,116 @@
|
|||
`default_nettype none
|
||||
|
||||
// ============================================================================
|
||||
|
||||
module comparator #
|
||||
(
|
||||
parameter WIDTH = 8,
|
||||
parameter ERROR_COUNT = 8,
|
||||
parameter ERROR_HOLD = 2500000
|
||||
)
|
||||
(
|
||||
// Clock and reset
|
||||
input wire CLK,
|
||||
input wire RST,
|
||||
|
||||
// Transmitted data input port
|
||||
input wire TX_STB,
|
||||
input wire [WIDTH-1:0] TX_DAT,
|
||||
|
||||
// Received data input port + bitslip
|
||||
input wire RX_STB,
|
||||
input wire [WIDTH-1:0] RX_DAT,
|
||||
output wire RX_BITSLIP,
|
||||
|
||||
// Error indicator
|
||||
output wire O_ERROR
|
||||
);
|
||||
|
||||
// ============================================================================
|
||||
// Data latch and comparator
|
||||
reg [WIDTH-1:0] tx_dat;
|
||||
reg tx_valid;
|
||||
|
||||
reg [WIDTH-1:0] rx_dat;
|
||||
reg rx_valid;
|
||||
|
||||
wire i_rdy = rx_valid && rx_valid;
|
||||
|
||||
always @(posedge CLK)
|
||||
if (!tx_valid && TX_STB)
|
||||
tx_dat <= TX_DAT;
|
||||
|
||||
always @(posedge CLK)
|
||||
if (RST)
|
||||
tx_valid <= 1'b0;
|
||||
else if (i_rdy)
|
||||
tx_valid <= 1'b0;
|
||||
else if (TX_STB)
|
||||
tx_valid <= 1'b1;
|
||||
|
||||
always @(posedge CLK)
|
||||
if (!rx_valid && RX_STB)
|
||||
rx_dat <= RX_DAT;
|
||||
|
||||
always @(posedge CLK)
|
||||
if (RST)
|
||||
rx_valid <= 1'b0;
|
||||
else if (i_rdy)
|
||||
rx_valid <= 1'b0;
|
||||
else if (RX_STB)
|
||||
rx_valid <= 1'b1;
|
||||
|
||||
|
||||
reg x_stb;
|
||||
reg x_error;
|
||||
|
||||
always @(posedge CLK)
|
||||
if (RST)
|
||||
x_stb <= 1'b0;
|
||||
else if(!x_stb && i_rdy)
|
||||
x_stb <= 1'b1;
|
||||
else if( x_stb)
|
||||
x_stb <= 1'b0;
|
||||
|
||||
always @(posedge CLK)
|
||||
if (i_rdy)
|
||||
x_error <= (rx_dat != tx_dat);
|
||||
|
||||
// ============================================================================
|
||||
// Error counter and bitslip generator
|
||||
reg [31:0] count_err;
|
||||
reg o_bitslip;
|
||||
|
||||
always @(posedge CLK)
|
||||
if (RST)
|
||||
count_err <= 0;
|
||||
else if (x_stb && x_error)
|
||||
count_err <= count_err + 1;
|
||||
else if (o_bitslip)
|
||||
count_err <= 0;
|
||||
|
||||
always @(posedge CLK)
|
||||
if (RST)
|
||||
o_bitslip <= 1'b0;
|
||||
else if (!o_bitslip && (count_err >= ERROR_COUNT))
|
||||
o_bitslip <= 1'b1;
|
||||
else if ( o_bitslip)
|
||||
o_bitslip <= 1'b0;
|
||||
|
||||
assign RX_BITSLIP = o_bitslip;
|
||||
|
||||
// ============================================================================
|
||||
// Error output
|
||||
reg [32:0] o_cnt;
|
||||
|
||||
always @(posedge CLK)
|
||||
if (RST)
|
||||
o_cnt <= 0;
|
||||
else if (x_stb && x_error)
|
||||
o_cnt <= ERROR_HOLD;
|
||||
else
|
||||
o_cnt <= (o_cnt[32]) ? o_cnt : (o_cnt - 1);
|
||||
|
||||
assign O_ERROR = !o_cnt[32];
|
||||
|
||||
endmodule
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
#!/usr/bin/env python3
|
||||
import random
|
||||
|
||||
def main():
|
||||
|
||||
template = """
|
||||
`default_nettype none
|
||||
|
||||
// ============================================================================
|
||||
|
||||
module rom
|
||||
(
|
||||
input wire CLK,
|
||||
input wire RST,
|
||||
|
||||
input wire RD,
|
||||
output wire [{rom_width_minus_one}:0] O
|
||||
);
|
||||
|
||||
// ============================================================================
|
||||
|
||||
reg [{rom_width_minus_one}:0] rom[0:{rom_size_minus_one}];
|
||||
|
||||
initial begin
|
||||
{rom_data}
|
||||
end
|
||||
|
||||
reg [{rom_width_minus_one}:0] dat;
|
||||
reg [{rom_size_bits_minus_one}:0] adr;
|
||||
|
||||
always @(posedge CLK)
|
||||
if (RST) adr <= 0;
|
||||
else if (RD) adr <= adr + 1;
|
||||
|
||||
always @(posedge CLK)
|
||||
if (RD) dat <= rom[adr];
|
||||
|
||||
assign O = dat;
|
||||
|
||||
// ============================================================================
|
||||
|
||||
endmodule
|
||||
"""
|
||||
|
||||
rom_size_bits = 5
|
||||
rom_size = 2 ** rom_size_bits
|
||||
rom_width = 8
|
||||
|
||||
rom_data = [random.randint(0, 2 ** rom_width - 1) for i in range(rom_size)]
|
||||
|
||||
# rom_data = []
|
||||
# for i in range(rom_size // 2):
|
||||
# rom_data.extend([0x00, 0xFF])
|
||||
|
||||
rom_data = "\n".join([" rom[%4d] <= %d'd%d;" % (i, rom_width, d) for i, d in enumerate(rom_data)])
|
||||
|
||||
print(template.format(
|
||||
rom_size_bits_minus_one=rom_size_bits - 1,
|
||||
rom_size_minus_one=rom_size - 1,
|
||||
rom_width_minus_one=rom_width - 1,
|
||||
rom_data=rom_data
|
||||
))
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
||||
|
|
@ -0,0 +1,156 @@
|
|||
`default_nettype none
|
||||
|
||||
// ============================================================================
|
||||
|
||||
module receiver #
|
||||
(
|
||||
parameter WIDTH = 8,
|
||||
parameter MODE = "SDR"
|
||||
)
|
||||
(
|
||||
input wire CLK,
|
||||
input wire RST,
|
||||
|
||||
input wire I_CLK,
|
||||
input wire I_DAT,
|
||||
|
||||
output wire O_STB,
|
||||
output wire [WIDTH-1:0] O_DAT,
|
||||
input wire O_BITSLIP
|
||||
);
|
||||
|
||||
// ============================================================================
|
||||
// CLKDIV generation using a BUFR
|
||||
wire i_clkdiv;
|
||||
wire i_rstdiv;
|
||||
|
||||
// Divider for BUFR
|
||||
localparam DIVIDE = (MODE == "SDR" && WIDTH == 2) ? "2" :
|
||||
(MODE == "SDR" && WIDTH == 3) ? "3" :
|
||||
(MODE == "SDR" && WIDTH == 4) ? "4" :
|
||||
(MODE == "SDR" && WIDTH == 5) ? "5" :
|
||||
(MODE == "SDR" && WIDTH == 6) ? "6" :
|
||||
(MODE == "SDR" && WIDTH == 7) ? "7" :
|
||||
(MODE == "SDR" && WIDTH == 8) ? "8" :
|
||||
|
||||
(MODE == "DDR" && WIDTH == 4) ? "2" :
|
||||
(MODE == "DDR" && WIDTH == 6) ? "3" :
|
||||
(MODE == "DDR" && WIDTH == 8) ? "4" : "BYPASS";
|
||||
// BUFR
|
||||
BUFR #
|
||||
(
|
||||
.BUFR_DIVIDE (DIVIDE)
|
||||
)
|
||||
bufr_div
|
||||
(
|
||||
.I (I_CLK),
|
||||
.O (i_clkdiv),
|
||||
.CLR (1'b0),
|
||||
.CE (1'b1)
|
||||
);
|
||||
|
||||
// ISERDES reset generator
|
||||
reg [3:0] rst_sr;
|
||||
initial rst_sr <= 4'hF;
|
||||
|
||||
always @(posedge i_clkdiv)
|
||||
if (RST) rst_sr <= 4'hF;
|
||||
else rst_sr <= rst_sr >> 1;
|
||||
|
||||
assign i_rstdiv = rst_sr[0];
|
||||
|
||||
// ============================================================================
|
||||
// ISERDES
|
||||
wire [7:0] d_dat;
|
||||
|
||||
(* KEEP, DONT_TOUCH *)
|
||||
ISERDESE2 #
|
||||
(
|
||||
.DATA_RATE (MODE),
|
||||
.DATA_WIDTH (WIDTH),
|
||||
.INTERFACE_TYPE ("NETWORKING"),
|
||||
.IS_CLKB_INVERTED (1'b1) // Do we have bits for that ??
|
||||
)
|
||||
iserdes
|
||||
(
|
||||
.CLK (I_CLK),
|
||||
.CLKB (I_CLK),
|
||||
.CLKDIV (i_clkdiv),
|
||||
.CE1 (1'b1),
|
||||
.CE2 (1'b1),
|
||||
.RST (i_rstdiv),
|
||||
.BITSLIP (bitslip),
|
||||
|
||||
.D (I_DAT),
|
||||
.Q1 (d_dat[0]),
|
||||
.Q2 (d_dat[1]),
|
||||
.Q3 (d_dat[2]),
|
||||
.Q4 (d_dat[3]),
|
||||
.Q5 (d_dat[4]),
|
||||
.Q6 (d_dat[5]),
|
||||
.Q7 (d_dat[6]),
|
||||
.Q8 (d_dat[7])
|
||||
);
|
||||
|
||||
// ============================================================================
|
||||
// Generate strobe synchronous to CLK
|
||||
reg clk_p;
|
||||
reg tick;
|
||||
|
||||
always @(posedge CLK)
|
||||
clk_p <= i_clkdiv;
|
||||
|
||||
always @(posedge CLK)
|
||||
if (RST)
|
||||
tick <= 1'b0;
|
||||
else
|
||||
tick <= !clk_p && i_clkdiv;
|
||||
|
||||
// ============================================================================
|
||||
// Bitslip. The bitslip signal should be synchronous to the CLKDIV. Here it is
|
||||
// asserted for as long as the CLKDIV period but it is not synchronous to it.
|
||||
reg bitslip_req;
|
||||
reg bitslip;
|
||||
|
||||
always @(posedge CLK)
|
||||
if (RST)
|
||||
bitslip_req <= 1'b0;
|
||||
else if (!bitslip_req && O_BITSLIP)
|
||||
bitslip_req <= 1'b1;
|
||||
else if (tick)
|
||||
bitslip_req <= 1'b0;
|
||||
|
||||
always @(posedge CLK)
|
||||
if (RST)
|
||||
bitslip <= 1'd0;
|
||||
else if (tick)
|
||||
bitslip <= bitslip_req;
|
||||
|
||||
// ============================================================================
|
||||
// Output sync to CLK
|
||||
reg x_stb;
|
||||
reg o_stb;
|
||||
reg [WIDTH-1:0] o_dat;
|
||||
|
||||
always @(posedge CLK)
|
||||
if (RST)
|
||||
x_stb <= 1'b0;
|
||||
else if(!x_stb && tick)
|
||||
x_stb <= 1'b1;
|
||||
else if( x_stb)
|
||||
x_stb <= 1'b0;
|
||||
|
||||
always @(posedge CLK)
|
||||
if (RST)
|
||||
o_stb <= 1'd0;
|
||||
else
|
||||
o_stb <= x_stb;
|
||||
|
||||
always @(posedge CLK)
|
||||
if (x_stb)
|
||||
o_dat <= d_dat;
|
||||
|
||||
assign O_STB = o_stb;
|
||||
assign O_DAT = o_dat[WIDTH-1:0];
|
||||
|
||||
endmodule
|
||||
|
|
@ -0,0 +1,69 @@
|
|||
|
||||
`default_nettype none
|
||||
|
||||
// ============================================================================
|
||||
|
||||
module rom
|
||||
(
|
||||
input wire CLK,
|
||||
input wire RST,
|
||||
|
||||
input wire RD,
|
||||
output wire [7:0] O
|
||||
);
|
||||
|
||||
// ============================================================================
|
||||
|
||||
reg [7:0] rom[0:31];
|
||||
|
||||
initial begin
|
||||
rom[ 0] <= 8'd157;
|
||||
rom[ 1] <= 8'd254;
|
||||
rom[ 2] <= 8'd208;
|
||||
rom[ 3] <= 8'd125;
|
||||
rom[ 4] <= 8'd39;
|
||||
rom[ 5] <= 8'd192;
|
||||
rom[ 6] <= 8'd242;
|
||||
rom[ 7] <= 8'd117;
|
||||
rom[ 8] <= 8'd186;
|
||||
rom[ 9] <= 8'd94;
|
||||
rom[ 10] <= 8'd201;
|
||||
rom[ 11] <= 8'd156;
|
||||
rom[ 12] <= 8'd224;
|
||||
rom[ 13] <= 8'd120;
|
||||
rom[ 14] <= 8'd255;
|
||||
rom[ 15] <= 8'd219;
|
||||
rom[ 16] <= 8'd12;
|
||||
rom[ 17] <= 8'd53;
|
||||
rom[ 18] <= 8'd156;
|
||||
rom[ 19] <= 8'd93;
|
||||
rom[ 20] <= 8'd97;
|
||||
rom[ 21] <= 8'd47;
|
||||
rom[ 22] <= 8'd9;
|
||||
rom[ 23] <= 8'd184;
|
||||
rom[ 24] <= 8'd68;
|
||||
rom[ 25] <= 8'd235;
|
||||
rom[ 26] <= 8'd67;
|
||||
rom[ 27] <= 8'd68;
|
||||
rom[ 28] <= 8'd216;
|
||||
rom[ 29] <= 8'd26;
|
||||
rom[ 30] <= 8'd16;
|
||||
rom[ 31] <= 8'd93;
|
||||
end
|
||||
|
||||
reg [7:0] dat;
|
||||
reg [4:0] adr;
|
||||
|
||||
always @(posedge CLK)
|
||||
if (RST) adr <= 0;
|
||||
else if (RD) adr <= adr + 1;
|
||||
|
||||
always @(posedge CLK)
|
||||
if (RD) dat <= rom[adr];
|
||||
|
||||
assign O = dat;
|
||||
|
||||
// ============================================================================
|
||||
|
||||
endmodule
|
||||
|
||||
|
|
@ -0,0 +1,82 @@
|
|||
`default_nettype none
|
||||
|
||||
// ============================================================================
|
||||
|
||||
module serializer #
|
||||
(
|
||||
parameter WIDTH = 4, // Serialization rate
|
||||
parameter MODE = "SDR" // "SDR" or "DDR"
|
||||
)
|
||||
(
|
||||
// Clock & reset
|
||||
input wire CLK,
|
||||
input wire RST,
|
||||
|
||||
// Data input
|
||||
input wire[WIDTH-1:0] I,
|
||||
output wire RD,
|
||||
output wire CE,
|
||||
|
||||
// Serialized output
|
||||
output wire O_CLK,
|
||||
output wire O_DAT
|
||||
);
|
||||
|
||||
// ============================================================================
|
||||
|
||||
generate if (MODE == "DDR" && (WIDTH & 1)) begin
|
||||
error for_DDR_mode_the_WIDTH_must_be_even ();
|
||||
end endgenerate
|
||||
|
||||
// ============================================================================
|
||||
// Output clock generation
|
||||
reg o_clk;
|
||||
wire ce;
|
||||
|
||||
always @(posedge CLK)
|
||||
if (RST) o_clk <= 1'd1;
|
||||
else o_clk <= !o_clk;
|
||||
|
||||
assign ce = !o_clk;
|
||||
|
||||
// ============================================================================
|
||||
reg [7:0] count;
|
||||
reg [WIDTH-1:0] sreg;
|
||||
wire sreg_ld;
|
||||
|
||||
always @(posedge CLK)
|
||||
if (RST) count <= 2;
|
||||
else if (ce) begin
|
||||
if (count == 0) count <= ((MODE == "DDR") ? (WIDTH/2) : WIDTH) - 1;
|
||||
else count <= count - 1;
|
||||
end
|
||||
|
||||
assign sreg_ld = (count == 0);
|
||||
|
||||
always @(posedge CLK)
|
||||
if (ce) begin
|
||||
if (sreg_ld) sreg <= I;
|
||||
else sreg <= sreg << ((MODE == "DDR") ? 2 : 1);
|
||||
end
|
||||
|
||||
wire [1:0] o_dat = sreg[WIDTH-1:WIDTH-2];
|
||||
|
||||
// ============================================================================
|
||||
// SDR/DDR output FFs
|
||||
reg o_reg;
|
||||
|
||||
always @(posedge CLK)
|
||||
if (!o_clk && MODE == "SDR") o_reg <= o_dat[1]; // +
|
||||
else if (!o_clk && MODE == "DDR") o_reg <= o_dat[0]; // +
|
||||
else if ( o_clk && MODE == "DDR") o_reg <= o_dat[1]; // -
|
||||
else o_reg <= o_reg;
|
||||
|
||||
// ============================================================================
|
||||
|
||||
assign O_DAT = o_reg;
|
||||
assign O_CLK = o_clk;
|
||||
|
||||
assign RD = (count == 1);
|
||||
assign CE = ce;
|
||||
|
||||
endmodule
|
||||
|
|
@ -0,0 +1,82 @@
|
|||
`default_nettype none
|
||||
|
||||
// ============================================================================
|
||||
|
||||
module transmitter #
|
||||
(
|
||||
parameter WIDTH = 8,
|
||||
parameter MODE = "SDR"
|
||||
)
|
||||
(
|
||||
// Input clock and reset
|
||||
input wire CLK,
|
||||
input wire RST,
|
||||
|
||||
// Data for comparison
|
||||
output wire O_STB,
|
||||
output wire [WIDTH-1:0] O_DAT,
|
||||
|
||||
// Serialized clock and data
|
||||
output wire S_CLK,
|
||||
output wire S_CE,
|
||||
output wire S_DAT
|
||||
);
|
||||
|
||||
// ============================================================================
|
||||
// ROM
|
||||
wire s_clk;
|
||||
wire s_ce;
|
||||
wire s_dat;
|
||||
|
||||
wire [WIDTH-1:0] rom_dat;
|
||||
wire rom_rd;
|
||||
|
||||
rom rom
|
||||
(
|
||||
.CLK (CLK),
|
||||
.RST (RST),
|
||||
|
||||
.RD (rom_rd & s_ce),
|
||||
.O (rom_dat) // Truncate bits if WIDTH < 8 here.
|
||||
);
|
||||
|
||||
// ============================================================================
|
||||
// Serializer
|
||||
|
||||
serializer #
|
||||
(
|
||||
.WIDTH (WIDTH),
|
||||
.MODE (MODE)
|
||||
)
|
||||
serializer
|
||||
(
|
||||
.CLK (CLK),
|
||||
.RST (RST),
|
||||
|
||||
.I (rom_dat),
|
||||
.RD (rom_rd),
|
||||
.CE (s_ce),
|
||||
|
||||
.O_CLK (s_clk),
|
||||
.O_DAT (s_dat)
|
||||
);
|
||||
|
||||
assign S_CLK = s_clk;
|
||||
assign S_CE = s_ce;
|
||||
assign S_DAT = s_dat;
|
||||
|
||||
// ============================================================================
|
||||
// Parallel output (for later comparison)
|
||||
reg o_stb;
|
||||
|
||||
always @(posedge CLK)
|
||||
if (RST) o_stb <= 1'b0;
|
||||
else if (!o_stb && s_ce && rom_rd) o_stb <= 1'b1;
|
||||
else if ( o_stb) o_stb <= 1'd0;
|
||||
|
||||
assign O_STB = o_stb;
|
||||
assign O_DAT = rom_dat;
|
||||
|
||||
// ============================================================================
|
||||
|
||||
endmodule
|
||||
|
|
@ -0,0 +1,138 @@
|
|||
`default_nettype none
|
||||
|
||||
// ============================================================================
|
||||
|
||||
module trx_path #
|
||||
(
|
||||
parameter WIDTH = 8,
|
||||
parameter MODE = "SDR"
|
||||
)
|
||||
(
|
||||
// Clock and reset
|
||||
input wire CLK,
|
||||
input wire RST,
|
||||
|
||||
// Input and output pins
|
||||
output wire O_CLK,
|
||||
output wire O_DAT,
|
||||
input wire I_DAT,
|
||||
|
||||
// Error indicator
|
||||
output wire ERROR
|
||||
);
|
||||
|
||||
// ============================================================================
|
||||
|
||||
wire tx_stb;
|
||||
wire [WIDTH-1:0] tx_dat;
|
||||
|
||||
wire rx_stb;
|
||||
wire [WIDTH-1:0] rx_dat;
|
||||
wire rx_bitslip;
|
||||
|
||||
wire s_clk;
|
||||
|
||||
// Transmitter
|
||||
transmitter #
|
||||
(
|
||||
.WIDTH (WIDTH),
|
||||
.MODE (MODE)
|
||||
)
|
||||
transmitter
|
||||
(
|
||||
.CLK (CLK),
|
||||
.RST (RST),
|
||||
|
||||
.O_STB (tx_stb),
|
||||
.O_DAT (tx_dat),
|
||||
|
||||
.S_CLK (s_clk),
|
||||
.S_DAT (O_DAT)
|
||||
);
|
||||
|
||||
assign O_CLK = s_clk;
|
||||
|
||||
// Receiver
|
||||
receiver #
|
||||
(
|
||||
.WIDTH (WIDTH),
|
||||
.MODE (MODE)
|
||||
)
|
||||
receiver
|
||||
(
|
||||
.CLK (CLK),
|
||||
.RST (RST),
|
||||
|
||||
.I_CLK (s_clk),
|
||||
.I_DAT (I_DAT),
|
||||
|
||||
.O_STB (rx_stb),
|
||||
.O_DAT (rx_dat),
|
||||
.O_BITSLIP (rx_bitslip)
|
||||
);
|
||||
|
||||
// The comparator module generates bitslip signal for the receiver. However
|
||||
// the bitslip can shift only modulo WIDTH. Therefore additional delay is
|
||||
// added which can delay the transmitted data that we compare to by a number
|
||||
// of full words.
|
||||
|
||||
// Count bitslip pulses to know how much to delay words
|
||||
reg [3:0] rx_bitslip_cnt;
|
||||
always @(posedge CLK)
|
||||
if (RST)
|
||||
rx_bitslip_cnt <= 0;
|
||||
else if (rx_bitslip) begin
|
||||
if (rx_bitslip_cnt == (2*WIDTH - 1))
|
||||
rx_bitslip_cnt <= 0;
|
||||
else
|
||||
rx_bitslip_cnt <= rx_bitslip_cnt + 1;
|
||||
end
|
||||
|
||||
// Word delay
|
||||
reg [1:0] tx_dly_cnt;
|
||||
reg [WIDTH-1:0] tx_dat_dly_a;
|
||||
reg [WIDTH-1:0] tx_dat_dly_b;
|
||||
reg [WIDTH-1:0] tx_dat_dly_c;
|
||||
reg [WIDTH-1:0] tx_dat_dly_d;
|
||||
wire [WIDTH-1:0] tx_dat_dly;
|
||||
|
||||
always @(posedge CLK)
|
||||
if (RST)
|
||||
tx_dly_cnt <= 0;
|
||||
else if(rx_bitslip && rx_bitslip_cnt == (2*WIDTH - 1))
|
||||
tx_dly_cnt <= tx_dly_cnt + 1;
|
||||
|
||||
always @(posedge CLK)
|
||||
if (tx_stb) begin
|
||||
tx_dat_dly_d <= tx_dat_dly_c;
|
||||
tx_dat_dly_c <= tx_dat_dly_b;
|
||||
tx_dat_dly_b <= tx_dat_dly_a;
|
||||
tx_dat_dly_a <= tx_dat;
|
||||
end
|
||||
|
||||
assign tx_dat_dly = (tx_dly_cnt == 0) ? tx_dat_dly_a :
|
||||
(tx_dly_cnt == 1) ? tx_dat_dly_b :
|
||||
(tx_dly_cnt == 2) ? tx_dat_dly_c :
|
||||
/*(tx_dly_cnt == 3) ?*/tx_dat_dly_d;
|
||||
|
||||
// Comparator
|
||||
comparator #
|
||||
(
|
||||
.WIDTH (WIDTH)
|
||||
)
|
||||
comparator
|
||||
(
|
||||
.CLK (CLK),
|
||||
.RST (RST),
|
||||
|
||||
.TX_STB (tx_stb),
|
||||
.TX_DAT (tx_dat_dly),
|
||||
|
||||
.RX_STB (rx_stb),
|
||||
.RX_DAT (rx_dat),
|
||||
.RX_BITSLIP (rx_bitslip),
|
||||
|
||||
.O_ERROR (ERROR)
|
||||
);
|
||||
|
||||
endmodule
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
create_project -force -name $env(PROJECT_NAME) -part xc7a35tcpg236-1
|
||||
|
||||
read_verilog ../$env(PROJECT_NAME).v
|
||||
|
||||
synth_design -top top
|
||||
|
||||
report_timing_summary -file top_timing_synth.rpt
|
||||
report_utilization -hierarchical -file top_utilization_hierarchical_synth.rpt
|
||||
report_utilization -file top_utilization_synth.rpt
|
||||
|
||||
write_edif -force ../$env(PROJECT_NAME).edif
|
||||
Loading…
Reference in New Issue