In my architecture I define a signal of some record type. Each of the record elements is driven in one process only.
The whole record signal is passed to procedures. The procedures will later be placed in a package. Passing the record as type "inout" leeds to all accessed record elements resolving to 'X'.
The code runs in Modelsim and is only for verification (no synthesis needed).
Driving the record elements directly works.
Minimal example; Architecture header:
-- Record type
type tr_Data is record
r1_A : std_logic;
r1_B : std_logic;
end record;
-- Signal definition and initialization
signal sr_Data : tr_Data := (
r1_A => '0',
r1_B => '1'
);
Architecture body:
-- This process only modifies sr_Data.r1_A
prcss_A: process
procedure proc_Modify_A(signal d: inout tr_Data) is
begin
d.r1_A <= not d.r1_A;
end procedure;
begin
wait for 1 us;
--sr_Data.r1_A <= not sr_Data.r1_A; -- This works
proc_Modify_A(sr_Data); -- This works not
wait for 1 us;
wait;
end process;
-- This process only modifies sr_Data.r1_B
prcss_B: process
procedure proc_Modify_B(signal d: inout tr_Data) is
begin
d.r1_B <= not d.r1_B;
end procedure;
begin
wait for 1.5 us;
--sr_Data.r1_B <= not sr_Data.r1_B; -- This works
proc_Modify_B(sr_Data); -- This works not
wait for 1 us;
wait;
end process;
This is the Result in Modelsim:

I'm not sure, if this is possible at all. Maybe there are also better solutions to my problem.
Thank's for the help!
This question demonstrates why providing a minimal, complete, and verifiable exampe is desirable for code errors (instead of snippets as here).
Creating a MCVe:
library ieee;
use ieee.std_logic_1164.all;
entity record_process is
end entity;
architecture foo of record_process is
type tr_Data is record
r1_A: std_logic;
r1_B: std_logic;
end record;
signal sr_Data: tr_Data := (r1_A => '0', r1_B => '1');
begin
prcss_A: -- This process only modifies sr_Data.r1_A
process
procedure proc_Modify_A(signal d: inout tr_Data) is
begin
d.r1_A <= not d.r1_A;
end procedure;
begin
wait for 1 us;
-- sr_Data.r1_A <= not sr_Data.r1_A; -- This works
proc_Modify_A(sr_Data); -- This works not
wait for 1 us;
wait;
end process;
prcss_B: -- This process only modifies sr_Data.r1_B
process
procedure proc_Modify_B(signal d: inout tr_Data) is
begin
d.r1_B <= not d.r1_B;
end procedure;
begin
wait for 1.5 us;
--sr_Data.r1_B <= not sr_Data.r1_B; -- This works
proc_Modify_B(sr_Data); -- This works not
wait for 1 us;
wait;
end process;
MONITOR:
process (sr_Data)
begin
report
LF & HT &
"sr_Data.r1_A = " & std_logic'image(sr_Data.r1_A) &
LF & HT &
"sr_Data.r1_B = " & std_logic'image(sr_Data.r1_B);
end process;
end architecture;
we see reported behavior that matches the OP's waveform:
record_process.vhdl:44:9:@0ms:(report note):
sr_Data.r1_A = '0'
sr_Data.r1_B = '1'
record_process.vhdl:44:9:@1us:(report note):
sr_Data.r1_A = 'X'
sr_Data.r1_B = '1'
record_process.vhdl:44:9:@1500ns:(report note):
sr_Data.r1_A = 'X'
sr_Data.r1_B = 'X'
The 'X's are caused by the way drivers are associated with subprogram actual parameters:
IEEE Std 1076-2008
4.2 Subprogram declarations
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. Similarly, a subprogram contains a driver for each formal signal parameter of mode out or inout declared in its subprogram specification.
For a signal parameter of mode inout or out, the driver of an actual signal is associated with the corresponding driver of the formal signal parameter at the start of each call. Thereafter, during the execution of the subprogram body, an assignment to the driver of a formal signal parameter is equivalent to an assignment to the driver of the actual signal.
10.7 Procedure call statement
For each formal parameter of a procedure, a procedure call shall specify exactly one corresponding actual parameter. This actual parameter is specified either explicitly, by an association element (other than the actual open) in the association list or, in the absence of such an association element, by a default expression (see 6.5.2).
There's a driver for the actual associated in whole, here a signal of a record type.
(This also tells you Tricky's answer is valid, which reduces the actual to an element of the whole.)
There's another possible solution
Drop the parameter list:
architecture fum of record_process is
type tr_Data is record
r1_A: std_logic;
r1_B: std_logic;
end record;
signal sr_Data: tr_Data := (r1_A => '0', r1_B => '1');
begin
prcss_A: -- This process only modifies sr_Data.r1_A
process
procedure proc_Modify_A is
begin
sr_Data.r1_A <= not sr_Data.r1_A;
end procedure;
begin
wait for 1 us;
-- sr_Data.r1_A <= not sr_Data.r1_A; -- This works
proc_Modify_A; -- This works not
wait for 1 us;
wait;
end process;
prcss_B: -- This process only modifies sr_Data.r1_B
process
procedure proc_Modify_B is
begin
sr_Data.r1_B <= not sr_Data.r1_B;
end procedure;
begin
wait for 1.5 us;
--sr_Data.r1_B <= not sr_Data.r1_B; -- This works
proc_Modify_B; -- This works not
wait for 1 us;
wait;
end process;
MONITOR:
process (sr_Data)
begin
report
LF & HT &
"sr_Data.r1_A = " & std_logic'image(sr_Data.r1_A) &
LF & HT &
"sr_Data.r1_B = " & std_logic'image(sr_Data.r1_B);
end process;
end architecture;
which produces:
record_process.vhdl:89:9:@0ms:(report note):
sr_Data.r1_A = '0'
sr_Data.r1_B = '1'
record_process.vhdl:89:9:@1us:(report note):
sr_Data.r1_A = '1'
sr_Data.r1_B = '1'
record_process.vhdl:89:9:@1500ns:(report note):
sr_Data.r1_A = '1'
sr_Data.r1_B = '0'
without any driver conflicts, lacking multiple drivers (14.7.2 Drivers) requiring resolution (14.7.3.4 Signal update) during simulation.
14.7.2 Drivers
Every signal assignment statement in a process statement defines a set of drivers for certain scalar signals. There is a single driver for a given scalar signal S in a process statement, provided that there is at least one signal assignment statement in that process statement and that the longest static prefix of the target signal of that signal assignment statement denotes S or denotes a composite signal of which S is a subelement. Each such signal assignment statement is said to be associated with that driver. Execution of a signal assignment statement affects only the associated driver(s).
The longest static prefix is defined in 8. Names:
8.1 General
A static signal name is a static name that denotes a signal. The longest static prefix of a signal name is the name itself, if the name is a static signal name; otherwise, it is the longest prefix of the name that is a static signal name. ...
where the longest static prefix now includes record elements as opposed to actual signals of a record type associated in whole.
This is possible because a subprogram is a sequence of statements (4.2 Subprogram bodies) and the procedures are declared within the scope of the declaration of sr_Data (12.1 Declarative region, 12.2 Scope of declarations, 12.3 Visibility).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With