VHDL, if statements, and process names - vhdl

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.

Related

'Opt_Design Error' in Vivado when trying Run Implementation

Trying to make a UART Transmitter to send a data from FPGA to PC; 9600 baudrate, 8-bits, no parity, 1 start & stop bit; I wrote a code with VHDL, run synthesis and simulate it in a way I like it to be. I wanted to see it with BASYS 3 FPGA, After created constraints, Run Implementation issued an error in which its called "Opt_Design Error".
library ieee;
use ieee.std_logic_1164.all;
entity rs232_omo is
generic(clk_max:integer:=10400); --for baudrate
port(
clk : in std_logic;
rst : in std_logic;
start : in std_logic;
input : in std_logic_vector(7 downto 0);
done : out std_logic;
output : out std_logic;
showstates: out std_logic_vector(3 downto 0)
);
end entity;
architecture dataflow of rs232_omo is
type states is (idle_state,start_state,send_state,stop_state);
signal present_state,next_state : states;
signal data,data_next : std_logic;
begin
process(clk,rst)
variable count : integer range 0 to clk_max;
variable index : integer range 0 to 10;
begin
if rst='1' then
present_state<=idle_state;
count:=0;
data<='1';
done<='0';
elsif rising_edge(clk) then
present_state<=next_state;
count:=count+1;
index:=index+1;
data<=data_next;
end if;
end process;
process(present_state,data,clk,rst,start)
variable count : integer range 0 to clk_max;
variable index : integer range 0 to 10;
begin
done<='0';
data_next<='1';
case present_state is
when idle_state =>
showstates<="1000";
data_next<='1';
if start='1' and rst='0' then
count:=count+1;
if count=clk_max then
next_state<=start_state;
count:=0;
end if;
end if;
when start_state =>
showstates<="0100";
data_next<='0';
count:=count+1;
if count=clk_max then
next_state<=send_state;
count:=0;
end if;
when send_state =>
showstates<="0010";
count:=count+1;
data_next<=input(index);
if count=clk_max then
if index=7 then
index:=0;
next_state<=stop_state;
else
index:=index+1;
end if;
count:=0;
end if;
when stop_state =>
showstates<="0001";
count:=count+1;
if count=clk_max then
next_state<=idle_state;
done<='1';
count:=0;
end if;
end case;
end process;
output<=data;
end architecture;
This's the error message in detail
"[DRC MDRV-1]Multiple Driver Nets:Net done_OBUF has multiple drivers:
done_OBUF_inst_i_1/O,and done_reg/Q"
"[Vivado_Tcl 4-78] Error(s) found during DRC. Opt_Design not run."
What would be the reason for this error?
You are assigning done both in the first and the second process, which is exactly what the implementation is complaining about, you cannot have multiple drivers.
Remove done<='0'; from the first process and it should complete the implementation.
(I didn't check if the rest of the code is doing exactly what you want.)

Turning on VHDL standard 2008 for Synopsys dc_shell analyzer

I get trouble to get my code that is a correct VHDL (2008 release of language) code correctly analyzed by dc_shell.
The case structure below that is valid 2008 generates an error
gen1: case myInt generate
when 0 =>
...
when 1 =>
...
when 2 =>
...
end generate;
I did not find in any part of the Synopsys design compiler documentation where it is described and if it supported or not.
Error:
106: gencfg: case nb_elem generate
^^^^
[Failure] Syntax error : received 'case'
while expecting 'postponed'
or '(' or 'assert' or 'block' or 'component'
or 'configuration' or 'entity' or 'for' or 'if'
or 'process' or 'with' or IDENTIFIER or STRING LITERAL
*** Presto compilation was unsuccessful. ***
VHDL Snippet is simple as that:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.math_real.all;
entity demo is
generic (
nbelem : positive range 1 to 6:= 6;
regwid : positive := 14
);
port (
data : in std_logic_vector(regwid-1 downto 0);
app_clk : in std_logic_vector(nbelem-1 downto 0);
clk_out : out std_logic
);
end demo;
architecture rtl of demo is
constant selwid : integer := integer(ceil(log2(real(nbelem))));
constant tied_up : std_logic := '1';
constant tied_low : std_logic := '0';
signal sel : std_logic_vector(selwid-1 downto 0);
begin -- architecture rtl
-- selectors mapping
-- NOTE: case style is vhdl08
gen0: block
begin
gencfg: case nbelem generate
when 5|6 =>
sel <= data(15 downto 13);
when 4|3 =>
sel <= data(12 downto 11);
when 2 =>
sel <= data(9 downto 9);
when 1 =>
sel <= (others => tied_low);
end generate gencfg;
end block gen0;
p0: process(all) is -- vhdl'08 syntax
variable sel_v : integer;
begin -- process p0_b
sel_v := to_integer(unsigned(sel));
if (sel_v < nbelem and sel_v > 0) then
clk_out <= app_clk(sel_v);
else
clk_out <= app_clk(0);
end if;
end process p0;
end architecture rtl;
In fact vhdl'08 is set by default so there is no specific option.
And there is already a case opened at Synopsys for that. But they do not provide any date for the support.
The work around is to get back to vhdl'87 syntax.

Is it possible to programmatically define a Hierarchical Name in VHDL 2008?

I have a rather large project, comprised of many modules integrated into one top-level component. I've created test-benches for these modules which make use of API packages (which I've created alongside them). I also have a top-level test-bench that tests the integrated system as a whole.
For one of the components, I'm interested in using VHDL-2008 Hierarchical Names within its MyModuleAPIPackage in order to access the internal signals from the top level testbench. Since I'm trying to write modular and re-usable code, I'd like to be able to instantiate the package so that it references the signals of the module within the component-level test (where the module is at the top level)
<<signal .MyComponent.MySignal : std_logic>>
and also within the top-level test (where there is an underlying structure)
<<signal .MySystem.MySubSystem.MyComponent.MySignal : std_logic>>
Perhaps this could be attainable through a combination of Hierarchical Names and generics?
Here is some (pseudo) code exemplifying what I'm trying to achieve.
MyModule.vhd
-- MyModule.vhd
entity MyModule is
port(
CLK : in std_logic;
RST : in std_logic;
DATA_IN : in std_logic_vector(7 downto 0);
DATA_OUT : out std_logic_vector(7 downto 0)
);
end entity MyModule;
architecture behavioral of MyModule is
-- Signal and constant definitions here.
begin
-- Describes how MyModule behaves.
end architecture behavioral;
----------------------
-- MyModule Test-Bench
----------------------
entity MyModule_tb is
end entity MyModule_tb;
architecture test of MyModule_tb is
-- Signal and constant definitions here
signal CLK, RST : std_logic := '0';
signal DATA_IN, DATA_OUT : std_logic_vector(7 downto 0) := (others = '0');
procedure DoComplexStuff(
InstructionCode : natural
)
is
begin
case InstructionCode is
when 0 =>
DATA_IN <= "01010101";
wait until CLK = '1';
DATA_IN <= "00110011";
wait until CLK = '1';
-- Lots of pretty complex stimuli
assert DATA_OUT = "00110011"
report "Output mismatch!"
severity failure;
when 1 =>
-- Lots of pretty complex stimuli
-- when ... =>
-- Plenty more instruction codes
others =>
null;
end procedure DoComplexStuff;
begin
CLK <= not CLK after 1 ms;
MainTestProc:
process
begin
for i in 0 to 99 loop
DoComplexStuff(i);
end loop;
end;
DUT: entity work.MyModule(behavioral)
port map(
CLK => CLK,
RST => RST,
DATA_IN => DATA_IN,
DATA_OUT => DATA_OUT
);
end architecture test;
I wish for procedure DoComplexStuff to be available at the top-level.
MyModuleApi.vhd
package MyModuleAPI is
generic(
-- Programatically defined aliases
PATH : path;
)
alias CLK is <<signal PATH.CLK : std_logic);
alias RST is <<signal PATH.RST : std_logic);
alias DATA_IN is <<signal PATH.DATA_IN : std_logic_vector(7 downto 0));
alias DATA_OUTis <<signal PATH.DATA_OUT : std_logic_vector(7 downto 0));
procedure DoComplexStuff(
InstructionCode : in natural
);
end package;
package body MyModuleAPI is
-- I can now include this package within MyModule_tb and
-- MyTopLevelComponent_tb and call DoComplexStuff to interact with the signals
-- from MyModule
procedure DoComplexStuff(
InstructionCode : natural
)
is
begin
case InstructionCode is
when 0 =>
DATA_IN <= "01010101";
wait until CLK = '1';
DATA_IN <= "00110011";
wait until CLK = '1';
-- Lots of pretty complex stimuli
assert DATA_OUT = "00110011"
report "Output mismatch!"
severity failure;
when 1 =>
-- Lots of pretty complex stimuli
-- when ... =>
-- Plenty more instruction codes
others =>
null;
end procedure DoComplexStuff;
end package body MyModuleAPI;
Therefore, MyModule_tb would include the package MyModuleAPI with a parameter specifying itself as the top level component and MyTopLevel_tb would include the same package with a parameter properly specifying the path to MyModule. (?)
NOTE: yes, my intention is to modify (bit-bang) internal signals during a top-level test. This would be similar to using ModelSim's "signal_force" and "signal_release" commands.
Thanks in advance for your guidance!

Record fields assigned from different processes

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.

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