Introduction
This article is the Basics Part 2 of the "Getting Started with Transceivers Agilex™ 5 / Agilex™ 3 Edition" series. It covers running logic simulation based on the design and testbench created in Basics Part 1. The logic simulator used is Questa.
The block diagram of the testbench used is shown below.
If you want to start from this article without creating the design in Basics Part 1, please use the files attached at the end of Basics Part 1. Also, the testbench created in this article and the simulation results (wlf) are attached at the end of this article for your reference.
1. Preparing the Testbench
1-1. Testbench to Use
The testbench generated in Basics Part 1 is located as shown below. In this article, we will modify and use this testbench.
1-2. Overview of the Modified Testbench
The main changes to the original testbench are the following five points:
(1) Comment out the generated clock and reset signals (to rename them)
(2) Add declarations for the signals to be used
(3) Add the clock frequency for the BFM (Bus Functional Model)
(4) Connect each port
(5) Add user-side operations and others
1-3. Adding Signal Declarations to Use
Declare the signals used in this testbench. Please add them as shown below. The clock and reset signals can remain as is, but for clarity, we will rename them this time. Therefore, the original clock and reset signal names are commented out.
The signals added above are as follows:
wire clk_100m_clk;
wire clk_156m_clk;
wire reset_reset;
wire ninit_done;
wire xcvr_tx_ready;
wire xcvr_rx_ready;
wire o_tx_serial_data;
wire o_tx_serial_data_n;
wire i_rx_serial_data;
wire i_rx_serial_data_n;
wire[79:0] i_tx_parallel_data;
wire[79:0] o_rx_parallel_data;
wire rx_clkout_clk;
wire tx_clkout_clk;
reg [1:0] s_xcvr_tx_ready_2r;
reg [9:0] s_cnt_10b;
wire rcvd_data_valid;
wire[31:0] rcvd_data_32b_hi;
wire[31:0] rcvd_data_32b_lo;
1-4. Add Clock Frequency to BFM and Rename Signals
Add the output frequency to the BFM of the generated clock. Please add the CLOCK_RATE parameter as shown below. Also, rename the clock and reset signals.
The text after adding the above is as follows:
xcvr_sample_inst_clk_100m_bfm_ip #(.CLOCK_RATE(100000000)) xcvr_sample_inst_clk_100m_bfm (
.clk (clk_100m_clk) // output, width = 1, clk.clk
);
xcvr_sample_inst_clk_156m_bfm_ip #(.CLOCK_RATE(156250000)) xcvr_sample_inst_clk_156m_bfm (
.clk (clk_156m_clk) // output, width = 1, clk.clk
);
xcvr_sample_inst_reset_bfm_ip xcvr_sample_inst_reset_bfm (
.reset (reset_reset), // output, width = 1, reset.reset
.clk (clk_100m_clk) // input, width = 1, clk.clk
);
1-5. Connect Each Port of xcvr_sample
Connect the ports of xcvr_sample. Please write as shown below.
The text to add is as follows:
xcvr_sample xcvr_sample_inst (
.clk_100m_clk (clk_100m_clk),
.clk_156m_clk (clk_156m_clk),
.phy_i_tx_reset_tx_reset (ninit_done),
.phy_i_rx_reset_rx_reset (ninit_done),
.phy_o_tx_reset_ack_tx_reset_ack (),
.phy_o_rx_reset_ack_rx_reset_ack (),
.phy_o_tx_ready_tx_ready (xcvr_tx_ready),
.phy_o_rx_ready_rx_ready (xcvr_rx_ready),
.phy_o_tx_serial_data_o_tx_serial_data (o_tx_serial_data),
.phy_o_tx_serial_data_n_o_tx_serial_data_n (o_tx_serial_data_n),
.phy_i_rx_serial_data_i_rx_serial_data (i_rx_serial_data),
.phy_i_rx_serial_data_n_i_rx_serial_data_n (i_rx_serial_data_n),
.phy_o_tx_pll_locked_o_tx_pll_locked (),
.phy_o_rx_is_lockedtodata_o_rx_is_lockedtodata (),
.phy_o_rx_is_lockedtoref_o_rx_is_lockedtoref (),
.phy_i_tx_parallel_data_i_tx_parallel_data (i_tx_parallel_data),
.phy_o_rx_parallel_data_o_rx_parallel_data (o_rx_parallel_data),
.reset_reset (reset_reset),
.reset_release_ninit_done_ninit_done (ninit_done),
.rx_clkout_clk (rx_clkout_clk),
.tx_clkout_clk (tx_clkout_clk)
);
1-6. Add User-Side Operations and Others
First, to loop back the serial signals, connect tx_serial_data and rx_serial_data.
Next, describe the transmit data. We will connect 10-bit counters in parallel. This time, the valid data width of the parallel data (PMA width) is 32 bits, and Enable Double Width Transfer is enabled, so the total data width input from the user side is 64 bits. The input pattern will be six 10-bit counters and one 4-bit counter at the most significant position.
Finally, describe the receive data. To keep the description minimal this time, we will check it without alignment. Therefore, the bit positions will be shifted compared to the transmit data.
Each 32-bit portion is connected as below. (For details on bit arrangement, please refer to the GTS Transceiver User Guide.)
The text to add is as follows:
///////////////////////////////////////////////////////////////////
//// loopback ////
assign i_rx_serial_data = o_tx_serial_data;
assign i_rx_serial_data_n = o_tx_serial_data_n;
///////////////////////////////////////////////////////////////////
//// tx parallel data ////
always@(posedge tx_clkout_clk or posedge reset_reset) begin
if (reset_reset)
s_xcvr_tx_ready_2r <= 2'h0 ;
else
s_xcvr_tx_ready_2r <= {s_xcvr_tx_ready_2r[0], xcvr_tx_ready} ;
end
assign s_xcvr_tx_ready = s_xcvr_tx_ready_2r[1];
always@(posedge tx_clkout_clk or negedge s_xcvr_tx_ready) begin
if (~s_xcvr_tx_ready)
s_cnt_10b <= 10'h000 ;
else
s_cnt_10b <= s_cnt_10b + 10'h001 ;
end
//// assign tx parallel data ////
assign i_tx_parallel_data[79:72] = 8'h80;
assign i_tx_parallel_data[71:40] = {s_cnt_10b[3:0], s_cnt_10b, s_cnt_10b, s_cnt_10b[9:2]};
assign i_tx_parallel_data[39:32] = 8'h40;
assign i_tx_parallel_data[31: 0] = {s_cnt_10b[1:0], s_cnt_10b, s_cnt_10b, s_cnt_10b};
///////////////////////////////////////////////////////////////////
//// rx parallel data ////
assign rcvd_data_valid = o_rx_parallel_data[38];
assign rcvd_data_32b_hi = o_rx_parallel_data[71:40];
assign rcvd_data_32b_lo = o_rx_parallel_data[31:0];
2. Running the Simulation
Run the logic simulation using the testbench prepared in Chapter 1. This time, we will introduce the procedure using Questa.
2-1. Change Directory
After launching Questa, perform Change Directory. Execute via File → Change Directory. Please navigate to the following mentor folder:
(Project Folder)\xcvr_sample_tb\xcvr_sample_tb\sim\mentor
2-2. Run the Simulation
After changing folders, enter the following in the transcript window:
do msim_setup.tcl
ld
Tip: Command input supports tab completion.
Tip: You can also enter ld_debug instead of ld.
This will display the following screen (it may take some time to appear):
Before running the simulation, add signals to check in the wave window. This time, we will display all signals of the testbench (xcvr_sample_tb). Right-click on xcvr_sample_tb and select Add Wave. You can also drag and drop to add to the Wave window.
In the transcript window, enter run 50 us. The simulation will run for 50 microseconds, and waveforms like the following will be displayed.
Tip: Wave window display settings can be configured in Windows Preference (Tools - Windows Preference). You can set the number of signal hierarchy levels shown, the time units displayed, and more as shown below.
Check rcvd_data_32b_hi and rcvd_data_32b_lo as received data. These signals extract the valid data portion from rx_parallel_data. Since alignment is not performed, bit positions may be shifted, but here you should be able to confirm the 10-bit and 4-bit counters.
Tip: The transmit data is 64 bits, consisting of six 10-bit counters and one 4-bit counter. This is embedded into the 80-bit tx_parallel_data for transmission. On the other hand, the received data extracts 64 bits from the 80-bit rx_parallel_data (rcvd_data_32b_hi, rcvd_data_32b_lo). Since alignment is not performed this time, bit 0 of the 64-bit data is shifted. Below is an example of received data.
Conclusion
This concludes this article. Please continue with the following real hardware operation verification.
Getting Started with Transceivers Agilex™ 5 / Agilex™ 3 Edition
Recommended Article: Altera FPGA Development Flow
Attachments
Sample testbench and simulation result (wlf) files created in this article.