umarcor on keep-compiling
ci: use the built-in '--keep-co… (compare)
umarcor on cosim
cosim/dpi-ffi: add 'vhdpi_ghdl.… cosim/dpi-ffi: add VHDPI_Test (compare)
umarcor on cosim
WIP setenv (compare)
umarcor on main
cosim/dpi-ffi/ghdl-vffi/test: a… (compare)
umarcor on cosim
umarcor on main
WIP envvars (compare)
umarcor on cosim
WIP envvars (compare)
umarcor on master
umarcor on main
umarcor on cosim
umarcor on master
cosim/dpi-ffi: create subdir 'g… cosim/dpi-ffi: fix compilation … cosim/dpi-ffi/ghd-vffi: use VUn… and 2 more (compare)
umarcor on cosim
ci: add workflow CoSim cosim/dpi-ffi: add README (compare)
umarcor on cosim
ci: add workflow CoSim cosim/dpi-ffi: add README (compare)
umarcor on cosim
cosim/dpi-ffi: create subdir 'g… cosim/dpi-ffi: fix compilation … cosim/dpi-ffi/ghd-vffi: use VUn… and 2 more (compare)
umarcor on top-subtype
umarcor on master
2008: ad tb_top_generic_subtype cosim: add ref to aguinet/drago… (compare)
umarcor on top-subtype
2008: ad tb_top_generic_subtype (compare)
umarcor on top-subtype
2008: ad tb_top_generic_subtype (compare)
umarcor on top-subtype
2008: ad tb_top_generic_subtype (compare)
umarcor on style
type t;
is legal as a forward type declaration, but it requires the complete type at a later point in the same unit
package P2 is
generic (
type designated_subtype
);
type fred is access designated_subtype ;
type tricky_pt is new protected pt
generic map (
....
);
It's a (new) type, and no subtype, because instances of PT are not compatible to each other.
either create a library file first, then run ghdl-yosys-plugin on that:
ghdl analyze file1.vhdl file2.vhdl subdir/file3.vhdl
ghdl elaborate topentity
yosys -m ghdl -p 'ghdl topentity'
or run ghdl-yosys-plugin directly on the files, without creating a library file:
yosys -m ghdl -p 'ghdl file1.vhdl file2.vhdl subdir/file3.vhdl -e topentity'
in general, the yosys ghdl
command is equivalent to invoking the ghdl binary as ghdl --synth
.
Actually, there is another solution in-between:
ghdl analyze file1.vhdl file2.vhdl subdir/file3.vhdl
yosys -m ghdl -p 'ghdl -e topentity'
That is useful if the files are analysed in a library different to the top-level, but you don't care about the logical lib name of the top-level:
ghdl analyze --work=designlib file1.vhdl file2.vhdl subdir/file3.vhdl
yosys -m ghdl -p 'ghdl toplevel.vhd -e topentity'
# Synthesis
yosys -m ghdl -p 'ghdl --work=designlib file1.vhdl file2.vhdl subdir/file3.vhdl --work=anyother toplevel.vhd -e topentity'
# Analysis and Elaboration
ghdl -a \
--work=designlib file1.vhdl file2.vhdl subdir/file3.vhdl \
--work=anyother toplevel.vhd testbench.vhd \
-e topentity
# elab-run
ghdl elab-run \
--work=designlib file1.vhdl file2.vhdl subdir/file3.vhdl \
--work=anyother toplevel.vhd testbench.vhd \
-e topentity \
--wave=mywave.ghw
entity test is
end test;
architecture rtl of test is
function f return real is
function f return real is
begin
return 3.14;
end f;
begin
return f;
end f;
begin
process
begin
report real'image(f);
wait;
end process;
end rtl;
function f return real;
function f return integer is
begin
return integer(real'(f));
end f;
I was on the team that created VHDL. I was probably the first person to actually write VHDL, since my task on the team was to write VHDL and see how usable it was.
inout
ports that are connected together
signal u1_io, u2_io : std_logic_vector(15 downto 0);
followed by u1 : one port map(io => u1_io); u2 : two port map(io => u2_io); u1_io <= transport u2_io after 10 ps; u2_io <= transport u1_io after 10 ps;
is not the way to go
'others
attribute: u1_io <= transport u2_io'others after 10 ps; u2_io <= transport u1_io'others after 10 ps;
sounds like a reasonable syntax, but I'm not sure how well that would translate to three drivers
If you "know" when each chip is driving the bus you could try something like:
p_delays : process(ic1_drive, ic2_drive, ic1_pin_io, ic2_pin_io)
begin
ic1_pin_io <= transport 'Z' after (12 ps);
ic2_pin_io <= transport 'Z' after (13 ps);
if(ic1_drive) then
ic2_pin_io <= transport ic1_pin_io after 9 ps;
end if;
if(ic2_drive) then
ic1_pin_io <= transport ic2_pin_io after 11 ps;
end if;
end process p_delays;
With:
To create ic1_drive and ic2_drive the test bench must look at the control signals in the transaction, and determine what is happening (this may be non trivial).
A quick test seems to be working as expected (there are some quirks when going to X, but it is a starting point).
Note: In this example the testbench drives the ic1_drive and ic2_drive instead of "calculating" them from other signals. But this makes it easier for the proof of concept.
--------------------------------------------------------------------------------
------------------------------------- ENTITY -----------------------------------
--------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
entity IC is
port(
drive : in std_logic;
clk : in std_logic;
pin_io : inout std_logic
);
end IC;
--------------------------------------------------------------------------------
---------------------------------- ARCHITECTURE --------------------------------
--------------------------------------------------------------------------------
architecture RTL of IC is
signal s_pin_val : std_ulogic := '0';
begin
pin_io <= s_pin_val when (drive = '1') else 'Z';
p_set_out : process (clk)
begin
if rising_edge(clk) then
if(drive = '1') then
s_pin_val <= NOT(s_pin_val);
end if;
end if;
end process p_set_out;
end RTL;
--------------------------------------------------------------------------------
------------------------------------- ENTITY -----------------------------------
--------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
entity IC_tb is
end IC_tb;
--------------------------------------------------------------------------------
---------------------------------- ARCHITECTURE --------------------------------
--------------------------------------------------------------------------------
architecture testBench of IC_tb is
signal clk : std_logic := '0';
signal ic1_drive : std_logic := '0';
signal ic2_drive : std_logic := '0';
signal ic1_pin_io : std_logic;
signal ic2_pin_io : std_logic;
begin
clk <= NOT(clk) after 50 ps;
p_delays : process(ic1_drive, ic2_drive, ic1_pin_io, ic2_pin_io)
begin
ic1_pin_io <= transport 'Z' after (12 ps);
ic2_pin_io <= transport 'Z' after (13 ps);
if(ic1_drive) then
ic2_pin_io <= transport ic1_pin_io after 9 ps;
end if;
if(ic2_drive) then
ic1_pin_io <= transport ic2_pin_io after 11 ps;
end if;
end process p_delays;
p_stimuli : process
begin
ic1_drive <= '0';
ic2_drive <= '0';
wait for 200 ps;
wait until rising_edge(clk);
ic1_drive <= '1';
wait for 500 ps;
wait until rising_edge(clk);
ic1_drive <= '0';
wait for 500 ps;
wait until rising_edge(clk);
ic2_drive <= '1';
wait for 500 ps;
wait until rising_edge(clk);
ic2_drive <= '0';
wait for 500 ps;
wait until rising_edge(clk);
ic1_drive <= '1';
ic2_drive <= '1';
wait for 500 ps;
wait until rising_edge(clk);
ic1_drive <= '0';
ic2_drive <= '0';
wait; -- !!!!!!!! Forever
end process p_stimuli;
i_ic1 : entity work.IC(RTL)
port map(
clk => clk,
drive => ic1_drive,
pin_io => ic1_pin_io
);
i_ic2 : entity work.IC(RTL)
port map(
clk => clk,
drive => ic2_drive,
pin_io => ic2_pin_io
);
end testBench;
Hello everyone! I need your advice on coding style. There are cases where I'm still struggling how to handle it.
Assuming that we want to, more or less, adhere to 80 chars per line rule how would you format this:
constant c_board_type : std_logic_vector(15 downto 0) := std_logic_vector(to_unsigned(g_board_type, 16));
-- ^ - 80 char limit
Should it look like this:
constant c_board_type : std_logic_vector(15 downto 0) :=
std_logic_vector(to_unsigned(g_board_type, 16));
or like this:
constant c_board_type : std_logic_vector(15 downto 0) := std_logic_vector(
to_unsigned(g_board_type,
16));
Same goes for example for function calls, where even the lenght of a single argument exceeds the 80 char limit.
write_to_ifc(adr_i => std_logic_vector(to_unsigned(ADDR_TOP_LEDS+ADDR_IN_OUT_REGS_POR, 32)), dat_i => x"0000_0000", perr_i => "0000", ptype_i => tb_ifc_parity_c);
-- ^ - 80 char limit
Should I just ignore this rule to fit the whole argument in one line:
write_to_ifc(adr_i => std_logic_vector(to_unsigned(ADDR_TOP_LEDS+ADDR_IN_OUT_REGS_POR, 32)),
dat_i => x"0000_0000", perr_i => "0000",
ptype_i => tb_ifc_parity_c);
-- ^ - 80 char limit
Or do you have better ideas?