Record fields assigned from different processes - vhdl

There is something strange going on when I assign different members of a record from different processes. What is the reason for this?
type t_collection is record
A : std_logic;
B : std_logic;
end record;
signal collection : t_collection ;
begin
collection.A <= '1';
process(Clk) is
begin
if rising_edge(Clk) then
collection.B <= '1';
end if;
end process;
In the simulator, collection.A resolves to 'X', and collection.B to '1'.

I agree with #fru1bat, unless there is more code in the assignment to "collection.B", it looks like you may have a bug in your simulator.
For Testbench applications, you can give the signal an initial value of all 'Z':
signal collection : t_collection := (A => 'Z', B => 'Z') ;
For RTL, I doubt the synthesis tools will like this.

Related

emulating systemverilog interfaces in VHDL using record types?

I've seen people using bidirectional buses of record types to emulate the SystemVerilog Interface language structure by driving either an input or output on each field of the record.... I'm just curious why my attempt to do the same things doesn't work? Any ideas how to do this correctly?
--Attemping to emulate SystemVerilog Interfaces using VHDL Record....
----------------------------------------------
-- DUT
----------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
entity dut is
port(
i1 : in std_logic;
i2 : in std_logic;
o1 : out std_logic;
o2 : out std_logic
);
end entity;
architecture beh of dut is
begin
o1 <= '1';
o2 <= '0';
end architecture;
----------------------------------------------
-- TESTBENCH
----------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_textio.all;
use std.textio.all;
entity testbench is
end entity;
architecture beh of testbench is
type sverilog_interface_t is record
field0 : std_logic;
field1 : std_logic;
field2 : std_logic;
field3 : std_logic;
end record;
signal sverilog_interface : sverilog_interface_t;
procedure show_bus(
signal sverilog_interface :inout sverilog_interface_t
) is
variable m :line;
begin
write(m, string'("task0"));
write(m, string'(" x0:")); write(m, sverilog_interface.field0);
write(m, string'(" x1:")); write(m, sverilog_interface.field1);
write(m, string'(" x2:")); write(m, sverilog_interface.field2);
write(m, string'(" x3:")); write(m, sverilog_interface.field3);
writeline(output, m);
end procedure;
procedure task0(
signal sverilog_interface :inout sverilog_interface_t
) is
begin
sverilog_interface.field0 <= '0';
sverilog_interface.field1 <= '1';
wait for 1 ns;
end procedure;
procedure task1(
signal sverilog_interface :inout sverilog_interface_t
) is
begin
sverilog_interface.field0 <= '1';
sverilog_interface.field1 <= '0';
wait for 1 ns;
end procedure;
begin
dut1: entity work.dut(beh)
port map(
i1 => sverilog_interface.field0,
i2 => sverilog_interface.field1,
o1 => sverilog_interface.field2, -- WHy 'U'? should be '0' or '1?
o2 => sverilog_interface.field3 -- WHy 'U'? should be '0' or '1?
);
process begin
wait for 1 ns;
show_bus(sverilog_interface);
task0(sverilog_interface);
show_bus(sverilog_interface);
task1(sverilog_interface);
show_bus(sverilog_interface);
report "end of testcase" severity failure;
end process;
end architecture;
F:\Xilinx\Vivado\2021.2\bin\xvhdl.bat --incr --relax --2008 -f test1.vhd
F:\Xilinx\Vivado\2021.2\bin\xelab.bat testbench -snapshot simout -incr -debug all
F:\Xilinx\Vivado\2021.2\bin\xsim.bat simout --tclbatch simout.sim.tcl --onerror quit --onfinish quit --ieeewarnings
****** xsim v2021.2 (64-bit)
**** SW Build 3367213 on Tue Oct 19 02:48:09 MDT 2021
**** IP Build 3369179 on Thu Oct 21 08:25:16 MDT 2021
** Copyright 1986-2021 Xilinx, Inc. All Rights Reserved.
## run all
task0 x0:U x1:U x2:U x3:U
task0 x0:0 x1:1 x2:U x3:U <-- WHy are x1 and x2 'U'?
task0 x0:1 x1:0 x2:U x3:U <-- WHy are x1 and x2 'U'?
Failure: end of testcase
Time: 3 ns Iteration: 0 Process: /testbench/line__88 File: test1.vhd
$finish called at time : 3 ns : File "test1.vhd" Line 99
exit 0
INFO: [Common 17-206] Exiting xsim at Tue Feb 15 16:02:17 2022...
code:(0)
ok
There are 2 drivers for the fields of your sverilog_interface: the DUT and the testbench process.
The DUT drives only the two last fields (because the mode of the others is in), to '1' and '0', respectively.
The process drives all fields because the sverilog_interface signal is associated with the inout interface declaration of your 3 procedure calls. LRM 4.2.2.3 Signal parameters:
A process statement contains a driver for each actual signal associated with a formal signal parameter of mode out or inout in a subprogram call.
The four fields are first driven to 'U', the leftmost value of the std_logic enumerated type, which is used as a default value for uninitialized std_logic signals. The two first fields are later driven to '0' or '1' values. But not the two last fields that are still driven to 'U'.
The resolution function attached to the std_logic type resolves the conflict between the DUT ('0' and '1') and the process ('U' and 'U') as 'U'.
One solution could be to explicitly drive the two last fields to 'Z' (high impedance) in your process:
process begin
sverilog_interface.field2 <= 'Z';
sverilog_interface.field3 <= 'Z';
wait for 1 ns;
...
Value 'Z', when in conflict with anything (except '-'), resolves as the anything. Or to do this in your procedures. Or, as some do (see OSVVM), to define your own resolution function and your own resolved subtype of std_ulogic such that 'U' and anything else resolves as the anything else.
Note: your show_bus procedure does not need mode inout, better use in. And your task0, task1 procedure do not need mode inout, better use out (principle of least privilege). But these modifications alone will not solve your problem: the process is still driving the 4 fields of the sverilog_interface signal.
Note: as noted by #user16145658 another solution would be to modify the default value of sverilog_interface at declaration:
signal sverilog_interface : sverilog_interface_t := ('U', 'U', 'Z', 'Z');
The process would then drive the 2 last fields to 'Z'.
This is a follow up to what Renard posted.
If you want to have some fun and stress test your simulator, you can define sverilog_interface_t as follows:
type sverilog_interface_t is record
field0 : maximum std_ulogic;
field1 : maximum std_ulogic;
field2 : maximum std_ulogic;
field3 : maximum std_ulogic;
end record;
What this does is use the function maximum [std_ulogic_vector return std_ulogic] as a resolution function. Resolution functions can be applied any place there the syntax calls for a subtype_indication. In non-LRM terms, this is also any place where you can put an array constraint on a type.
I caution that many vendors were not expecting maximum to be used as a resolution function, so where I use this technique in OSVVM, I unfortunately use a wrapper function named resolved_max to call maximum. Note that the wrapper function is strictly to maximize tool support without having to have code variations. Maximum was introduced in 2008, so it is past time for simulators to support this.

VHDL - Register for Push Button

I'm trying to create a simple push button in VHDL that turns on after an input switch or pb goes from 0 to 1 to 0 using a clock and a process. However, my code seems to be giving me undefined output. Here's what I have so far.
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
Entity captureInput is port
(
CLK : in std_logic := '0';
RESET_n : in std_logic := '0';
buttonState : in std_logic := '0';
buttonOut : out std_logic := '0'
);
end Entity;
ARCHITECTURE one of captureInput is
signal lastButtonState: std_logic := '0';
signal btnState : std_logic := '0';
BEGIN
process (CLK, RESET_n) is
begin
if (RESET_n = '0') then
lastButtonState <= '0';
elsif (rising_edge(CLK)) then
if (buttonState ='0' and lastButtonState = '1') then
btnState <= '1';
end if;
lastButtonState <= buttonState;
end if;
end process;
buttonOut <= btnState
end;
Try to initialize your btnState in the reset branch of your register and also have an else statement where you set your btnState back to 0, under some condition. I would bet that your undefined output comes from the fact that you do not define your btnState anywhere else outside your if conditions. It's good practice to not rely on the initial value of your declaration: Synthesis tools ignore it and some simulators will as well. Also, remember that the clocked body of the if will generate a register for every signal that gets assigned a value inside it, and that signals will keep the last value assigned to them inside a process.
You are also missing the Library ieee; statement at the top and a semicolon after buttonOut <= btnState.
Reading a button do need a debouncer.
Please take a look at:
VHDLWhiz generate statement
or
VHDLWhiz How to read a button in VHDL
Even though I see that you have already accepted Dimitris' answer, I can add that your code is almost right, you just need to toggle on the falling edge of of the latch instead of setting it to '1' as you do.
Try
if(rising_edge(CLK)) then
lastButtonState <= buttonState;
if(buttonState='0' and lastButtonState='1') then
btnState <= not btnState;
end if;
end if;
buttonOut <= btnState -- etc...
You don't need to initialize anything to '0' but you DEFINITELY need a switch debouncer as lukipedio said otherwise your toggle will not be consistent.
If you think about it, what you're doing is putting a "clock divider" on your lastButtonState register by toggling in order to set the btnState register at half the "frequency" of lastButtonState, which is what you want.
BTW, if you switch your toggling condition to
(buttonState='1' and lastButtonState='0')
then it will toggle on the rising edge of lastButtonState, in other words it will be toggle-on-press instead of toggle-on-release.

i don't understand the utility of default values in state machine

I am trying to understand state machine in VHDL for detecting the edge on a signal in VHDL. in next state I dont understand why we put the:
"next_etat<= reg_etat" because I think it could work without any problem even without it .
I'd would what are the default value of reg_etat and next_etat when we have just run the program because their is no real default value like in c for example int var=0;
entity machine_etat is
Port ( clk : in STD_LOGIC;
rst : in STD_LOGIC;
entree : in STD_LOGIC;
tc : out STD_LOGIC);
end machine_etat;
architecture architecture_machine_etat of machine_etat is
type T_etat is (idle,edge,one);
signal next_etat, reg_etat : T_etat;
begin
registre_etat: process(clk)
begin
if rising_edge(clk) then
if rst = ’1’ then
reg_etat <= idle;
else
reg_etat <= next_etat;
end if;
end if;
end process registre_etat;
tc <= ’1’ when reg_etat = edge else ’0’;
etat_suivant: process(reg_etat,entree)
begin
next_etat <= reg_etat;-- defaults values here i dont see their purpose
case reg_etat is
when idle =>
if entree =’1’ then
next_etat <= edge;
end if;
when edge =>
next_etat <= one;
when one =>
if entree =’0’ then
next_etat <= idle;
end if;
end case;
end process etat_suivant;
end architecture_machine_etat;
If you don't assign next_etat (pardon my French) in all situations, logical synthesis will infer a latch to remember it's state. A latch is something you don't want, as it is very sensitive to digital logic latencies and might become metastable: also something you don't want.
HDL programming significantly differs from CPU programming.

VHDL, if statements, and process names

I've got two processes that handle the inputs and output of a single LVDS receiver on a design for an FPGA. Now I need these same two processes concurrently repeated 8 times (for 8 separate LVDS receivers) with slightly different signal names (i.e. sigout1 vs. sigout0). Is there any way I can accomplish this with a for loop? Here are my two processes:
IBUFDS_inst : IBUFDS
generic map (DIFF_TERM => FALSE,
IBUF_LOW_PWR => FALSE,
IOSTANDARD => "DEFAULT")
port map (O => lvds_internal,
I => sigin0_p,
IB => sigin0_n);
lvdsFlop:PROCESS(clk)
BEGIN
IF (clk = '1' AND clk'EVENT) THEN
IF (reset_l = '0') THEN
sigout0 <= '0';
ELSE
sigout0 <= lvds_internal;
END IF;
END IF;
END PROCESS;
I was hoping to use a for loop in the following way:
FOR i IN 0 TO 7 LOOP
--Do the two processes, with signal names dependent on i:
--sigout0 first iteration, sigout1 next iteration, etc for all
--signals.
END LOOP;
If possible I'd like to have each of the processes name depend on i too (for simulation purposes) So I'd have IBUFDS_inst0, IBUFDS_inst1, etc. However, the above implementation does not pass a syntax check.
Edit: Thanks for the help guys, here is my updated VHDL:
--Instantiate LVDS receivers and LVCMOS output for each channel
GEN_LVDS: FOR i IN sigout'RANGE GENERATE
BEGIN
--Input LVDS buffer
IBUFDS_inst : IBUFDS
generic map (DIFF_TERM => FALSE,
IBUF_LOW_PWR => FALSE,
IOSTANDARD => "DEFAULT")
port map (O => lvds_internal(i),
I => sigin_p(i),
IB => sigin_n(i));
END GENERATE GEN_LVDS;
--LVCMOS output flip-flop
lvds_Flop:PROCESS(clk_fast)
BEGIN
IF (clk_fast = '1' AND clk_fast'EVENT) THEN
IF (reset_l = '0') THEN
sigout <= (others => '0');
ELSE
sigout <= lvds_internal;
END IF;
END IF;
END PROCESS lvds_Flop;
Have not tested in hardware yet but it simulates well.
IBUFDS_inst is a label, not a process name. You can't have it's name depends on i, but you can achieve what you want, and you will be able to distinguish between them.
To do that, sigout, sigin_p, sigin_n and lvds_internal must be std_logic_vector instead of std_logic. Here is a sample code:
entity lvds_test is
port map (
clk : in std_logic;
reset_l : in std_logic;
sigin_p : in std_logic_vector(7 downto 0);
sigin_n : in std_logic_vector(7 downto 0);
sigout : out std_logic_vector(7 downto 0)
);
end entity lvds_test;
architecture rtl of lvds_test is
signal lvds_internal : std_logic_vector(sigin_p'range);
begin
LVDS_GEN: for i in lvds_internal'range generate
IBUFDS_inst: IBUFDS
generic map (
DIFF_TERM => FALSE,
IBUF_LOW_PWR => FALSE,
IOSTANDARD => "DEFAULT"
) port map (
O => lvds_internal(i),
I => sigin_p(i),
IB => sigin_n(i)
);
end generate LVDS_GEN;
lvdsFlop: process(clk)
begin
if rising_edge(clk) then
if reset_l = '0' then
sigout <= (others => '0');
else
sigout <= lvds_internal;
end if;
end if;
end process lvdsFlop;
end architecture rtl;
You need to use a generate statement:
gen : for i in 0 to 7 generate
[Optional: local signals]
begin
[...]
my : process(...)
begin
[...]
end process;
end generate;
The full name of the process is now gen[i].my. Additionally, you should use vectors for your signals, so you can address them by index.

VHDL 'generate' FSM states

I have a variable number of modules linked to another module via a signal bus : std_logic_vector(NUM-1 downto 0), with each component using 8 bits, so that:
bus(7 downto 0) = first module
bus(15 downto 8) = second module
As for creating the instances and doing the port mapping, that is easily done with a
INST: for i in 0 to NUM-1 generate
Inst_module port map ( bus => bus(i*8+7 downto i*8) );
end generate INST;
My question:
I would like to be able to interface with each module via a FSM (since it needs to do some other things too), so would like to be able to 'generate' the following code, rather than having to write out each state manually (Where signal empty : std_logic_vector(NUM-1 downto 0) is a status flag for each module)
type state_type is (st0_idle, st1_work0, st1_work1 --,etc.)
signal state : state_type;
begin
process(empty)
begin
if RESET = '1' then
--reset FSM
state <= st0_idle;
else
if CLK'event and CLK='1' then
case state is
when st0_idle =>
if empty(0) = '0' then
state <= st1_work0;
elsif empty(1) = '1' then
state <= st1_work1;
--etc.
end if;
when st1_work0 =>
bus(7 downto 0) <= SOMETHING;
state <= st0_idle;
when st1_work1 =>
bus(15 downto 8) <= SOMETHINGELSE;
state <= st0_idle;
--etc..
end if;
end if;
end process;
As you can see, there is a lot of repetition. But I can't simply put a for-generate inside the case, so what should I do?
One good way to make processes with state machines more readable is to merge common code into procedures defined within the process. For example:
process (empty) is
procedure assign_something (
index : natural;
something : std_logic_vector(7 downto 0)
next_state : state_type
) is
begin
bus(index*8+7 downto index*8) <= something;
state <= next_state;
end procedure;
begin
wait until rising_edge(clk);
case state is
when st0_idle => ...
when st1_work0 => assign_something(0, something, st0_idle);
when st1_work1 => assign_something(1, something_else, st0_idle);
-- ... etc ...
end case;
if reset = '1' then
state <= st0_idle;
end if;
end procedure;
Hopefully you get the idea. Depending on how regular the state machine structure is, you may also want to replace the enumerated state variables that correspond to each index with a simple count or index variable that you keep track of along with the named state.
That's all up to you, but however you do it, using procedures to factor out common code whenever you can will probably make your VHDL much easier to work with.
Applying this change would make the code look something like this:
architecture ...
type state_type is (st_idle, st_work);
signal state : state_type;
signal index : integer range 0 to NUM-1;
...
begin
...
process (empty) is
procedure assign_something (
index : natural;
something : std_logic_vector(7 downto 0)
next_state : state_type
) is
begin
bus(index*8+7 downto index*8) <= something;
state <= next_state;
end procedure;
begin
wait until rising_edge(clk);
case state is
when st_idle =>
for i in 0 to NUM-1 loop
if empty(i) = '1' then
index := i;
exit;
end if;
end loop;
when st_work => assign_something(index, something, st_idle);
end case;
if reset = '1' then
state <= st_idle;
end if;
end procedure;
Obviously this has to be changed to match exactly what you want to do ... =)

Resources