Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Pseudo UART allowing to connect via pseudoterminal to GHDL simulated IP core

189 views
Skip to first unread message

Wojciech M. Zabolotny

unread,
Jun 2, 2011, 1:30:18 PM6/2/11
to
Below are the sources (in C and VHDL) implementing the pseudo-UART
allowing you to establish communication with your IP core simulated
in GHDL (http://ghdl.free.fr).
The simulated core is accesible via pseudoterminal (e.g. /dev/pts/11)
in Linux or similar system, just as it would be a real hardware
connected to real hardware port.
For details see "desc.txt" in attached archive.
All attached sources are PUBLIC DOMAIN. however I'd be glad if someone
using them provides information about original sources.
I'd be also glad to hear about people using this design and about any
improvements introduced by them.

Wojciech M. Zabolotny
wzab<at>ise.pw.edu.pl

#!/bin/sh
# This is a shell archive (produced by GNU sharutils 4.11).
# To extract the files from this archive, save it to some FILE, remove
# everything before the `#!/bin/sh' line above, then type `sh FILE'.
#
lock_dir=_sh13473
# Made on 2011-06-02 19:20 CEST by <wzab@wzab>.
# Source directory was `/tmp/uart'.
#
# Existing files will *not* be overwritten, unless `-c' is specified.
#
# This shar contains:
# length mode name
# ------ ---------- ------------------------------------------
# 2946 -rw-r--r-- desc.txt
# 1717 -rw-r--r-- ghdl_pty.c
# 2017 -rw-r--r-- ghdl_uart_pkg.vhd
# 3845 -rw-r--r-- ghdl_uart_tb.vhd
# 5231 -rw-r--r-- ghdl_uart.vhd
# 463 -rw-rw-r-- makefile
#
MD5SUM=${MD5SUM-md5sum}
f=`${MD5SUM} --version | egrep '^md5sum .*(core|text)utils'`
test -n "${f}" && md5check=true || md5check=false
${md5check} || \
echo 'Note: not verifying md5sums. Consider installing GNU coreutils.'
if test "X$1" = "X-c"
then keep_file=''
else keep_file=true
fi
echo=echo
save_IFS="${IFS}"
IFS="${IFS}:"
gettext_dir=
locale_dir=
set_echo=false

for dir in $PATH
do
if test -f $dir/gettext \
&& ($dir/gettext --version >/dev/null 2>&1)
then
case `$dir/gettext --version 2>&1 | sed 1q` in
*GNU*) gettext_dir=$dir
set_echo=true
break ;;
esac
fi
done

if ${set_echo}
then
set_echo=false
for dir in $PATH
do
if test -f $dir/shar \
&& ($dir/shar --print-text-domain-dir >/dev/null 2>&1)
then
locale_dir=`$dir/shar --print-text-domain-dir`
set_echo=true
break
fi
done

if ${set_echo}
then
TEXTDOMAINDIR=$locale_dir
export TEXTDOMAINDIR
TEXTDOMAIN=sharutils
export TEXTDOMAIN
echo="$gettext_dir/gettext -s"
fi
fi
IFS="$save_IFS"
if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null
then if (echo -n test; echo 1,2,3) | grep n >/dev/null
then shar_n= shar_c='
'
else shar_n=-n shar_c= ; fi
else shar_n= shar_c='\c' ; fi
f=shar-touch.$$
st1=200112312359.59
st2=123123592001.59
st2tr=123123592001.5 # old SysV 14-char limit
st3=1231235901

if touch -am -t ${st1} ${f} >/dev/null 2>&1 && \
test ! -f ${st1} && test -f ${f}; then
shar_touch='touch -am -t $1$2$3$4$5$6.$7 "$8"'

elif touch -am ${st2} ${f} >/dev/null 2>&1 && \
test ! -f ${st2} && test ! -f ${st2tr} && test -f ${f}; then
shar_touch='touch -am $3$4$5$6$1$2.$7 "$8"'

elif touch -am ${st3} ${f} >/dev/null 2>&1 && \
test ! -f ${st3} && test -f ${f}; then
shar_touch='touch -am $3$4$5$6$2 "$8"'

