![]() |
JACK WHITHAM | ||
![]() |
![]() |
||
![]() |
Home -> vlabifhw |
| |||||||||||
|
The virtual lab interface hardware (vlabifhw) provides this concentrator service, allowing software to communicate with multiple devices inside an FPGA. The software component, vlabif, has its own documentation. You can get vlabifhw and vlabif as a zip archive from the download page.
vlabifhw is completely independent of VL2. The hardware component
(vlabifhw) can be connected to a VL2 board server, or any computer with
an RS232 port. The software component (vlabif)
can use
the vlab module to communicate via a VL2
board server, or the pyserial
module to communicate via a local serial port.
Usage
vlabifhw supports up to 14 user-defined bi-directional channels
for 8 bit data:
Typical usage | ||
---|---|---|
A bi-directional channel represented in hardware | The same channel represented in software | |
Example 1 | Example 2 | |
in_channel_data : in std_logic_vector(7 downto 0); in_channel_wr : in std_logic_vector(0 downto 0); in_channel_rdy : out std_logic_vector(0 downto 0); out_channel_data : out std_logic_vector(7 downto 0); out_channel_wr : out std_logic_vector(0 downto 0); out_channel_rdy : in std_logic_vector(0 downto 0); |
1 auth = vlab.loadAuthorisation("vluser.key") 2 vlf = vlab.VlabClientFactory(auth) 3 reactor.connectTCP(auth.relay_server_name, 22, vlf) 4 yield vlf.getChannel() 5 6 ip = vlabif.VlabInterfaceProtocol() 7 yield vl.openUART(0, ip) 8 yield ip.start() 9 10 # create channel interface: 11 chan = vlabif.SimpleDriver() 12 # (or other twisted.internet.protocol.Protocol) 13 ip.openChannel(1, chan) 14 15 chan.write("send bytes") 16 reply = yield chan.wait(5) |
1 ip = vlabif.VlabInterfaceProtocol() 2 3 serialport.SerialPort(ip, "/dev/ttyS0", 4 reactor=reactor, baudrate=115200) 5 yield ip.start() 6 7 # create channel interface: 8 chan = vlabif.SimpleDriver() 9 # (or other twisted.internet.protocol.Protocol) 10 ip.openChannel(1, chan) 11 12 chan.write("send bytes") 13 reply = yield chan.wait(5) |
VHDL interface of vlabifhw | Python interface of vlabif using a VL2 connection with authorisation file vluser.key | Python interface of vlabif using local serial port /dev/ttyS0. |
In this usage pattern, "do_something_with" will be activated on every clock cycle where a new byte is available. If the program shown above is being executed, it will be activated ten times for each byte in the string "send bytes".process ( clk ) is begin if ( clk'event ) and ( clk = '1' ) then if ( out_channel_wr = '1' ) and ( ready = '1' ) then do_something_with ( out_channel_data ) ; end if ; end if ; end process ; out_channel_rdy <= ready ;
"in_channel" has the same interface. "in_channel_wr" may be asserted when "in_channel_rdy" is high; if this is done, then the byte on "in_channel_data" is accepted as input. A typical usage pattern would be:
process ( clk ) is begin if ( clk'event ) and ( clk = '1' ) then in_channel_wr <= '0' ; if ( in_channel_rdy = '1' ) then in_channel_data <= produce_byte () ; in_channel_wr <= '1' ; end if ; end if ; end process ;
Note: If you are using a Xilinx FPGA, you can remove fifo.vhd and replace it with fifo_xilinx.vhd. If you do this, you should also add fifo_kc.vhd and bbfifo_16x8.vhd to the project. bbfifo_16x8 is a Xilinx-optimised FIFO implementation by Ken Chapman, originally distributed with the Picoblaze CPU. The file is also available from here. It is not distributed with vlabifhw for licensing reasons.After adding the vlabifhw files, add the vlabifhw component to one of your own VHDL files. You must connect the following inputs and outputs:
X is calculated as ( 8 * ext_channels ) - 1, Y is calculated as ext_channels - 1. In this way, the size of these vectors is set to match ext_channels. Let Z be a channel number from 1 to ext_channels. Here is how the bits of in/out_channel are related to channel numbers:in_channel_data : in std_logic_vector(X downto 0); in_channel_wr : in std_logic_vector(Y downto 0); in_channel_rdy : out std_logic_vector(Y downto 0); out_channel_data : out std_logic_vector(X downto 0); out_channel_wr : out std_logic_vector(Y downto 0); out_channel_rdy : in std_logic_vector(Y downto 0);
channel number | Z |
---|---|
_data vector | ( ( Z * 8 ) - 1 downto ( Z * 8 ) - 8 |
_wr vector | ( Z - 1 ) |
_rdy vector | ( Z - 1 ) |
software: openChannel() parameter | Z |
These are documented elsewhere.debug_clock : out std_logic; debug_reset : out std_logic; breakpoint : in std_logic; dc_control : out DC_Control_Wires; dc_out : out std_logic; dc_in : in std_logic
There are three other connections that you should be aware of, even if you do not use them:
vlhw : entity vlabifhw generic map ( ext_channels => 1 , fifo_depth => 1, clock_freq => clock_freq ) port map ( -- External hardware connections clk => clk, reset => '0', hw_tx => hw_tx, hw_rx => hw_rx, -- Internal connections: these are not used in this example. out_channel_data => open, out_channel_wr => open, out_channel_rdy => "1", in_channel_data => x"00", in_channel_wr => "0", in_channel_rdy => open, -- Activation signal: not used active => open, -- Controls for device under test: also not used debug_clock => open, debug_reset => open, breakpoint => '0', dc_control => open, dc_out => open, dc_in => '0' );
start() sends an activation escape code that turns the vlabifhw features
on; this activation code must begin within the first 7 bytes that are
sent, or it will be ignored and relayed normally. This activation
code is documented in the vlabif protocol
documentation.
Alternate Interface: Multiple Clock Domains
The vlabifhw component expects all of its channels to use the same
clock input: the "clk" input given to vlabifhw. In some applications,
this may not be possible. In these cases, the "vlabifhw_cn" component
should be used instead, as it allows each channel to have its own
clock. This is done by adding an extra layer of registers to
the vlabifhw component, using a handshake protocol to move data
between clock domains.
Copyright (C) Jack Whitham 1997-2011