Virtual IO

From Hamsterworks Wiki!

Jump to: navigation, search

This FPGA Project was completed in Jan 2016.

I had the luck to attend an Avnet Speedway Design Workshop "Introduction to Vivado Design Suite". It was a very worthwhile way to spend a day. Here is one really useful thing I picked up.

One of the IP blocks is "Virtual Input/Output", that can help you debug your design.

Contents

Sample design

This minimal design just hooks up the switches and LEDs on the Basys3 board to the VIO Debug IP, allowing me to read the switches and set the LEDs from the Vivado GUI.

The first step is to create a quick project connect the switches to the LEDs:

vio_test.vhd

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity vio_test is
    Port ( switches : in  STD_LOGIC_VECTOR (15 downto 0);
           leds     : out STD_LOGIC_VECTOR (15 downto 0));
end vio_test;

architecture Behavioral of vio_test is
begin

clk_proc: process(clk)
    begin
        if rising_edge(clk) then
            leds <= switches;
        end if;
    end process;

end Behavioral;

basys3.xdc

Sorry for the size of the constraints - it will be worth it!

set_property PACKAGE_PIN W5 [get_ports clk]							
set_property IOSTANDARD LVCMOS33 [get_ports clk]
create_clock -add -name sys_clk_pin -period 10.00 -waveform {0 5} [get_ports clk]

## Switches
set_property PACKAGE_PIN V17      [get_ports {switches[0]}]					
set_property PACKAGE_PIN V16      [get_ports {switches[1]}]					
set_property PACKAGE_PIN W16      [get_ports {switches[2]}]					
set_property PACKAGE_PIN W17      [get_ports {switches[3]}]					
set_property PACKAGE_PIN W15      [get_ports {switches[4]}]					
set_property PACKAGE_PIN V15      [get_ports {switches[5]}]					
set_property PACKAGE_PIN W14      [get_ports {switches[6]}]					
set_property PACKAGE_PIN W13      [get_ports {switches[7]}]					
set_property PACKAGE_PIN V2       [get_ports {switches[8]}]					
set_property PACKAGE_PIN T3       [get_ports {switches[9]}]					
set_property PACKAGE_PIN T2       [get_ports {switches[10]}]					
set_property PACKAGE_PIN R        [get_ports {switches[11]}]					
set_property PACKAGE_PIN W2       [get_ports {switches[12]}]					
set_property PACKAGE_PIN U1       [get_ports {switches[13]}]					
set_property PACKAGE_PIN T1       [get_ports {switches[14]}]					
set_property PACKAGE_PIN R2       [get_ports {switches[15]}]					
set_property IOSTANDARD  LVCMOS33 [get_ports {switches[*]}]
 

## LEDs
set_property PACKAGE_PIN U16     [get_ports {leds[0]}]					
set_property PACKAGE_PIN E19     [get_ports {leds[1]}]					
set_property PACKAGE_PIN U19     [get_ports {leds[2]}]					
set_property PACKAGE_PIN V19     [get_ports {leds[3]}]					
set_property PACKAGE_PIN W18     [get_ports {leds[4]}]					
set_property PACKAGE_PIN U15     [get_ports {leds[5]}]					
set_property PACKAGE_PIN U14     [get_ports {leds[6]}]					
set_property PACKAGE_PIN V14     [get_ports {leds[7]}]					
set_property PACKAGE_PIN V13     [get_ports {leds[8]}]					
set_property PACKAGE_PIN V3      [get_ports {leds[9]}]					
set_property PACKAGE_PIN W3      [get_ports {leds[10]}]					
set_property PACKAGE_PIN U3      [get_ports {leds[11]}]					
set_property PACKAGE_PIN P3      [get_ports {leds[12]}]					
set_property PACKAGE_PIN N3      [get_ports {leds[13]}]					
set_property PACKAGE_PIN P1      [get_ports {leds[14]}]					
set_property PACKAGE_PIN L1      [get_ports {leds[15]}]					
set_property IOSTANDARD LVCMOS33 [get_ports {leds[*]}]

Generating the Virtual Input/Output IP core

First task is to find the IP block in the catalog:

Vio1.png

Double-click, then customize it to have 16-bit input and output ports:

Vio2.png

Vio3.png

Then generate all the outputs. One you have generated the outputs you should be able to find the instantiation template:

Vio4.png

Copy the important bits out of the file, and then integrate them into the above design.

Updated source

I've replaced the process that assigned the switches to the LEDs with the Virtual I/O block:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity vio_test is
    Port ( clk      : in  STD_LOGIC;
           switches : in  STD_LOGIC_VECTOR (15 downto 0);
           leds     : out STD_LOGIC_VECTOR (15 downto 0));
end vio_test;

architecture Behavioral of vio_test is
    COMPONENT vio_0
      PORT (
        clk        : IN STD_LOGIC;
        probe_in0  : IN STD_LOGIC_VECTOR(15 DOWNTO 0);
        probe_out0 : OUT STD_LOGIC_VECTOR(15 DOWNTO 0)
      );
    END COMPONENT;
begin

i_vio : vio_0
  PORT MAP (
    clk        => clk,
    probe_in0  => switches,
    probe_out0 => leds
  );
begin

end Behavioral;

Build the design, generate the bitstream and download it to the board using Vivado's Hardware Manager. You should have a debug probes file, that will be automatically populated in the dialog box:

Vios5.png

You will then be able to add the probes to the workspace:

Vios6.png

You can then expand the probes, and by right-clicking on the signals change them to being 'click to toggle' buttons for the outputs, and LED display indicators.

Vios7.png

If you change the switches on the dev board, the values on the screen will change, and by clicking on the buttons in Vivado you can control the LEDs.

Why is the really cool?

Normally when debugging designs I've been bringing internal signals up to the top level, then connecting them to the LEDs or switches. With this IP blocks, you can just drop them deep into your design, allowing you to inject signals are see the status of signals from deep within your design.

And when you no longer need it, you can just put the "IF 1 = 0 GENERATE" block, to remove it completely from the design!

Personal tools