Removed the need for physical pin loopback. The design now transmitts and receives using the same pins.

Signed-off-by: Maciej Kurc <mkurc@antmicro.com>
This commit is contained in:
Maciej Kurc 2019-09-12 15:03:56 +02:00
parent e722712661
commit 2b3ca04914
9 changed files with 171 additions and 379 deletions

View File

@ -24,15 +24,15 @@ ifeq ($(SYNTH), yosys)
$(YOSYS) -p "read_verilog $< ; synth_xilinx -flatten -nosrl; write_edif -pvector bra -attrprop $@" -l $@.log
else ifeq ($(SYNTH), vivado)
%.edif: %.v
%.edif: %.v tcl/syn.tcl
mkdir -p build-syn.$(basename $@)
cd build-syn.$(basename $@) && env PROJECT_NAME=$(basename $@) $(XRAY_VIVADO) -mode batch -source ../syn.tcl -nojournal -log ../$@.log
cd build-syn.$(basename $@) && env PROJECT_NAME=$(basename $@) $(XRAY_VIVADO) -mode batch -source ../tcl/syn.tcl -nojournal -log ../$@.log
rm -rf *.backup.log
endif
%.bit: %.edif par.tcl
%.bit: %.edif tcl/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
cd build-par.$(basename $@) && env PROJECT_NAME=$(basename $@) $(XRAY_VIVADO) -mode batch -source ../tcl/par.tcl -nojournal -log ../$@.log
rm -rf *.backup.log

View File

@ -1,35 +1,19 @@
# ISERDES minitest for SDR and DDR
## Description
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 design serializes data using logic for all tested ISERDES modes. The data is presented onto selected pins. The same pins are used to receive the data which is then fed to ISERDES cells. No physical loopback is required. The clock is routed internally.
The received data is compared against transmitted internally. Errors are
indicated using LEDs. The comparator module automatically invokes the bitslip
feature of ISERDES (by brutaly testing all possible combinations).
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:
@ -47,7 +31,9 @@ there is correct reception:
The switch SW0 is used as reset.
## Building
To build the project run the following command and the bit file will be generated.
```
make basys3_top.bit
make basys3_iserdes_sdr_ddr.bit
```

View File

@ -39,32 +39,21 @@ 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]
# JA (X1Y1)
set_property PACKAGE_PIN J1 [get_ports io[0]]
set_property PACKAGE_PIN L2 [get_ports io[1]]
set_property PACKAGE_PIN J2 [get_ports io[2]]
set_property PACKAGE_PIN G2 [get_ports io[3]]
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]
# JB (X0Y2)
set_property PACKAGE_PIN A14 [get_ports io[4]]
set_property PACKAGE_PIN A16 [get_ports io[5]]
set_property PACKAGE_PIN B15 [get_ports io[6]]
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]
# JC (X0Y0)
set_property PACKAGE_PIN K17 [get_ports io[7]]
set_property PACKAGE_PIN M18 [get_ports io[8]]
set_property PACKAGE_PIN N17 [get_ports io[9]]
foreach port [get_ports] {
set_property IOSTANDARD LVCMOS33 $port

View File

@ -0,0 +1,89 @@
`include "src/rom.v"
`include "src/serializer.v"
`include "src/transmitter.v"
`include "src/receiver.v"
`include "src/comparator.v"
`include "src/iserdes_sdr_ddr_test.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,
inout wire [9:0] io
);
// ============================================================================
// Clock & reset
reg [3:0] rst_sr;
initial rst_sr <= 4'hF;
always @(posedge clk)
if (sw[0])
rst_sr <= 4'hF;
else
rst_sr <= rst_sr >> 1;
wire CLK = clk;
wire RST = rst_sr[0];
// ============================================================================
// Test uints
wire [9:0] error;
genvar i;
generate for (i=0; i<10; i=i+1) begin
localparam DATA_WIDTH = (i == 0) ? 2 :
(i == 1) ? 3 :
(i == 2) ? 4 :
(i == 3) ? 5 :
(i == 4) ? 6 :
(i == 5) ? 7 :
(i == 6) ? 8 :
(i == 7) ? 4 :
(i == 8) ? 6 :
/*(i == 9) ?*/ 8;
localparam DATA_RATE = (i < 7) ? "SDR" : "DDR";
iserdes_sdr_ddr_test #
(
.DATA_WIDTH (DATA_WIDTH),
.DATA_RATE (DATA_RATE)
)
iserdes_test
(
.CLK (CLK),
.RST (RST),
.IO_DAT (io[i]),
.O_ERROR (error[i])
);
end endgenerate
// ============================================================================
// I/O connections
reg [23:0] heartbeat_cnt;
always @(posedge CLK)
heartbeat_cnt <= heartbeat_cnt + 1;
assign led[9: 0] = (RST) ? 9'd0 : ~error;
assign led[ 10] = heartbeat_cnt[22];
assign led[15:11] = 0;
endmodule

