Avoid duplicating code in VHDL - vhdl

I have a code listing that is full of code like the following, but larger chunks.
if (m = '00000') then
done <= '1';
else
done <= '0';
end if;
Is there any way of making this like a function of a c like #define so that I don't have to write the same code all over the place?

This code is not VHDL in the first place, so you have other things to worry about. (It's a bit more VHDL-like after the edit)
Thankfully VHDL has nothing like C's #define. Instead it has tools for proper abstractions such as packages (very roughly, C++ namespaces but done right), functions and procedures.
This allows you to write
done <= test_zero(m);
assuming done is a signal ( or done := test_zero(m); if it's a variable)
test_zero is then a function, something like
function test_zero ( word : in std_logic_vector) return std_logic is
begin
if word = (word'range => '0') then
return '1';
else
return '0';
end if;
end test_zero;
which (because it uses the "range" attribute) will work with different sizes of "m".
You will end up with a collection of useful functions : keep them in a package and use them throughout the project.
A package usually appears as two parts : the package specification (a bit like a C header file done right)
package my_tools is
function test_zero ( word : in std_logic_vector) return std_logic;
end my_tools;
and a package body containing the implementations
package body my_tools is
function test_zero ( word : in std_logic_vector) return std_logic is
...
end test_zero;
end my_tools;
To use it, it is compiled into a library (we'll use the default library "work" which is already declared by an implicit library work; in every VHDL file). Then you can choose either to make everything in the package visible in your code:
use work.my_tools.all;
Or make only one function visible:
use work.my_tools.test_zero;
Or make it obvious to anyone reading the code where the mysterious "test_zero" function came from:
done <= my_tools.test_zero(m);
If you have used C++ namespaces you will recognise these different strategies.
What makes the VHDL equivalent "namespaces done right" is that the VHDL compiler uses these declarations to track dependencies automatically and compile the right bits, instead of needing additional #includes and external tools like makefiles which must be kept in sync with the actual code by hand.

Related

VHDL Case choice is not locally static

This code works with some tools
Aldec Riviera Pro
but not others
GHDL ( ERROR choice must be locally static expression)
LIBRARY IEEE;
USE IEEE.std_logic_1164.ALL;
USE IEEE.numeric_std.ALL;
ENTITY INSTRUCTION_PROCESSOR IS
PORT (
clk : IN std_logic;
instruction : IN INTEGER
);
END ENTITY INSTRUCTION_PROCESSOR;
ARCHITECTURE behavioural OF INSTRUCTION_PROCESSOR IS
TYPE INSTRUCTION_t IS RECORD
instr : INTEGER;
cycles : INTEGER;
END RECORD;
CONSTANT CMD_A : INSTRUCTION_t := (instr => 0, cycles => 5);
CONSTANT CMD_B : INSTRUCTION_t := (instr => 1, cycles => 3);
BEGIN
PROCESSOR : PROCESS (clk)
VARIABLE loop_cycles : INTEGER := 0;
BEGIN
IF clk'event AND clk = '1' THEN
CASE instruction IS
WHEN CMD_A.instr =>
loop_cycles := CMD_A.cycles;
WHEN CMD_B.instr =>
loop_cycles := CMD_B.cycles;
WHEN OTHERS =>
NULL;
END CASE;
END IF;
END PROCESS;
END ARCHITECTURE;
https://www.edaplayground.com/x/jYD
since CMD_A and CMD_B are declared as constant records i would expect this to work...
any words of wisdom or is it just a bad idea?
I'm not sure the ghdl-0.35 version on EDA playground is up to handling --std=08 (-2008) for this issue without trying it. A recent ghdl-0.37-dev version shows it works:
ghdl -a --std=08 instruction_processor.vhdl
ghdl -e --std=08 tb
instruction_processor.vhdl:68:8:error: for default port binding of component instance "uut":
instruction_processor.vhdl:68:8:error: type of signal interface "instruction" declared at line 56:9
instruction_processor.vhdl:68:8:error: not compatible with type of port "instruction" declared at line 9:9
instruction_processor.vhdl:68:8:error: signal interface "cycles" has no association in entity "instruction_processor"
ghdl:error: compilation error
even if the testbench and/or entity header needs a bit of work. Both INSTRUCTION_PROCESSOR and TB are located in the same design file used above.
The IEEE Std 1076-2008 revision changed some definitions in 9.4.2 Locally static primaries
9.4.2 Locally static primaries
An expression is said to be locally static if and only if every operator in the expression denotes an implicitly defined operator or an operator defined in one of the packages STD_LOGIC_1164, NUMERIC_BIT, NUMERIC_STD, NUMERIC_BIT_UNSIGNED, or NUMERIC_STD_UNSIGNED in library IEEE, and if every primary in the expression is a locally static primary, where a locally static primary is defined to be one of the following:
...
m) A record aggregate in which all expressions in element associations are locally static expressions.
...
Prior to -2008 a an aggregate could not be locally static. An aggregate is an expression which is 'a formula that defines the computation of a value', previously always globally static for a constant declaration value expression.
Allowing certain expressions to be locally static comes from the VHDL-200x effort producing the -2008 revision (Fast Track Proposal FT-22). The idea is expressions with locally static primaries that produce values from basic or predefined operations including those found in IEEE library packages listed above are implemented as pure functions and are not dependent on elaboration. To avoid confusion a procedure call is a statement.
Analyzing your code with Aldec Riviera Pro used a -2008 compliant flag according to the EDA playground session from your comment:
Should an earlier revision of the standard be required due to tool chain constraints either the case statement can be replaced by an if statement or a concurrent conditional assignment statement which implies and if statement equivalent. A selected signal assignment statement on the other hand implies a case statement and conforms to the same semantics.
Try to put constraint into the integer.
instruction : IN INTEGER RANGE 0 TO ...;

verilog compiler error: near “;”: syntax error

timescale 1ns/10ps
/* resource counter for nor gates
*/
module global_vars;
integer count;
endmodule
module my_nor(y, a, b);
output y;
input a, b;
global_vars gv;
/* at instantiation increment the resources used */
gv =gv +1;
/* add 2ns inherent delay */
nor #2 nor1(y,a,b);
endmodule
When I compile, there is one syntax error at global_vars gv;
I have no idea. Should I initial the gv?
In verilog you can not just do this:
gv = gv +1;
wire types need to use assign:
wire gv;
assign gv = a + b;
reg types can use initial, always #* or always #(posedge clk).
always #* begin
gv = a + b;
end
Your trying to use an instance like a variable, I am not sure what your trying to do with your global_vars, may be make a global variable but creating an instance would make it local not global. Here you would do just as well to make gv an integer rather than an instance.
Note
Wire assignment and always #* are combinatorial, is there is no time delay in the assignment, therefor the value can not be directly referenced to itself. For example
gv = gv + 1;
Is a combinatorial loop, when do you expect the +1 to happen. This is normally solved by making gv a flip-flop and updating its value on a clock edge:
always #(posedge clk) begin
gv <= gv + 1;
end
In this case you still need to set an initial value for gv. for FPGAs this can be done using an initial or an async reset for ASIC.
FPGA using initial:
initial begin
gv = 'b0;
end
always #(posedge clk) begin
gv <= gv + 1;
end
Or for ASIC using reset:
always #(posedge clk or negedge rst_n) begin
if (~rst_n) begin
gv <= 'b0;
end
else begin
gv <= gv + 1;
end
end
It looks like you are trying to embed a reference to a global variable within a synthesizable module so that you can count how many times that module has been instantiated. As #Morgan has already pointed out, you can't reference a module instantiate as a variable. But there is an even more fundamental problem -- you are trying to mix behavioral code (i.e. global variables) into synthesizable code and that just doesn't work.
Creating a synthesized module is really a two step process -- design and then coding. In the design phase, you figure out what kind of logic you are trying to create. You don't need to go down to the gate level, but you should be able to sketch out the function with clouds of combinatorial logic, registers, FIFOs, memories etc. Once you've gained some familiarity with the language, this may strictly be a mental process rather than something committed to paper, but you still need to think about the logic you are creating. Then once you have designed your circuit, you actually go write the code to implement your design.
Global variables do not exist in hardware. You can make a counter that is accessible by multiple modules, but but it would need some sort of arbitration process. But what you're trying to do is create a run-time counter that counts up the number of modules instantiated, for which there is no hardware analog. You could use 'define statements to instantiate a variable number of modules and have a signal from each module which is defined as '1' if the module is instantiated and '0' if it isn't and then count the number of '1's, but that is self defeating since you already had to define a macro telling you the number of modules before you instantiated them! In which case, you might as well just use the macro value directly and dispense with all the extra signals.

VHDL - Conditional attribute declaration depending on a generic

How do I write a code segment which would evaluate a generic and create (or not create) an attribute accordingly?
Example :
if G_MY_GENERIC then
attribute my_attribute_typ : string;
attribute my_attribute_typ of signal_having_an_attr : signal is "value";
else
--nothing is created
end if;
It is perfectly possible to write something similar to that, but the attribute will only be visible in the scope of the generate statement.
g_something: if test_condition generate
attribute my_attribute_typ : string;
attribute an_attribute of my_attribute_typ: signal is "value";
begin
-- attribute is visible in this scope
p_my_process: process(clk)
begin
-- attribute is also visible here
end process;
end generate;
-- but not here
Instead you have to use something like the following to conditionally set an attribute (cumbersome, but achieves the result):
signal asvRam : svRam_at(0 to gc_nFifoDepth-1) := (others => (others => '0'));
type svStr_at is array(boolean) of string(0 to 10);
constant c_svRamStyle : svStr_at := (false => " ", true => "distributed");
attribute ram_style : string;
attribute ram_style of asvRam : signal is c_svRamStyle(gc_bDistributedRam);
We talked more generalized conditional compilation in the IEEE VHDL Working Group. The debate was heated. Some wanted a compile time approach (similar to 'C') and some an elaboration time approach. Compile time approach works well in C because constants are also compile time objects, however, in VHDL, a compile time approach will not understand things in the VHDL environment, and hence, using a generic is not an option. OTOH, the compile time option would probably give you vendor name, tool type (simulator, synthesis, ...), ...
I have added your code as a requirement to the proposal page. It is at: http://www.eda.org/twiki/bin/view.cgi/P1076/ConditionalCompilation
If you are willing to share additional insight on your application, I would like to add that to the proposal also.
Basically: this is exactly how VHDL does not work. In VHDL you declare your intent to use specific bits of hardware, and then the synthesizer attempts to connect those bits of hardware. Any semblance of dynamically creating hardware like for ... generate loops are essentially just a semblance: syntactic sugar to take the pain away.
What you can do is conditionally assign to signals/variables:
process (sig1, sig2, enable) is
begin
if enable = '1'
then
out <= sig1;
else
out <= sig2;
end if;
end process;

Define "enum"-type depending on generics

I am writing a statemachine, which has a generic parameter, and some states existence depends on this. Since I have my states defined in something like an enum (don't know the vhdl term for it), I wonder if I can define this enum depending on the generic somewhat like so:
generic(x: bool); -- in the entity
....
architecture ...
if x then generate
type states_t is (State1, State2, State3ifX)
else
type states_t is (State1, State2)
end generate;
variable state : states_t;
begin
case state is
....
if x then generate
when State3ifX =>
...
end if;
end case
end architecture;
Do I have to carry the dead weight (logic for state3, danger to drop into it (does not matter in my case since I do not expect radiation), additional bit since ceil(ld(3))=2 > ld(2)=1), or is there a possibility to strip unnecessary state(s)?
(In my case there are several states that could be stripped, however seperate architectures are not worth while the effort)
you can define the "states"-type in a process that is optionally generated using a generic. see a reference example below:
entity blabla is
generic(sel: std_logic := '0');
port(
...
architecture Behavioral of blabla is
begin
q1: if sel='0' generate
p: process(clk)
type t_state is (s1, s2, s3);
variable state: t_state;
begin
if rising_edge(clk) then
...
end if;
end process;
end generate;
q2: if sel='1' generate
p: process(clk)
type t_state is (s1, s2);
variable state: t_state;
begin
if rising_edge(clk) then
...
end if;
end process;
end generate;
I can't think of a way to achieve what you need.
On the upside, your concern about having to "carry the dead weight (logic for state3, danger to drop into it)" is not something you need to worry about - the synthesizer will optimise the logic away, so the state register will only be as big as it needs to be for the states you can actually reach.
I know its an old tread but still a hit on google so Im adding how Im doing it
label: if x generate
declarations <- put types, signals & attribures here !!!!
begin
ur code
end generate label;
You might want to consider second architecture or even simpler just a different entity - just another vhd file with slightly different name (like _x1, then _x2)
I find "genercis system" not really practical in more advanced cases (to much bloat-code to write), and then u might use different synthezisers so two archoitecture with one entity might not work, generate with decalrations inside might not work.... I would create different vhd for that - it will work in all the cases)
Cheers

Why do we use functions in VHDL

Functions are obviously less verbose to write than entities. But it implies many drawbacks, including:
No generic keyword equivalent
Only one output possible
It appears that functions can be called recursively. May it not be the case with entities? If so, is there any good reason to use functions except for aesthetic purposes?
Functions can't create hardware directly - they have to exist within an architecture to do so. There's nothing to stop you putting all your functionality into a function (or procedure) and then just calling that within a process though.
Regarding some of your other points:
With procedures you can have multiple inout or out parameters.
Entities can recurse... Consider:
entity recurse is
generic (
depth : integer := 1;
param : integer := 3);
port (
a : in integer;
b : out integer);
end entity recurse;
architecture a1 of recurse is
signal c : integer;
begin
c <= a + 1;
bottom: if depth = param generate
b <= a + 1;
end generate bottom;
mid:if depth /= param generate
recurse_1: entity work.recurse
generic map (
param => param,
depth => depth+1)
port map (
a => c,
b => b);
end generate mid;
end architecture a1;
Not very useful, but it synthesises and simulates just fine.
And finally, of course you only use functions for aesthetic purposes (assuming you include maintainability and readability into the definition of aesthetic, which most programming types do in my experience). You only use enumerated types, entities, records and a whole host of other language features for 'aesthetic purposes'. Even assembly mnemonics are aesthetic! Maybe should return to toggling DIP switches :)
Functions in vhdl make the code easy to maintain and read. generally architectures are very big and while debugging if something is not working you can easily find the problematic function and correct it and no need to analyse the entire architecture body.
in case of small codes it's useless but in more big machines it makes you better understand if you consider it function wise.
There is no rule for this so all comments are welcome.
in short : the advantage of functions are
overloading
operators definition
overloading of operators therefore
Better Structure of code
I can see why you are confused, another good question would be why there's both procedure and function. (VHDL seems quite inelegant sometimes!)
That being said, I use both procedures and functions all the time, although mostly in testbenches. For example, for a testbench for a firewall system I made a while back I wrote a procedure called pd_tb_send_udp_packet() that I use repeatedly in the main process, e.g.,
pd_tb_send_udp_packet("10.10.10.2", 1234, false);
pd_tb_send_udp_packet("10.10.10.1", 1234, true);
pd_tb_send_udp_packet("10.10.10.1", 1235, false);
pd_tb_send_udp_packet("ff02:100::1", 1234, false);
pd_tb_send_udp_packet("ff02:101::1", 1234, true);
This procedure generates a random UDP packet with the given addr/port and sends it to the firewall system, then tests whether it is forwarded or not based on the final boolean parameter. Here are the first lines of it, where I use functions from a library:
if f_atvtb_is_ipv6_addr(dest_ip_addr) then
v_ipv6 := true;
v_ipv6_addr := f_atvtb_ipv6_addr(dest_ip_addr);
else
v_ipv6 := false;
v_ipv4_addr := f_atvtb_ip_addr(dest_ip_addr);
end if;
The latter two return 128 and 32 bit std_logic_vectors from the string input, respectively.
While I could probably do all this without using procedures and functions somehow, it would definitely be a lot more messy.

Resources