I recently ran into a question regarding VHDL block and process structures and didn't find any explanation in text books or internet forums.
Is there any difference between the block and the process statements in the codes bellow?
library IEEE;
use IEEE.std_logic_1164.all;
entity example is
port ( a, b, clock : in std_logic;
c : out std_logic);
end entity;
architecture rtl of example is
begin
test_block : block (clock'event and clock = '1')
begin
c <= guarded a and b;
end block test;
end rtl;
and
library IEEE;
use IEEE.std_logic_1164.all;
entity example is
port ( a, b, clock : in std_logic;
c : out std_logic);
end entity;
architecture rtl of example is
begin
test_proc : process (clock)
begin
if (clock'event and clock = '1') then
c <= a and b;
end if;
end process test_proc;
end rtl;
The main difference is in the keyword guarded. If you write your code without it, whole logic would be regular combinational. So, I guess, if you want to write mostly concurrent code with some sequential logic, you can carefuly use block statement and when sequential needed use guarded. I've asked my colleagues who have huge background in FPGA design and they told that block is kinda anachronism, almost nobody use it, but it still in standard to give some choice for designers.
Related
I'm currently programming a system in VHDL, and I'm using an enumerator from another package called vnir, which is defined as such:
package vnir is
type row_type_t is (ROW_NONE, ROW_NIR, ROW_BLUE, ROW_RED);
end package vnir;
I've defined my architecture as such
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.vnir;
entity imaging_buffer is
port(
clock : in std_logic;
reset_n : in std_logic;
vnir_row_ready : in vnir.row_type_t
);
end entity imaging_buffer;
architecture rtl of imaging_buffer is
signal vnir_row_ready_i : vnir.row_type_t;
begin
vnir_pipeline : process (reset_n, clock) is
begin
if (reset_n = '0') then
vnir_row_ready_i <= vnir.ROW_NONE;
elsif rising_edge(clock) then
if (vnir_row_ready /= vnir.ROW_NONE) then
--do stuff
end if;
end if;
end process vnir_pipeline;
end architecture;
The internal signal vnir_row_ready_i can be assigned to no problem, however the relational operator doesn't seem to work as ModelSim throws this error when I try to compile:
# ** Error: C:/Users/nashg/Documents/iris_project/ex2_iris/vhdl/subsystems/sdram/Imaging Buffer/test.vhd(23): (vcom-1581) No feasible entries for infix operator '/='.
# ** Error: C:/Users/nashg/Documents/iris_project/ex2_iris/vhdl/subsystems/sdram/Imaging Buffer/test.vhd(23): Type error resolving infix expression "/=" as type std.STANDARD.BOOLEAN.
# ** Error: C:/Users/nashg/Documents/iris_project/ex2_iris/vhdl/subsystems/sdram/Imaging Buffer/test.vhd(28): VHDL Compiler exiting
My coworker helped me figure out how to make it work! I think that the /= operator is created in the vnir scope, but not ported over to the entity I'm working on. By writing :use work.vnir."/="; at the beginning of the file it compiles, so the full entity looks like so:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.vnir;
use work.vnir."/=";
entity imaging_buffer is
port(
clock : in std_logic;
reset_n : in std_logic;
vnir_row_ready : in vnir.row_type_t
);
end entity imaging_buffer;
architecture rtl of imaging_buffer is
signal vnir_row_ready_i : vnir.row_type_t;
begin
vnir_pipeline : process (reset_n, clock) is
begin
if (reset_n = '0') then
vnir_row_ready_i <= vnir.ROW_NONE;
elsif rising_edge(clock) then
if (vnir_row_ready /= vnir.ROW_NONE) then
--do stuff
end if;
end if;
end process vnir_pipeline;
end architecture;
Alternatively it did work by including use work.vnir.all; and taking out the vnir. before the types, but that wasn't possible with the project I'm working one
I expect the following code to simply generate two AND gates, but the gate of the procedure gets a latch at the output. In my original code, removing (commenting) the direct path gets rid of the latch, but I haven't been able to isolate this.
What causes this latch, and how can it be avoided?
Note that this is a purely combinatorial circuit without ifs and such generally associated with latch inference.
I am using Vivado 2018.3 on Linux Mint 19.
Edit 1: putting the direct path in a process statement gets rid of the latch.
Edit 2: the latch is no longer there after synthesis, so it can (probably) not cause problems. The question remains why it is generated in the first place.
library IEEE;
use IEEE.std_logic_1164.all;
entity mcve is
port (
a, b : in std_logic;
o : out std_logic_vector(1 downto 0)
);
end entity;
architecture rtl of mcve is
procedure and_proc (signal pa, pb : in std_logic; signal po : out std_logic) is
begin
po <= pa and pb;
end procedure;
begin
o(0) <= a and b;
and_proc(a, b, o(1));
end architecture;
I'd like to be able to continuously force a signal down in my testbench hierarchy. Here is a simple example illustrating how I've been doing this in my test benches.
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity double_inverter is
port(
a : in std_logic;
z : out std_logic
);
end double_inverter;
architecture x of double_inverter is
signal b : std_logic;
begin
b <= not a;
z <= not b;
end architecture x;
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity inverter_tb is
end inverter_tb;
architecture y of inverter_tb is
signal z : std_logic;
signal clk : std_logic := '0';
begin
clk <= not clk after 5 ns;
dut : entity work.double_inverter
port map(
a => '0',
z => z
);
continuous_stim : process(clk)
begin
<< signal dut.b : std_logic >> <= force clk;
end process;
end architecture y;
This works in Modelsim 10.4b i.e. signal b in the double_inverter instance will be set by clk and not signal a, but is there a better way to control external name signals?
Thanks for your help.
In some situations you can use is an alias to the external name:
alias dut_b is <<signal dut.b : std_logic >> ;
Since we think of signals being declared in an architecture, our instinct is to put the alias in the architecture. However, in this situation, it is not allowed because the DUT has not been elaborated yet.
You may be allowed to put it in the process - I would have to do some research to check if the language allows this. My concern is that processes do not allow signal declarations, so I am not confident that it will allow aliases to signals in a process - no harm in trying it and letting us know if it worked.
Generally when I am using something like this, I put it in a architecture declarative region of a component that creates the test cases and is instanced by the testbench. To avoid issues with elaboration order, I make sure to instance my DUT first in the testbench and typically the component that generates the test cases last (with the transaction based models in the middle) - VHDL elaborates designs in the order they are instantiated.
I have a problem with my vhdl code . In active-hdl it works perfectly , but when i tried to implement it on the FPGA board using ise design xilinx i have a problem with one component . The error i found is:
ERROR:Xst:827 - "E:/proiect_final/dispozitiv_impartitor/src/generator_square_wave.vhd" line 16: Signal numar_intermediar<0> cannot be synthesized, bad synchronous description. The description style you are using to describe a synchronous element (register, memory, etc.) is not supported in the current software release.
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
entity generator_square_wave is
port(clock,reset :in bit;
controler:std_logic_vector(2 downto 0);
numar:out std_logic_vector(7 downto 0);
data_clock:out bit);
end generator_square_wave ;
architecture descriere of generator_square_wave is
signal reset1:std_logic;
begin
process (clock,reset) -- here it shows me the error
variable numar_intermediar:bit_vector(3 downto 0 ):="0000";
variable numar_intermediar2:std_logic_vector(3 downto 0);
variable bitul:bit;
begin
reset1<=to_stdulogic(reset);
if rising_edge(reset1) then
numar_intermediar:="0001";
numar_intermediar2:=To_StdLogicVector(numar_intermediar);
numar(0)<=numar_intermediar2(0);
numar(1)<=numar_intermediar2(1);
numar(2)<=numar_intermediar2(2);
numar(3)<=numar_intermediar2(3);
numar(4)<='0';
numar(5)<='0';
numar(6)<='0';
numar(7)<='0';
else if( clock'event and clock ='1' and controler="001")then
bitul:=numar_intermediar(0);
numar_intermediar:=numar_intermediar srl 1;
numar_intermediar(3):=bitul;
numar_intermediar2:=To_StdLogicVector(numar_intermediar);
numar(0)<=numar_intermediar2(0);
numar(1)<=numar_intermediar2(1);
numar(2)<=numar_intermediar2(2);
numar(3)<=numar_intermediar2(3);
numar(4)<='0';
numar(5)<='0';
numar(6)<='0';
numar(7)<='0';
if(reset/='1' and controler/="001")then
numar<="00000000";
end if;
end if;
end if;
data_clock<=clock;
end process;
end descriere;
You have a few problems. First, you shouldn't be treating reset as a clock (i.e. using rising_edge()). If it's asynchronous, you should just write:
if reset1 = '1' then
...
The following line also has a problem (not sure if this is strictly illegal, but it's not recommended):
if( clock'event and clock ='1' and controler="001")then
This should be:
if clock'event and clock = '1' then
if controler = "001" then
(with additional end if to match.)
That should at least allow it to synthesize.
You may also want to make the statement reset1<=to_stdulogic(reset) concurrent instead of including it in the process, and there are a couple other possible changes you could make, but they're not as critical (unless I've missed something).
For a class, I was asked to write a VHDL procedure that takes two integer inputs A and B and replaces A with A+B and B with A-B. I wrote the following program and testbench. It completes implementation and the Behavioral Syntax check but it will not simulate. Although I get no errors, I do get some warnings stating that A and B are in combinational feedback loops. Can someone shed some light on what the problem may be?
Module:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity Problem2 is
Port ( A : inout integer;
B : inout integer);
end Problem2;
architecture Behavioral of Problem2 is
procedure AB (signal A,B: inout integer) is
begin
A<=A+B after 20 ns;
B<=A-B after 30 ns;
end AB;
begin
AB(A=>A, B=>B);
end Behavioral;
TestBench:
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
ENTITY Problem2_test IS
END Problem2_test;
ARCHITECTURE behavior OF Problem2_test IS
-- Component Declaration for the Unit Under Test (UUT)
COMPONENT Problem2
PORT(
A : INOUT integer;
B : INOUT integer
);
END COMPONENT;
--BiDirs
signal A : integer;
signal B : integer;
-- No clocks detected in port list. Replace <clock> below with
-- appropriate port name
BEGIN
-- Instantiate the Unit Under Test (UUT)
uut: Problem2 PORT MAP (
A => A,
B => B
);
ABproc: process is
begin
A<=25;
B<=22;
wait;
end process;
END;
The problem is:
Your component writes to it's own inputs. This is the equivalent of an infinite loop. The reason you've done this is because ....
The description of the problem doesn't make sense.
I was asked to write a VHDL procedure that takes two integer inputs A and B...
Fine
...and replaces A with...
What?!
You can't replace A (or B) because you'll get this problem. You could write a procedure that takes two integer inputs, and gives two integer outputs. Those outputs could then feed some registers which then feed the input, but there has to be a register there to break the combinatorial feedback loop.
Don't test it inside a the problem2 entity. Just call the procedure straight from your test bench.
(This code is not tested!)
ABproc: process is
begin
A<=25;
B<=22;
AB(A, B);
wait 1 ns;
assert A = 47;
assert B = 3;
wait; -- forever
end process;