View File

@ -1,266 +0,0 @@
`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

View File

@ -1,36 +0,0 @@
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

View File

@ -2,32 +2,48 @@
// ============================================================================
module trx_path #
module iserdes_sdr_ddr_test #
(
parameter WIDTH = 8,
parameter MODE = "SDR"
parameter DATA_WIDTH = 8,
parameter DATA_RATE = "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,
// Data pin
inout wire IO_DAT,
// Error indicator
output wire ERROR
output wire O_ERROR
);
// ============================================================================
// IOB
wire iob_o;
wire iob_i;
OBUFT obuf
(
.I (iob_o),
.T (1'b0),
.O (IO_DAT)
);
IBUF ibuf
(
.I (IO_DAT),
.O (iob_i)
);
// ============================================================================
wire tx_stb;
wire [WIDTH-1:0] tx_dat;
wire [DATA_WIDTH-1:0] tx_dat;
wire rx_stb;
wire [WIDTH-1:0] rx_dat;
wire [DATA_WIDTH-1:0] rx_dat;
wire rx_bitslip;
wire s_clk;
@ -35,8 +51,8 @@ wire s_clk;
// Transmitter
transmitter #
(
.WIDTH (WIDTH),
.MODE (MODE)
.WIDTH (DATA_WIDTH),
.MODE (DATA_RATE)
)
transmitter
(
@ -47,16 +63,14 @@ transmitter
.O_DAT (tx_dat),
.S_CLK (s_clk),
.S_DAT (O_DAT)
.S_DAT (iob_o)
);
assign O_CLK = s_clk;
// Receiver
receiver #
(
.WIDTH (WIDTH),
.MODE (MODE)
.WIDTH (DATA_WIDTH),
.MODE (DATA_RATE)
)
receiver
(
@ -64,7 +78,7 @@ receiver
.RST (RST),
.I_CLK (s_clk),
.I_DAT (I_DAT),
.I_DAT (iob_i),
.O_STB (rx_stb),
.O_DAT (rx_dat),
@ -72,7 +86,7 @@ receiver
);
// The comparator module generates bitslip signal for the receiver. However
// the bitslip can shift only modulo WIDTH. Therefore additional delay is
// the bitslip can shift only modulo DATA_WIDTH. Therefore additional delay is
// added which can delay the transmitted data that we compare to by a number
// of full words.
@ -82,24 +96,24 @@ always @(posedge CLK)
if (RST)
rx_bitslip_cnt <= 0;
else if (rx_bitslip) begin
if (rx_bitslip_cnt == (2*WIDTH - 1))
if (rx_bitslip_cnt == (2*DATA_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;
reg [1:0] tx_dly_cnt;
reg [DATA_WIDTH-1:0] tx_dat_dly_a;
reg [DATA_WIDTH-1:0] tx_dat_dly_b;
reg [DATA_WIDTH-1:0] tx_dat_dly_c;
reg [DATA_WIDTH-1:0] tx_dat_dly_d;
wire [DATA_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))
else if(rx_bitslip && rx_bitslip_cnt == (2*DATA_WIDTH - 1))
tx_dly_cnt <= tx_dly_cnt + 1;
always @(posedge CLK)
@ -118,7 +132,7 @@ assign tx_dat_dly = (tx_dly_cnt == 0) ? tx_dat_dly_a :
// Comparator
comparator #
(
.WIDTH (WIDTH)
.WIDTH (DATA_WIDTH)
)
comparator
(
@ -132,7 +146,7 @@ comparator
.RX_DAT (rx_dat),
.RX_BITSLIP (rx_bitslip),
.O_ERROR (ERROR)
.O_ERROR (O_ERROR)
);
endmodule

View File

@ -0,0 +1,16 @@
create_project -force -name $env(PROJECT_NAME) -part xc7a35tcpg236-1
read_edif ../$env(PROJECT_NAME).edif
link_design -part xc7a35tcpg236-1
source ../basys3.xdc
set_property SEVERITY {Warning} [get_drc_checks UCIO-1]
set_property SEVERITY {Warning} [get_drc_checks NSTD-1]
place_design
route_design
write_checkpoint -force ../$env(PROJECT_NAME).dcp
write_bitstream -force ../$env(PROJECT_NAME).bit