else
shar_touch=:
echo
${echo} 'WARNING: not restoring timestamps. Consider getting and
installing GNU `touch'\'', distributed in GNU coreutils...'
echo
fi
rm -f ${st1} ${st2} ${st2tr} ${st3} ${f}
#
if test ! -d ${lock_dir} ; then :
else ${echo} "lock directory ${lock_dir} exists"
exit 1
fi
if mkdir ${lock_dir}
then ${echo} "x - created lock directory ${lock_dir}."
else ${echo} "x - failed to create lock directory ${lock_dir}."
exit 1
fi
# ============= desc.txt ==============
if test -n "${keep_file}" && test -f 'desc.txt'
then
${echo} "x - SKIPPING desc.txt (file already exists)"
else
${echo} "x - extracting desc.txt (text)"
sed 's/^X//' << 'SHAR_EOF' > 'desc.txt' &&
When working with simulated soft CPUs to be implemented in FPGA,
I often needed a possibility to connect terminal emulator
(e.g. Minicom) or my own program to serial port of the simulated
IP core.
X
Finally I've found a solution, which seems to be good enough
to share it with others.
X
I use the pseudoterminal (ptmx) found in Linux to establish
communication between GHDL simulator and my terminal program.
However GHDL does not offer functions needed to control
pseudoterminals, therefore I've prepared a small C library
(ghdl_pty.c) providing necessary functions via VPI.
Additionally I needed to provide nonblocking reading from
the pseudoterminal, to avoid stopping of simulation when no
data is available this functionality is also implemented
in ghdl_pty.c, in function ghdl_pty_read.
X
XFrom the VHDL side, my pseudo UART is visible as:
X
X component ghdl_uart
X port (
X data_out : out std_logic_vector(7 downto 0);
X data_in : in std_logic_vector(7 downto 0);
X dav : out std_logic; -- received data available
X ready : out std_logic; -- there is free space in transmit buffer
X empty : out std_logic; -- the transmit buffer is empty
X rd : in std_logic; -- asynchronous read strobe
X wr : in std_logic -- asynchronous write strobe
X );
X end component;
X
When new data arrives, "dav" goes high. To read the data, you should
set "rd" to '1' and the data will be visible on "data_out".
If no more data are in the input queue, "dav" goes low.
X
If you want to write data, you put them on "data_in", and rise "wr".
The data are transmitted to the output queue, and later transmitted
to the pseudoterminal.
X
The design with input and output queues may seem to be too complex,
but allows you to easily modify ghdl_uart.vhd adding clock and
providing synchronous operation.
However even the current implementation may work with synchronous
block, as shown in the provided testbench (ghdl_uart_tb.vhd).
X
To check how does it work, you should unpack the archive,
and simply issue the "make" command.
After successful compilation, you will see information about
assigned pseudoterminal (/dev/pts/11 in the case shown below):
X
$ make
gcc -c ghdl_pty.c
ghdl -a --std=02 --ieee=standard ghdl_uart_pkg.vhd ghdl_uart.vhd ghdl_uart_tb.vhd
ghdl -e -Wl,ghdl_pty.o --std=02 --ieee=standard ghdl_uart_tb
X./ghdl_uart_tb
Psudoterminal: /dev/pts/11
X
So you should start minicom in another console:
$ minicom -p /dev/pts/11
X
and you'll be able to communicate with the simulated IP core.
The core simulated in testbench simple echoes received characters with
toggled 5th bit.
X
When you disconnect your program from pseudoterminal, the simulation will stop.
However you may change this behaviour modifying ghdl_pty.c
X
I hope, that the emulated UART will be useful for you, therefore I've
published it as PUBLIC DOMAIN.
X
Wojciech M. Zabolotny
wzab<at>ise.pw.edu.pl
X
SHAR_EOF
(set 20 11 06 02 19 18 27 'desc.txt'
eval "${shar_touch}") && \
chmod 0644 'desc.txt'
if test $? -ne 0
then ${echo} "restore of desc.txt failed"
fi
if ${md5check}
then (
${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'desc.txt': 'MD5 check failed'
) << \SHAR_EOF
a45496cfbbae935c5b70174470b48153 desc.txt
SHAR_EOF
else
test `LC_ALL=C wc -c < 'desc.txt'` -ne 2946 && \
${echo} "restoration warning: size of 'desc.txt' is not 2946"
fi
fi
# ============= ghdl_pty.c ==============
if test -n "${keep_file}" && test -f 'ghdl_pty.c'
then
${echo} "x - SKIPPING ghdl_pty.c (file already exists)"
else
${echo} "x - extracting ghdl_pty.c (text)"
sed 's/^X//' << 'SHAR_EOF' > 'ghdl_pty.c' &&
/*
X VPI code allowing you to connect terminal emulator or other program to pty "connected"
X to the UART-like port in IP core simulated in GHDL.
X
X This code is written by Wojciech M. Zabolotny (wz...@ise.pw.edu.pl) on 2nd June 2011
X and is published as PUBLIC DOMAIN
X
*/
X
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <linux/ioctl.h>
#include <sys/stat.h>
#include <sys/poll.h>
#include <fcntl.h>
#include <errno.h>
X
int ptyf = -1;
X
int ghdl_pty_open(void)
{
X ptyf = open("/dev/ptmx",O_RDWR);
X if(ptyf<0) {
X perror("I can't open pseudoterminal\n");
X return -1;
X }
X if(unlockpt(ptyf)<0) {
X perror("I can't unlock pseudoterminal\n");
X return -1;
X }
X if(grantpt(ptyf)<0) {
X perror("I can't grant pseudoterminal\n");
X return -1;
X }
X printf("Psudoterminal: %s\n",ptsname(ptyf));
X return 0;
}
X
int ghdl_pty_read(void)
{
X unsigned char c;
X //In the masks below you may omit POLLHUP in this case
X //disconnection of the terminal emulator from pty will not
X //stop simulation, and you'll be able to reconnect
X //the same or different program to pty and running simulation
X struct pollfd pfd[1]={{ptyf,POLLIN | POLLERR | POLLHUP,0}};
X int res;
X res=poll(pfd,1,0);
X if(res==0) return -1;
X if(res<0) return -2; //error
X //If you removed POLLHUP from the mask above, you should remove it below too
X if(pfd[0].revents & (POLLERR|POLLHUP)) return -2; //disconnected or error?
X if(pfd[0].revents & POLLIN) {
X read(ptyf,&c,1);
X return c;
X }
X return -3; //Shouldn't happen!
}
X
int ghdl_pty_write(int byte)
{
X unsigned char c = byte;
X write(ptyf,&c,1);
X return 0;
}
X
X
SHAR_EOF
(set 20 11 06 02 18 45 20 'ghdl_pty.c'
eval "${shar_touch}") && \
chmod 0644 'ghdl_pty.c'
if test $? -ne 0
then ${echo} "restore of ghdl_pty.c failed"
fi
if ${md5check}
then (
${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'ghdl_pty.c': 'MD5 check failed'
) << \SHAR_EOF
f6ffc4589eb8199662d17666a666966e ghdl_pty.c
SHAR_EOF
else
test `LC_ALL=C wc -c < 'ghdl_pty.c'` -ne 1717 && \
${echo} "restoration warning: size of 'ghdl_pty.c' is not 1717"
fi
fi
# ============= ghdl_uart_pkg.vhd ==============
if test -n "${keep_file}" && test -f 'ghdl_uart_pkg.vhd'
then
${echo} "x - SKIPPING ghdl_uart_pkg.vhd (file already exists)"
else
${echo} "x - extracting ghdl_uart_pkg.vhd (text)"
sed 's/^X//' << 'SHAR_EOF' > 'ghdl_uart_pkg.vhd' &&
-------------------------------------------------------------------------------
-- Title : GHDL UART
-- Project : GHDL UART
-------------------------------------------------------------------------------
-- File : ghdl_uart_pkg.vhd
-- Author : Wojciech M. Zabolotny ( wz...@ise.pw.edu.pl )
-- Created : 2011-06-02
-- Last update: 2011-06-02
-- Platform :
-- Standard : VHDL'93
-------------------------------------------------------------------------------
-- Description: GHDL UART allows you to communicate with IP core simulated in
-- GHDL simulator via pseudoterminal in Linux or similar system
-- You may use minicom, or your own program to connect to pseudoterminal
-- allocated by GHDL UART and work with simulated IP core like with real
-- hardware via hardware UART.
-------------------------------------------------------------------------------
-- Copyright (c) 2011
-- Published as PUBLIC DOMAIN
-------------------------------------------------------------------------------
-- Revisions :
-- Date Version Author Description
-- 2011-06-02 1.0 wzab Created
X
package ghdl_uart_pkg is
X
X function ghdl_pty_open
X return integer;
X attribute foreign of ghdl_pty_open : function is "VHPIDIRECT ghdl_pty_open";
X function ghdl_pty_read
X return integer;
X attribute foreign of ghdl_pty_read : function is "VHPIDIRECT ghdl_pty_read";
X function ghdl_pty_write (
X v : integer)
X return integer;
X attribute foreign of ghdl_pty_write : function is "VHPIDIRECT ghdl_pty_write";
X
end ghdl_uart_pkg;
X
package body ghdl_uart_pkg is
X
X function ghdl_pty_open
X return integer is
X begin -- ghdl_pty_open
X assert false severity failure;
X end ghdl_pty_open;
X
X function ghdl_pty_read
X return integer is
X begin -- ghdl_pty_read
X assert false severity failure;
X end ghdl_pty_read;
X
X function ghdl_pty_write (
X v : integer)
X return integer is
X begin -- ghdl_pty_write
X assert false severity failure;
X end ghdl_pty_write;
X
end ghdl_uart_pkg;
SHAR_EOF
(set 20 11 06 02 18 38 04 'ghdl_uart_pkg.vhd'
eval "${shar_touch}") && \
chmod 0644 'ghdl_uart_pkg.vhd'
if test $? -ne 0
then ${echo} "restore of ghdl_uart_pkg.vhd failed"
fi
if ${md5check}
then (
${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'ghdl_uart_pkg.vhd': 'MD5 check failed'
) << \SHAR_EOF
309fccd533f88144536b84f678b98ad5 ghdl_uart_pkg.vhd
SHAR_EOF
else
test `LC_ALL=C wc -c < 'ghdl_uart_pkg.vhd'` -ne 2017 && \
${echo} "restoration warning: size of 'ghdl_uart_pkg.vhd' is not 2017"
fi
fi
# ============= ghdl_uart_tb.vhd ==============
if test -n "${keep_file}" && test -f 'ghdl_uart_tb.vhd'
then
${echo} "x - SKIPPING ghdl_uart_tb.vhd (file already exists)"
else
${echo} "x - extracting ghdl_uart_tb.vhd (text)"
sed 's/^X//' << 'SHAR_EOF' > 'ghdl_uart_tb.vhd' &&
-------------------------------------------------------------------------------
-- Title : Testbench for design "ghdl_uart"
-- Project : GHDL UART
-------------------------------------------------------------------------------
-- File : ghdl_uart_tb.vhd
-- Author : wzab
-- Company :
-- Created : 2006-12-02
-- Last update: 2011-06-02
-- Platform :
-- Standard : VHDL'87
-------------------------------------------------------------------------------
-- Description: This is a testbench, demonstrating
-------------------------------------------------------------------------------
-- Copyright (c) 2006
-- Published as PUBLIC DOMAIN
-------------------------------------------------------------------------------
-- Revisions :
-- Date Version Author Description
-- 2006-12-02 1.0 wzab Created
-------------------------------------------------------------------------------
X
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use std.textio.all;
library work;
-------------------------------------------------------------------------------
X
entity ghdl_uart_tb is
X
end ghdl_uart_tb;
X
-------------------------------------------------------------------------------
X
architecture symul2 of ghdl_uart_tb is
X constant rdp_name : string := "/tmp/wrpipe";
X constant wrp_name : string := "/tmp/rdpipe";
X
X component ghdl_uart
X port (
X data_out : out std_logic_vector(7 downto 0);
X data_in : in std_logic_vector(7 downto 0);
X dav : out std_logic; -- received data available
X ready : out std_logic; -- there is free space in transmit buffer
X empty : out std_logic; -- the transmit buffer is empty
X rd : in std_logic; -- asynchronous read strobe
X wr : in std_logic -- asynchronous write strobe
X );
X end component;
X
X signal data_out : std_logic_vector(7 downto 0);
X signal data_in : std_logic_vector(7 downto 0);
X signal dav : std_logic;
X signal ready : std_logic;
X signal rd : std_logic;
X signal wr : std_logic;
X signal rst : std_logic := '0';
X
X -- clock
X signal Clk : std_logic := '1';
X
begin -- symul2
X
X ghdl_uart_1 : ghdl_uart
X port map (
X data_out => data_out,
X data_in => data_in,
X dav => dav,
X ready => ready,
X empty => open,
X rd => rd,
X wr => wr);
X
X data_in <= data_out xor x"20"; -- We send back received data with
X -- toggled 5th bit
X
X process (clk, rst)
X -- The ghdl_uart block is asynchronous, however to show how it may be used
X -- in a synchronous block, I have created a simple synchronous process
X begin -- process
X if rst = '0' then -- asynchronous reset (active low)
X rd <= '0';
X wr <= '0';
X elsif clk'event and clk = '1' then -- rising clock edge
X rd <= '0';
X wr <= '0';
X if (dav = '1') and (rd = '0') and (ready = '1') then
X -- 1st cycle: Received data is available, raise rd signal to read it
X rd <= '1';
X elsif rd = '1' then
X -- 2nd cycle: Read data is available on data_out and with toggled 5th
X -- bit on data_in, we start writing the converted data
X wr <= '1';
X elsif wr = '1' then
X -- 3rd cycle: deactivate both rd and wr signals and wait until dav goes
X -- high again
X rd <= '0';
X wr <= '0';
X end if;
X end if;
X end process;
X
X Clk <= not Clk after 100 ns;
X Rst <= '1' after 25 ns;
end symul2;
X
-------------------------------------------------------------------------------
X
configuration ghdl_uart_tb_symul2_cfg of ghdl_uart_tb is
X for symul2
X end for;
end ghdl_uart_tb_symul2_cfg;
X
-------------------------------------------------------------------------------
SHAR_EOF
(set 20 11 06 02 18 45 06 'ghdl_uart_tb.vhd'
eval "${shar_touch}") && \
chmod 0644 'ghdl_uart_tb.vhd'
if test $? -ne 0
then ${echo} "restore of ghdl_uart_tb.vhd failed"
fi
if ${md5check}
then (
${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'ghdl_uart_tb.vhd': 'MD5 check failed'
) << \SHAR_EOF
ab27e8d43ed82b7fa4f14b4731f3ef27 ghdl_uart_tb.vhd
SHAR_EOF
else
test `LC_ALL=C wc -c < 'ghdl_uart_tb.vhd'` -ne 3845 && \
${echo} "restoration warning: size of 'ghdl_uart_tb.vhd' is not 3845"
fi
fi
# ============= ghdl_uart.vhd ==============
if test -n "${keep_file}" && test -f 'ghdl_uart.vhd'
then
${echo} "x - SKIPPING ghdl_uart.vhd (file already exists)"
else
${echo} "x - extracting ghdl_uart.vhd (text)"
sed 's/^X//' << 'SHAR_EOF' > 'ghdl_uart.vhd' &&
-------------------------------------------------------------------------------
-- Title : GHDL UART
-- Project : GHDL UART
-------------------------------------------------------------------------------
-- File : ghdl_uart.vhd
-- Author : Wojciech M. Zabolotny ( wz...@ise.pw.edu.pl )
-- Created : 2011-06-02
-- Last update: 2011-06-02
-- Platform :
-- Standard : VHDL'93
-------------------------------------------------------------------------------
-- Description: GHDL UART allows you to communicate with IP core simulated in
-- GHDL simulator via pseudoterminal in Linux or similar system
-- You may use minicom, or your own program to connect to pseudoterminal
-- allocated by GHDL UART and work with simulated IP core like with real
-- hardware via hardware UART.
-------------------------------------------------------------------------------
-- Copyright (c) 2011
-- Published as PUBLIC DOMAIN
-------------------------------------------------------------------------------
-- Revisions :
-- Date Version Author Description
-- 2011-06-02 1.0 wzab Created
-------------------------------------------------------------------------------
X
X
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use std.textio.all;
library work;
use work.ghdl_uart_pkg.all;
X
entity ghdl_uart is
X
X port (
X data_out : out std_logic_vector(7 downto 0);
X data_in : in std_logic_vector(7 downto 0);
X dav : out std_logic; -- received data available
X ready : out std_logic; -- there is free space in transmit buffer
X empty : out std_logic; -- the transmit buffer is empty
X rd : in std_logic; -- asynchronous read strobe
X wr : in std_logic -- asynchronous write strobe
X );
X
end ghdl_uart;
X
architecture simul of ghdl_uart is
X constant UART_FIFO_LENGTH : integer := 1000;
X type T_UART_FIFO is array (0 to UART_FIFO_LENGTH) of integer;
X signal wr_fifo, rd_fifo : T_UART_FIFO;
-- FIFO pointers
X signal wr_fifo_rp, wr_fifo_wp, rd_fifo_rp, rd_fifo_wp : integer := 0;
X
begin -- simul
X
-- Processes controlling flags informing about status of UART
X dav <= '1' when rd_fifo_wp /= rd_fifo_rp else '0';
X
X check_ready : process (wr_fifo_rp, wr_fifo_wp)
X variable new_wp : integer;
X begin -- process
X ready <= '1';
X new_wp := wr_fifo_wp + 1;
X if new_wp = UART_FIFO_LENGTH then
X new_wp := 0;
X end if;
X if new_wp = wr_fifo_rp then
X ready <= '0';
X end if;
X end process check_ready;
X
X empty <= '0' when wr_fifo_wp /= wr_fifo_rp else '1';
X
X -- Process reading the data from the output FIFO
X -- and transmitting it to the PTY via VPI routine
X
X pipe_wr : process (wr_fifo, wr_fifo_rp, wr_fifo_wp)
X variable char_out : integer;
X variable new_rp : integer;
X variable res : integer;
X begin
X if wr_fifo_rp /= wr_fifo_wp then
X char_out := wr_fifo(wr_fifo_rp);
X res := ghdl_pty_write(char_out);
X -- Update pointer
X new_rp := wr_fifo_rp+1;
X if new_rp = UART_FIFO_LENGTH then
X new_rp := 0;
X end if;
X wr_fifo_rp <= new_rp;
X end if;
X end process pipe_wr;
X
X -- Process reading data from PTY (via VPI routine)
X -- and putting it into the read FIFO
X pipe_rd : process
X variable char_in : integer;
X variable new_wp : integer;
X variable res : integer;
X begin -- process reading from socket
X res := ghdl_pty_open;
X while true loop
X char_in := ghdl_pty_read;
X if char_in = -2 then
X assert false report "Pseudoterminal disconnected?" severity failure;
X end if;
X if char_in >= 0 then
X new_wp := rd_fifo_wp+1;
X if new_wp = UART_FIFO_LENGTH then
X new_wp := 0;
X end if;
X if new_wp = rd_fifo_rp then
X -- FIFO overflow!
X assert false report "FIFO overflow!" severity failure;
X else
X rd_fifo(rd_fifo_wp) <= char_in;
X rd_fifo_wp <= new_wp;
X end if;
X end if;
X -- You may customize the value below to change responsivness of
X -- the simulation
X wait for 1000 ns;
X end loop;
X end process pipe_rd;
X
X -- Read process (asynchronous version)
X RD1 : process (rd)
X variable rline : line;
X variable new_rp : integer;
X begin -- process
X if rd'event and rd = '1' then
X data_out <= (others => 'U');
X if rd_fifo_rp /= rd_fifo_wp then
X data_out <= std_logic_vector(to_unsigned(rd_fifo(rd_fifo_rp), 8));
X new_rp := rd_fifo_rp + 1;
X if new_rp = UART_FIFO_LENGTH then
X new_rp := 0;
X end if;
X rd_fifo_rp <= new_rp;
X end if;
X end if;
X end process RD1;
X
X
X -- Write process (asynchronous version)
X WR1 : process (wr)
X --variable rline : line;
X variable new_wp : integer;
X begin -- process
X if wr'event and wr = '1' then
X new_wp := wr_fifo_wp + 1;
X if new_wp = UART_FIFO_LENGTH then
X new_wp := 0;
X end if;
X if new_wp /= wr_fifo_rp then
X wr_fifo(wr_fifo_wp) <= to_integer(unsigned(data_in));
X wr_fifo_wp <= new_wp;
X end if;
X end if;
X end process WR1;
X
end simul;
SHAR_EOF
(set 20 11 06 02 18 38 22 'ghdl_uart.vhd'
eval "${shar_touch}") && \
chmod 0644 'ghdl_uart.vhd'
if test $? -ne 0
then ${echo} "restore of ghdl_uart.vhd failed"
fi
if ${md5check}
then (
${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'ghdl_uart.vhd': 'MD5 check failed'
) << \SHAR_EOF
7ef686e7819e137c6375fcfd76755943 ghdl_uart.vhd
SHAR_EOF
else
test `LC_ALL=C wc -c < 'ghdl_uart.vhd'` -ne 5231 && \
${echo} "restoration warning: size of 'ghdl_uart.vhd' is not 5231"
fi
fi
# ============= makefile ==============
if test -n "${keep_file}" && test -f 'makefile'
then
${echo} "x - SKIPPING makefile (file already exists)"
else
${echo} "x - extracting makefile (text)"
sed 's/^X//' << 'SHAR_EOF' > 'makefile' &&
VHDLS = \
X ghdl_uart_pkg.vhd \
X ghdl_uart.vhd \
X ghdl_uart_tb.vhd \
X
STD=standard
#STD=synopsys
X
all: simulate
X
ghdl_pty.o : ghdl_pty.c
X gcc -c ghdl_pty.c
X
simulate: ghdl_uart_tb
X ./ghdl_uart_tb
# ./wzrmb_tb --vcd=wzrmb_tb.vcd --stop-time=500000ns
ghdl_uart_tb: ${VHDLS} ghdl_pty.o
# vhdlp -work fmf fmf/*.vhd
X ghdl -a --std=02 --ieee=${STD} ${VHDLS}
X ghdl -e -Wl,ghdl_pty.o --std=02 --ieee=${STD} ghdl_uart_tb
clean:
X rm *.o *.vcd *.ghw ghdl_uart_tb
X
SHAR_EOF
(set 20 11 06 02 18 47 48 'makefile'
eval "${shar_touch}") && \
chmod 0664 'makefile'
if test $? -ne 0
then ${echo} "restore of makefile failed"
fi
if ${md5check}
then (
${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'makefile': 'MD5 check failed'
) << \SHAR_EOF
dc830bf595de501e590ec3a5d29a6f28 makefile
SHAR_EOF
else
test `LC_ALL=C wc -c < 'makefile'` -ne 463 && \
${echo} "restoration warning: size of 'makefile' is not 463"
fi
fi
if rm -fr ${lock_dir}
then ${echo} "x - removed lock directory ${lock_dir}."
else ${echo} "x - failed to remove lock directory ${lock_dir}."
exit 1
fi
exit 0

Wojciech M. Zabolotny

unread,
Apr 8, 2012, 4:20:09 PM4/8/12
to
Below are the sources (in C and VHDL) implementing the pseudo-UART
allowing you to establish communication with your IP core simulated
in GHDL (http://ghdl.free.fr).
The simulated core is accesible via pseudoterminal (e.g. /dev/pts/11)
in Linux or similar system, just as it would be a real hardware
connected to real hardware port.
For details see "desc.txt" in attached archive.
All attached sources are PUBLIC DOMAIN. however I'd be glad if someone
using them provides information about original sources.
I'd be also glad to hear about people using this design and about any
improvements introduced by them.

This version is improved comparing to the original by adding
support for setupTerminal function (written by Alejandro
Armagnac).
Additionally I have also added "#define _XOPEN_SOURCE" definition
in ghdl_pty.c file, which is needed to correctly compile
support for pseudoterminals.

Wojciech M. Zabolotny
wzab<at>ise.pw.edu.pl

#!/bin/sh
# This is a shell archive (produced by GNU sharutils 4.11).
# To extract the files from this archive, save it to some FILE, remove
# everything before the `#!/bin/sh' line above, then type `sh FILE'.
#
lock_dir=_sh28251
# Made on 2012-04-08 22:14 CEST by <wzab@WZLap>.
# Source directory was `/home/wzab/biezace/VHDL/sock_uart/vpi2'.
#
# Existing files will *not* be overwritten, unless `-c' is specified.
#
# This shar contains:
# length mode name
# ------ ---------- ------------------------------------------
# 3233 -rw-r--r-- desc.txt
# 2245 -rw-r--r-- ghdl_pty.c
# 2342 -rw-r--r-- ghdl_uart_pkg.vhd
# 3851 -rw-r--r-- ghdl_uart_tb.vhd
# 5276 -rw-r--r-- ghdl_uart.vhd
# 387 -rw-rw-r-- makefile
CHANGES:
This version of ghdl_uart has been improved by Alejandro Armagnac,
who added support for setupTerminal function allowing to set the speed.
X
Additionally I have added the "#define _XOPEN_SOURCE" directive
which is now needed to correctly support the pseudoterminal
X
DESCRIPTION:
(set 20 12 04 08 22 14 18 'desc.txt'
eval "${shar_touch}") && \
chmod 0644 'desc.txt'
if test $? -ne 0
then ${echo} "restore of desc.txt failed"
fi
if ${md5check}
then (
${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'desc.txt': 'MD5 check failed'
) << \SHAR_EOF
b56accbd093948868a950844b7ba48cd desc.txt
SHAR_EOF
else
test `LC_ALL=C wc -c < 'desc.txt'` -ne 3233 && \
${echo} "restoration warning: size of 'desc.txt' is not 3233"
fi
fi
# ============= ghdl_pty.c ==============
if test -n "${keep_file}" && test -f 'ghdl_pty.c'
then
${echo} "x - SKIPPING ghdl_pty.c (file already exists)"
else
${echo} "x - extracting ghdl_pty.c (text)"
sed 's/^X//' << 'SHAR_EOF' > 'ghdl_pty.c' &&
/*
X VPI code allowing you to connect terminal emulator or other program to pty "connected"
X to the UART-like port in IP core simulated in GHDL.
X
X This code is written by Wojciech M. Zabolotny (wz...@ise.pw.edu.pl) on 2nd June 2011
X and is published as PUBLIC DOMAIN
X
*/
#define _XOPEN_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <unistd.h>
#include <termios.h>
/* Function below added by Alejandro Armagnac */
int ghdl_pty_setupTerminal(int speed_int)
{
X speed_t speed = speed_int;
X struct termios options;
X
X if (tcgetattr(ptyf, &options) == -1)
X {
X printf("Error getting tty attributes");
X return -1;
X }
X
X cfmakeraw(&options);
X cfsetspeed(&options, speed);
X
X options.c_cflag |= (CS8);
X
X if (tcsetattr(ptyf, TCSANOW, &options) == -1)
X {
X printf("Error setting tty attributes");
X return -1;
X }
X
X return 0;
}
X
SHAR_EOF
(set 20 12 04 08 21 57 27 'ghdl_pty.c'
eval "${shar_touch}") && \
chmod 0644 'ghdl_pty.c'
if test $? -ne 0
then ${echo} "restore of ghdl_pty.c failed"
fi
if ${md5check}
then (
${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'ghdl_pty.c': 'MD5 check failed'
) << \SHAR_EOF
ddd94346b48164580a8dccd8ea11e79a ghdl_pty.c
SHAR_EOF
else
test `LC_ALL=C wc -c < 'ghdl_pty.c'` -ne 2245 && \
${echo} "restoration warning: size of 'ghdl_pty.c' is not 2245"
fi
fi
# ============= ghdl_uart_pkg.vhd ==============
if test -n "${keep_file}" && test -f 'ghdl_uart_pkg.vhd'
then
${echo} "x - SKIPPING ghdl_uart_pkg.vhd (file already exists)"
else
${echo} "x - extracting ghdl_uart_pkg.vhd (text)"
sed 's/^X//' << 'SHAR_EOF' > 'ghdl_uart_pkg.vhd' &&
-------------------------------------------------------------------------------
-- Title : GHDL UART
-- Project : GHDL UART
-------------------------------------------------------------------------------
-- File : ghdl_uart_pkg.vhd
-- Author : Wojciech M. Zabolotny ( wz...@ise.pw.edu.pl )
-- Created : 2011-06-02
-- Last update: 2012-04-08
X function ghdl_pty_setupTerminal (baud : integer)
X return integer;
X attribute foreign of ghdl_pty_setupTerminal : function is
X "VHPIDIRECT ghdl_pty_setupTerminal";
X
X
end ghdl_uart_pkg;
X
package body ghdl_uart_pkg is
X
X function ghdl_pty_open
X return integer is
X begin -- ghdl_pty_open
X assert false severity failure;
X end ghdl_pty_open;
X
X function ghdl_pty_read
X return integer is
X begin -- ghdl_pty_read
X assert false severity failure;
X end ghdl_pty_read;
X
X function ghdl_pty_write (
X v : integer)
X return integer is
X begin -- ghdl_pty_write
X assert false severity failure;
X end ghdl_pty_write;
X
X function ghdl_pty_setupTerminal (baud : integer)
X return integer is
X begin
X assert false severity failure;
X end ghdl_pty_setupTerminal;
X
X
end ghdl_uart_pkg;
SHAR_EOF
(set 20 12 04 08 21 28 12 'ghdl_uart_pkg.vhd'
eval "${shar_touch}") && \
chmod 0644 'ghdl_uart_pkg.vhd'
if test $? -ne 0
then ${echo} "restore of ghdl_uart_pkg.vhd failed"
fi
if ${md5check}
then (
${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'ghdl_uart_pkg.vhd': 'MD5 check failed'
) << \SHAR_EOF
d6af77ecea4a98094e519437514a63ac ghdl_uart_pkg.vhd
SHAR_EOF
else
test `LC_ALL=C wc -c < 'ghdl_uart_pkg.vhd'` -ne 2342 && \
${echo} "restoration warning: size of 'ghdl_uart_pkg.vhd' is not 2342"
fi
fi
# ============= ghdl_uart_tb.vhd ==============
if test -n "${keep_file}" && test -f 'ghdl_uart_tb.vhd'
then
${echo} "x - SKIPPING ghdl_uart_tb.vhd (file already exists)"
else
${echo} "x - extracting ghdl_uart_tb.vhd (text)"
sed 's/^X//' << 'SHAR_EOF' > 'ghdl_uart_tb.vhd' &&
-------------------------------------------------------------------------------
-- Title : Testbench for design "ghdl_uart"
-- Project : GHDL UART
-------------------------------------------------------------------------------
-- File : ghdl_uart_tb.vhd
-- Author : wzab
-- Company :
-- Created : 2006-12-02
-- Last update: 2012-04-08
X --constant rdp_name : string := "/tmp/wrpipe";
X --ODconstant wrp_name : string := "/tmp/rdpipe";
(set 20 12 04 08 21 38 56 'ghdl_uart_tb.vhd'
eval "${shar_touch}") && \
chmod 0644 'ghdl_uart_tb.vhd'
if test $? -ne 0
then ${echo} "restore of ghdl_uart_tb.vhd failed"
fi
if ${md5check}
then (
${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'ghdl_uart_tb.vhd': 'MD5 check failed'
) << \SHAR_EOF
d5c4158b764463ec50eda3bb5ac94990 ghdl_uart_tb.vhd
SHAR_EOF
else
test `LC_ALL=C wc -c < 'ghdl_uart_tb.vhd'` -ne 3851 && \
${echo} "restoration warning: size of 'ghdl_uart_tb.vhd' is not 3851"
fi
fi
# ============= ghdl_uart.vhd ==============
if test -n "${keep_file}" && test -f 'ghdl_uart.vhd'
then
${echo} "x - SKIPPING ghdl_uart.vhd (file already exists)"
else
${echo} "x - extracting ghdl_uart.vhd (text)"
sed 's/^X//' << 'SHAR_EOF' > 'ghdl_uart.vhd' &&
-------------------------------------------------------------------------------
-- Title : GHDL UART
-- Project : GHDL UART
-------------------------------------------------------------------------------
-- File : ghdl_uart.vhd
-- Author : Wojciech M. Zabolotny ( wz...@ise.pw.edu.pl )
-- Created : 2011-06-02
-- Last update: 2012-04-08
X --res := ghdl_pty_setupTerminal(115200);
(set 20 12 04 08 21 39 28 'ghdl_uart.vhd'
eval "${shar_touch}") && \
chmod 0644 'ghdl_uart.vhd'
if test $? -ne 0
then ${echo} "restore of ghdl_uart.vhd failed"
fi
if ${md5check}
then (
${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'ghdl_uart.vhd': 'MD5 check failed'
) << \SHAR_EOF
ba1c024675a695906785b1342474e798 ghdl_uart.vhd
SHAR_EOF
else
test `LC_ALL=C wc -c < 'ghdl_uart.vhd'` -ne 5276 && \
${echo} "restoration warning: size of 'ghdl_uart.vhd' is not 5276"
fi
fi
# ============= makefile ==============
if test -n "${keep_file}" && test -f 'makefile'
then
${echo} "x - SKIPPING makefile (file already exists)"
else
${echo} "x - extracting makefile (text)"
sed 's/^X//' << 'SHAR_EOF' > 'makefile' &&
VHDLS = \
X ghdl_uart_pkg.vhd \
X ghdl_uart.vhd \
X ghdl_uart_tb.vhd \
X
STD=standard
#STD=synopsys
X
all: simulate
X
ghdl_pty.o : ghdl_pty.c
X gcc -c ghdl_pty.c
X
simulate: ghdl_uart_tb
X ./ghdl_uart_tb
ghdl_uart_tb: ${VHDLS} ghdl_pty.o
X ghdl -a --std=02 --ieee=${STD} ${VHDLS}
X ghdl -e -Wl,ghdl_pty.o --std=02 --ieee=${STD} ghdl_uart_tb
clean:
X rm *.o *.vcd *.ghw *.cf ghdl_uart_tb
X
SHAR_EOF
(set 20 12 04 08 22 00 57 'makefile'
eval "${shar_touch}") && \
chmod 0664 'makefile'
if test $? -ne 0
then ${echo} "restore of makefile failed"
fi
if ${md5check}
then (
${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'makefile': 'MD5 check failed'
) << \SHAR_EOF
52b5c089c0c07aa919b0e064f0cfeb6d makefile
SHAR_EOF
else
test `LC_ALL=C wc -c < 'makefile'` -ne 387 && \
${echo} "restoration warning: size of 'makefile' is not 387"

wza...@gmail.com

unread,
Mar 5, 2015, 8:15:14 AM3/5/15
to
I have just stated, that to obtain correct operation with current version of GNU/Linux OS, I had to add:

#define _XOPEN_SOURCE

in the ghdl_pty.c
before all "#include" statements.
--
Regards,
Wojtek

wza...@gmail.com

unread,
Mar 5, 2015, 8:16:22 AM3/5/15
to
Oooops, It was already added in version 1.1
Sorry for confusion,
Wojtek
0 new messages