Testbench description¶
Overview¶
The following figure depicts the Testbench:
Types¶
t_reg¶
A record type used to define register configurations for the testbench.
| Property | Description |
|---|---|
| Type Name | t_reg |
| Purpose | Register fields with address and default value |
| Fields | - name : string - Register name identifier- addr : std_logic_vector(7 downto 0) - 8-bit register address- data : std_logic_vector(15 downto 0) - 16-bit reset value |
Constants¶
General constants¶
The following constants are defined:
| Name | Type | Value | Description |
|---|---|---|---|
C_FREQ_HZ |
positive | 0d100_000_000 | Clock frequency |
C_CLK_PERIOD |
time | 1 sec / C_FREQ_HZ |
Clock period |
C_GIT_ID |
vector[31: 0] | 0x12345678 | Git identifier for DUT version tracking |
C_UART_BAUD_RATE_BPS |
positive | 0d115_200 | UART baud rate in bits per second |
C_UART_BIT_TIME |
time | 1 sec / C_UART_BAUD_RATE_BPS |
Time duration for one UART bit |
C_UART_BIT_TIME_ACCURACY |
time | 0. 01 * C_UART_BIT_TIME |
UART bit timing tolerance (1%) |
C_UART_WRITE_NB_BITS |
positive | 10 * 8 | Total bits for UART write command |
C_UART_WRITE_CMD_TIME |
time | C_UART_BIT_TIME * C_UART_WRITE_NB_BITS |
Total time for UART write command |
C_READ_NB_BITS |
positive | 10 * 9 | Total bits for UART read command |
C_UART_READ_CMD_TIME |
time | C_UART_BIT_TIME * C_UART_READ_NB_BITS |
Total time for UART read command |
C_SPI_FREQ_HZ |
positive | 0d1_000_000 | SPI SLCK frequency |
C_SPI_BIT_TIME |
time | 1 sec / C_SPI_FREQ_HZ |
SPI baud rate in bits per second |
C_SPI_BIT_TIME_ACCURACY |
time | 0.01 * C_SPI_BIT_TIME |
SPI bit timing tolerance (1%) |
C_SPI_NB_DATA_BIS |
positive | 8 | Total bits in SPI transaction |
C_SPI_TRANSACTION_TIME |
time | (C_SPI_NB_DATA_BIS + 2) * C_SPI_BIT_TIME |
SPI transaction time |
C_H_VGA_PIXEL_FREQUENCY |
integer | 0d65_000_000 | VGA pixel clock frequency |
C_H_VGA_PIXEL_BIT_TIME |
time | 1 sec / C_H_VGA_PIXEL_FREQUENCY |
VGA pixel clock period |
C_H_PIXELS |
integer | 0d1024 | VGA active display width (pixels) |
C_H_FRONT_PORCH |
integer | 0d24 | VGA horizontal front porch (pixels) |
C_H_SYNC_PULSE |
integer | 0d136 | VGA horizontal sync pulse width (pixels) |
C_H_BACK_PORCH |
integer | 0d160 | VGA horizontal back porch (pixels) |
C_H_HSYNC_HIGH |
integer | C_H_PIXELS + C_H_FRONT_PORCH + C_H_BACK_PORCH |
VGA horizontal sync high period (pixels) |
C_H_WHOLE_LINE |
integer | C_H_SYNC_PULSE + C_H_HSYNC_HIGH |
VGA total horizontal line (pixels) |
C_H_SYNC_PULSE_TIME |
time | C_H_SYNC_PULSE * C_H_VGA_PIXEL_BIT_TIME |
VGA horizontal sync pulse duration |
C_H_SYNC_PULSE_TIME_ACCURACY |
time | 0.01 * C_H_SYNC_PULSE * C_H_VGA_PIXEL_BIT_TIME |
VGA horizontal sync pulse tolerance |
C_H_HSYNC_HIGH_TIME |
time | C_H_HSYNC_HIGH * C_H_VGA_PIXEL_BIT_TIME |
VGA horizontal sync high duration |
C_H_HSYNC_HIGH_TIME_ACCURACY |
time | 0.01 * C_H_HSYNC_HIGH * C_H_VGA_PIXEL_BIT_TIME |
VGA horizontal sync high tolerance |
C_H_WHOLE_LINE_TIME |
time | C_H_SYNC_PULSE_TIME + C_H_HSYNC_HIGH_TIME |
VGA total horizontal line duration |
C_H_WHOLE_LINE_TIME_ACCURACY |
time | C_H_SYNC_PULSE_TIME_ACCURACY + C_H_HSYNC_HIGH_TIME_ACCURACY |
VGA total horizontal line tolerance |
C_V_VGA_PIXEL_FREQUENCY |
integer | C_H_VGA_PIXEL_FREQUENCY / C_H_WHOLE_LINE |
VGA line frequency (Hz) |
C_V_VGA_PIXEL_BIT_TIME |
time | 1 sec / C_V_VGA_PIXEL_FREQUENCY |
VGA line period |
C_V_PIXELS |
integer | 0d768 | VGA active display height (lines) |
C_V_FRONT_PORCH |
integer | 0d3 | VGA vertical front porch (lines) |
C_V_SYNC_PULSE |
integer | 0d6 | VGA vertical sync pulse width (lines) |
C_V_BACK_PORCH |
integer | 0d29 | VGA vertical back porch (lines) |
C_V_HSYNC_HIGH |
integer | C_V_PIXELS + C_V_FRONT_PORCH + C_V_BACK_PORCH |
VGA vertical sync high period (lines) |
C_V_WHOLE_LINE |
integer | C_V_SYNC_PULSE + C_V_HSYNC_HIGH |
VGA total vertical frame (lines) |
C_V_SYNC_PULSE_TIME |
time | C_V_SYNC_PULSE * C_V_VGA_PIXEL_BIT_TIME |
VGA vertical sync pulse duration |
C_V_SYNC_PULSE_TIME_ACCURACY |
time | 0.01 * C_V_SYNC_PULSE * C_V_VGA_PIXEL_BIT_TIME |
VGA vertical sync pulse tolerance |
C_V_HSYNC_HIGH_TIME |
time | C_V_HSYNC_HIGH * C_V_VGA_PIXEL_BIT_TIME |
VGA vertical sync high duration |
C_V_HSYNC_HIGH_TIME_ACCURACY |
time | 0.01 * C_V_HSYNC_HIGH * C_V_VGA_PIXEL_BIT_TIME |
VGA vertical sync high tolerance |
C_V_WHOLE_LINE_TIME |
time | C_V_SYNC_PULSE_TIME + C_V_HSYNC_HIGH_TIME |
VGA total vertical frame duration |
C_V_WHOLE_LINE_TIME_ACCURACY |
time | C_V_SYNC_PULSE_TIME_ACCURACY + C_V_HSYNC_HIGH_TIME_ACCURACY |
VGA total vertical frame tolerance |
Registers¶
The following registers are defined as t_reg:
| Name | Address | Reset Value |
|---|---|---|
C_REG_GIT_ID_MSB |
0x00 | 0x1234 |
C_REG_GIT_ID_LSB |
0x01 | 0x5678 |
C_REG_12 |
0x02 | 0x1212 |
C_REG_34 |
0x03 | 0x3434 |
C_REG_56 |
0x04 | 0x5656 |
C_REG_78 |
0x05 | 0x7878 |
C_REG_SPI_TX |
0x06 | 0x0000 |
C_REG_SPI_RX |
0x07 | 0x0000 |
C_REG_SPI_RX |
0x07 | 0x0000 |
C_REG_VGA_CTRL |
0x08 | 0x00F0 |
C_REG_9A |
0xAB | 0x9A9A |
C_REG_CD |
0xAC | 0xCDCD |
C_REG_EF |
0xDC | 0xEFEF |
C_REG_SWITCHES |
0xB1 | 0x0000 |
C_REG_LED |
0xEF | 0x0001 |
C_REG_16_BITS |
0xFF | 0x0000 |
C_REG_DEAD |
0xCC | 0xDEAD |
Processes¶
Process p_check_uart_timings¶
Description¶
Verifies UART TX timings by transmitting test data 0x5555 and measuring bit durations.
Data Conversion:
- Test data
0x5555contains four'5'characters - Each
'5'is converted to ASCII →0x35(binary:00110101)
UART Frame Structure:
Each character is transmitted as a 10-bit frame:
[Start] [Bit0 Bit1 Bit2 Bit3 Bit4 Bit5 Bit6 Bit7] [Stop]
0 1 0 1 0 1 1 0 0 1
└─────────── LSB to MSB ───────────┘
The diagram below shows the waveform and which falling/rising edges are awaited:
In total, it is repeated four times.
Parameters¶
The process defines two variables:
| Parameter | Type | Default | Description |
|---|---|---|---|
v_start_time |
time |
- | The start time of the measurement |
v_start_bit_time |
time |
- | The start time of the measurement of a bit state |
Steps¶
-
Wait for the start of UART timings check
- Wait for a rising edge on signal
tb_check_uart_timings - Log info message: "Checking UART timings on TX with value 0x5555"
- Wait for a rising edge on signal
-
For each byte (1 to 4)
- Wait for start bit
- Wait for falling edge on
tb_pad_o_uart_tx(a) - Set
v_start_bit_timeto current time - If first byte, set
v_start_timeto current time
- Wait for falling edge on
- Wait for a rising edge on signal
tb_pad_o_uart_tx(b) - Check that
(now - v_start_bit_time)is in time rangeC_UART_BIT_TIME±C_UART_BIT_TIME_ACCURACYwith procedureproc_check_time_in_range - Set
v_start_bit_timeto current time - Wait for a falling edge on signal
tb_pad_o_uart_tx(c) - Check that
(now - v_start_bit_time)is in time rangeC_UART_BIT_TIME±C_UART_BIT_TIME_ACCURACYwith procedureproc_check_time_in_range - Set
v_start_bit_timeto current time - Wait for a rising edge on signal
tb_pad_o_uart_tx(d) - Check that
(now - v_start_bit_time)is in time rangeC_UART_BIT_TIME±C_UART_BIT_TIME_ACCURACYwith procedureproc_check_time_in_range - Set
v_start_bit_timeto current time - Wait for a falling edge on signal
tb_pad_o_uart_tx(e) - Check that
(now - v_start_bit_time)is in time rangeC_UART_BIT_TIME±C_UART_BIT_TIME_ACCURACYwith procedureproc_check_time_in_range - Set
v_start_bit_timeto current time - Wait for a rising edge on signal
tb_pad_o_uart_tx(f) - Check that
(now - v_start_bit_time)is in time rangeC_UART_BIT_TIME±C_UART_BIT_TIME_ACCURACYwith procedureproc_check_time_in_range - Set
v_start_bit_timeto current time - Wait for a falling edge on signal
tb_pad_o_uart_tx(g) - Check that
(now - v_start_bit_time)is in time range2. 0 * C_UART_BIT_TIME±2.0 * C_UART_BIT_TIME_ACCURACYwith procedureproc_check_time_in_range - Set
v_start_bit_timeto current time - Wait for a rising edge on signal
tb_pad_o_uart_tx(h) - Check that
(now - v_start_bit_time)is in time range2.0 * C_UART_BIT_TIME±2.0 * C_UART_BIT_TIME_ACCURACYwith procedureproc_check_time_in_range - Set
v_start_bit_timeto current time
- Wait for start bit
-
Verify total elapsed time
- Check that
(now - v_start_time)is in time range 9 * 4C_UART_BIT_TIME±C_UART_BIT_TIME_ACCURACYwith procedureproc_check_time_in_range
- Check that
Process p_check_spi_timings¶
Description¶
Verifies SPI clock timings.
Currently only verifies SPI clock timings.
The diagram below shows the waveform and which rising edges are awaited:
Parameters¶
The process defines two variables:
| Parameter | Type | Default | Description |
|---|---|---|---|
v_start_time |
time |
- | The start time of the measurement |
v_start_bit_time |
time |
- | The start time of the measurement of a bit state |
Steps¶
-
Wait for the start of SPI timings check
- Wait for a rising edge on signal
tb_check_spi_timings
- Wait for a rising edge on signal
-
For each bit (1 to 8)
- Wait for a rising edge on signal
tb_pad_o_sclk(a to h) - If first bit (
bits = 1):- Set
v_start_timeto current time - Set
v_start_bit_timeto current time
- Set
- Else:
- Check that
(now - v_start_bit_time)is in time rangeC_SPI_BIT_TIME±C_SPI_BIT_TIME_ACCURACYwith procedureproc_check_time_in_range - Set
v_start_bit_timeto current time
- Check that
- Wait for a rising edge on signal
-
Verify total elapsed time
- Check that
(now - v_start_time)is in time range7 * C_SPI_BIT_TIME±7 * C_SPI_BIT_TIME_ACCURACYwith procedureproc_check_time_in_range
- Check that
Process p_check_hsync_timings¶
Description¶
This process verifies the VGA horizontal synchronization (HSYNC) timing.
Parameters¶
The process defines two variables:
| Parameter | Type | Default | Description |
|---|---|---|---|
v_start_time |
time |
- | The start time of the measurement |
v_start_bit_time |
time |
- | The start time of the measurement of a bit state |
Steps¶
-
Wait for the start of HSYNC timings check
- Wait for a rising edge on signal
tb_check_hsync_timings
- Wait for a rising edge on signal
-
Measure HSYNC pulse width (sync pulse duration)
- Wait for falling edge on
tb_pad_o_vga_hsync(start of sync pulse) - Capture both
v_start_timeandv_start_bit_timeas baseline - Wait for rising edge on
tb_pad_o_vga_hsync(end of sync pulse) - Validate sync pulse duration against
C_H_SYNC_PULSE_TIME±C_H_SYNC_PULSE_TIME_ACCURACY - Update
v_start_bit_timeto current time
- Wait for falling edge on
-
Measure HSYNC high period and total line time
- Wait for next falling edge on
tb_pad_o_vga_hsync(completion of one horizontal line) - Validate high period: Check time since last edge against
C_H_HSYNC_HIGH_TIME±C_H_HSYNC_HIGH_TIME_ACCURACY - Validate complete line time: Check time since initial
v_start_timeagainstC_H_WHOLE_LINE_TIME±C_H_WHOLE_LINE_TIME_ACCURACY
- Wait for next falling edge on
Process p_check_vsync_timings¶
Description¶
This process verifies the VGA vertical synchronization (VSYNC) timing.
Parameters¶
The process defines two variables:
| Parameter | Type | Default | Description |
|---|---|---|---|
v_start_time |
time |
- | The start time of the measurement |
v_start_bit_time |
time |
- | The start time of the measurement of a bit state |
Steps¶
-
Wait for the start of HSYNC timings check
- Wait for a rising edge on signal
tb_check_vsync_timings
- Wait for a rising edge on signal
-
Measure HSYNC pulse width (sync pulse duration)
- Wait for falling edge on
tb_pad_o_vga_vsync(start of sync pulse) - Capture both
v_start_timeandv_start_bit_timeas baseline - Wait for rising edge on
tb_pad_o_vga_vsync(end of sync pulse) - Validate sync pulse duration against
C_V_SYNC_PULSE_TIME±C_V_SYNC_PULSE_TIME_ACCURACY - Update
v_start_bit_timeto current time
- Wait for falling edge on
-
Measure HSYNC high period and total line time
- Wait for next falling edge on
tb_pad_o_vga_vsync - Validate high period: Check time since last edge against
C_V_HSYNC_HIGH_TIME±C_V_HSYNC_HIGH_TIME_ACCURACY - Validate complete frame time: Check time since initial
v_start_timeagainstC_V_WHOLE_LINE_TIME±C_V_WHOLE_LINE_TIME_ACCURACY
- Wait for next falling edge on
Procedures¶
Procedure proc_check_time_in_range¶
Description¶
This procedure performs a range check to verify that time_to_check is within expected_time ± accuracy.
Parameters¶
| Parameter | Type | Default | Description |
|---|---|---|---|
time_to_check |
time |
- | The actual time value to be validated |
expected_time |
time |
- | The target/expected time value |
accuracy |
time |
- | The acceptable deviation (tolerance) from the expected time |
message |
string |
"" |
Optional custom message prefix for the assertion output |
Steps¶
- Perform Range Check
- Check that
abs(time_to_check - expected_time) <= accuracywith procedurecheck
- Check that
Procedure proc_reset_dut¶
Description¶
This procedure puts all the testbench signals into a known state.
Parameters¶
| Parameter | Type | Default | Description |
|---|---|---|---|
c_clock_cycles |
positive |
50 | Number of clock cycles to wait |
Steps¶
-
Reset the DUT by Setting Input State to All Zeros
- Set
tb_pad_i_rst_hto1 - Set
tb_i_uart_selectto0 - Set
tb_i_uart_rx_manualto0 - Set
tb_pad_i_switch_0to0 - Set
tb_pad_i_switch_1to0 - Set
tb_pad_i_switch_2to0 - Set
tb_i_read_addressto0x00 - Set
tb_i_read_address_validto0 - Set
tb_i_write_addressto0x00 - Set
tb_i_write_datato0x0000 - Set
tb_i_write_validto0 - Set
tb_check_uart_timingsto0 - Set
tb_check_spi_timingsto0
- Set
-
Wait for the Specified Number of Clock Cycles
- Wait for
c_clock_cycles * C_CLK_PERIOD
- Wait for
-
De-assert Reset
- Set
tb_pad_i_rst_hto0
- Set
-
Wait for the DUT to Settle
- Wait for 5 ns
Procedure proc_uart_send_byte¶
Description¶
This procedure sends a byte via UART using the manually driven line.
Parameters¶
| Parameter | Type | Default | Description |
|---|---|---|---|
uart_rx |
std_logic |
- | The UART line to drive |
byte_to_send |
vector[7:0] |
- | The byte to send |
Steps¶
-
Ensure the Manual UART is Selected
- If
tb_i_uart_select = 0:- Set
tb_i_uart_selectto1 - Wait for 200 ns
- Set
- If
-
Send the Start Bit
- Set
uart_rxto0 - Wait for
C_UART_BIT_TIME
- Set
-
Send the Data Bits (LSB to MSB)
- For
bit_idxinbyte_to_send'lowtobyte_to_send'high:- Set
uart_rxtobyte_to_send(bit_idx) - Wait for
C_UART_BIT_TIME
- Set
- For
-
Send the Stop Bit
- Set
uart_rxto1 - Wait for 1. 1 ×
C_UART_BIT_TIME
- Set
Procedure proc_uart_write¶
Description¶
This procedure writes a value to a specified UART register.
Parameters¶
| Parameter | Type | Default | Description |
|---|---|---|---|
reg |
t_reg |
- | The register to write to |
value |
vector[15:0] |
- | The value to write to the register |
Steps¶
-
Ensure the Model UART is Selected
- If
tb_i_uart_select = 1:- Set
tb_i_uart_selectto0 - Wait for 200 ns
- Set
- If
-
Set Up the Write Operation
- Set
tb_i_write_addresstoreg.addr - Set
tb_i_write_datatovalue - Set
tb_i_write_validto1
- Set
-
Wait and De-assert the Valid Flag
- Wait for 200 ns
- Set
tb_i_write_validto0
-
Wait for the Write Operation to Complete
- Wait for 1.1 ×
C_UART_WRITE_CMD_TIME
- Wait for 1.1 ×
Procedure proc_uart_read¶
Description¶
This procedure reads a value from a specified UART register.
Parameters¶
| Parameter | Type | Default | Description |
|---|---|---|---|
reg |
t_reg |
- | The register to read from |
Steps¶
-
Ensure the Model UART is Selected
- If
tb_i_uart_select = 1:- Set
tb_i_uart_selectto0 - Wait for 200 ns
- Set
- If
-
Wait Before Starting the Read
- Wait for 500 ns (to avoid simulation stuck)
-
Set Up the Read Operation
- Set
tb_i_read_addresstoreg.addr - Set
tb_i_read_address_validto1
- Set
-
Wait for the Read Operation to Complete
- Wait for a rising edge on signal
tb_o_read_data_valid
- Wait for a rising edge on signal
-
De-assert the Read Valid Signal
- Set
tb_i_read_address_validto0
- Set
Procedure proc_uart_check¶
Description¶
This procedure checks if the read value from a specified UART register matches the expected value.
Parameters¶
| Parameter | Type | Default | Description |
|---|---|---|---|
reg |
t_reg |
- | The register to check |
expected_value |
vector[15:0] |
- | The expected value to compare against |
Steps¶
-
Read the Register Value
- Read the register
regvalue with procedureproc_uart_read
- Read the register
-
Check the Returned Value
- Check that the returned value
tb_o_read_dataequalsexpected_valuewith the procedurecheck_equal
- Check that the returned value
Procedure proc_uart_check_default_value¶
Description¶
This procedure checks if the default value of a specified UART register matches the expected reset value.
Parameters¶
| Parameter | Type | Default | Description |
|---|---|---|---|
reg |
t_reg |
- | The register to check |
Steps¶
- Check the Default Value Against the Register's Reset Value
- Check that the value after reset is equal to the one specified in
reg.datawith the procedureproc_uart_check
- Check that the value after reset is equal to the one specified in
Procedure proc_uart_check_read_only¶
Description¶
This procedure checks if a specified UART register is read-only by attempting to write to it and verifying that the value remains unchanged.
Parameters¶
| Parameter | Type | Default | Description |
|---|---|---|---|
reg |
t_reg |
- | The register to check |
Steps¶
-
Attempt to Write an Incorrect Value to the Register
- Write the data
not(reg.data)to the register addressreg.addrwith procedureproc_uart_write
- Write the data
-
Check if the Register Value Remains Unchanged
- Read back the register and check if the register value remains unchanged with procedure
proc_uart_check
- Read back the register and check if the register value remains unchanged with procedure
Procedure proc_uart_check_read_write¶
Description¶
This procedure checks if a specified UART register is read-write by writing a value to it and verifying that the value is correctly updated.
Parameters¶
| Parameter | Type | Default | Description |
|---|---|---|---|
reg |
t_reg |
- | The register to check |
expected_value |
vector[15:0] |
- | The expected value to compare against after writing |
Steps¶
-
Write the Inverted Default Value to the Register
- Write the data
not(reg.data)to the register addressreg.addrwith procedureproc_uart_write
- Write the data
-
Check if the Register Value is Updated Correctly
- Read back the register and check if the register value is matching
expected_valuewith procedureproc_uart_check
- Read back the register and check if the register value is matching
Procedure proc_spi_write¶
Description¶
Writes a byte value to the SPI master module via UART register interface.
Parameters¶
| Parameter | Type | Default | Description |
|---|---|---|---|
value |
vector[7:0] |
- | 8-bit data to transmit via SPI |
Steps¶
-
Reset C_REG_SPI_TX for Rising Edge Detection
- Write
0x0000to registerC_REG_SPI_TXwith procedureproc_uart_write
- Write
-
Write the Data with Valid Flag Set
- Write
(7b0 & 1b1 & value)to the registerC_REG_SPI_TXwith procedureproc_uart_write
- Write
Procedure proc_spi_check¶
Description¶
Writes a value to SPI master and verifies correct transmission and reception.
Parameters¶
| Parameter | Type | Default | Description |
|---|---|---|---|
value |
vector[7:0] |
- | 8-bit data to transmit and verify |
Steps¶
-
Write Data to SPI
- Start an SPI transaction with procedure
proc_spi_write
- Start an SPI transaction with procedure
-
Retrieve Data from SPI Slave Stream
- Pop data from
C_SLAVE_STREAMintov_spi_slave_data(MOSI path verification)
- Pop data from
-
Verify MOSI Path
- Check that
v_spi_slave_dataequalsvaluewith procedurecheck_equal
- Check that
-
Read and Verify MISO Register Data
- Check that sampled SPI data from slave is matching the one decoded in the
REG_SPI_RXregister with procedureproc_uart_check
- Check that sampled SPI data from slave is matching the one decoded in the