Quick VHDL question, I don't have access to Xilinx at the moment due to dead laptop, so can't test this.
I was wondering if it's possible to use variables and arithmetic in 'downto' statements, e.g:
proc: process (x)
begin
y <= z(x downto 0) & z(7 downto x);
end process;
Thanks.
Yes, for reference look this page. Arrays allow integer expressions as a definition of the endpoints of a range.
My guess is that it would synthesize to a large and ugly multiplexer instead of a simple shift register which is looks like you are trying to create.
Related
I am working in a TOP file of a project in VHDL. I have a problem-question concerning the port mapping.
Below, is a part of the code that I am trying to implement and afterwards the description of the context.
generate_microfib:
for i in 0 to 5 generate
fib: microfib
Port Map (
InL => SignalNumber(num(i)*2 + i), --Input Left
OutR => SignalNumber(num(i)*2 + i+1) --Output Right
);
end generate generate_microfib;
The code above creates multiple components of microfib. The microfib, has an input and an output port. What I want to do is connect the left input of the current created component with the right output of the previous created one.
My initial thought was to do it inside the port mapping, but VHDL doesn't give many options for calculations in the for..generate statement. So, I decided to do it in two steps. Meaning that, I first create the desired components and afterwards do the connections (by setting the desired signals equal).
So, my question is: Is it possible to do the connections in a function for example, by setting:
SignalNumber(i)=SignalNumber(i-1)?
I know that the '<=' operator is accepted and not the '=' but I want to show you that my goal is to make those two signals equal and not assign the value of the one to the other.
When I've done things like this, I've used an array-type signal to act as an intermediate placeholder. Then, within the generate loop, you can connect the ports to the indexed locations on the array signal.
So you could try something like this, using std_ulogic as an example port type:
architecture rtl of entity is:
constant N_DEVICES : integer := 5;
signal port_connector : std_ulogic vector(N_DEVICES downto 0);
begin
-- Concurrent statements
generate_microfib : for i in N_DEVICES-1 downto 0 generate
fib : microfib
port map (
InL => port_connector(i+1)
OutR => port_connector(i)
)
end generate generate_microfib;
-- Other stuff
end architecture rtl;
Then, port_connector(N_DEVICES) acts as the input to the chain, and port_connector(0) acts as the output from the chain.
This isn't a function, but it is (relatively) clean and avoids too much of a headache with the generate statement. Functions in VHDL, though, are meant to produce calculated values, not circuit connections, so I would recommend against trying for that anyhow.
How can I solve this problem?
reg variable is defined as:
signal reg:STD_LOGIC_VECTOR(7 downto 0):="00000001";
There is a problem with ror operation in the code below. The error message is:
Line 109: Syntax error near "ror".
Line 108: found '0' definitions of operator "=", cannot determine exact overloaded matching definition for "="
--
process(clk1,up_down,enable,reset)
begin
if up_down="1" then
reg ror 1;
end if;
end process;
Your problem is the the ror operator is not defined for std_logic_vector.
VHDL exhibits a behaviour of computer (and hardware description) languages called overloading. Overloading is where an operator, function or procedure is multiply defined for different types. The compiler looks at the combination of types when the operator (etc) is used (called the signature) and tries it match that with the various versions that have been declared. This only works if there is exactly one match. Any more and the code is ambiguous, because the compiler doesn't know which version to used. Any less and there is no version for the compiler to use. This is your problem - there is no version of the ror operator that uses std_logic_vector.
You have two solutions:
(i) RECOMMENDED : implement your rotate right behaviour manually using the concatenation operator and slicing:
if up_down="1" then
reg <= reg(0) & reg(7 downto 1);
end if;
(ii) NOT RECOMMENDED : convert your std_logic_vector to a different type that does have a version of the ror operator defined, eg unsigned. Why "not recommended"? Because I would not recommend using any the the following operators ever, because they can behave strangely (and their behaviour doesn't seem to be consistent across different EDA tools);
ror rol sla sra sll srl
By the way, this line would be wrong even if ror were defined for std_logic_vector:
reg ror 1;
You can't just say that any more than you could just say
reg + 1;
You need to assign the result of the operation in both cases to something. I have assumed you want to assign it to reg in both cases.
I have an assert in my VHDL code that validates generics passed through the entity of my component. The severity of the assert is set to FAILURE, because I want to quit the simulation if the generics are misused. When simulating with Active-HDL (really any version, but I've specifically used versions 12-14a), the assert is hit when the generics are misused and the simulation exits before doing anything else. When simulating with ModelSim DE (I've only tried 10.6c, 32-bit), however, the assert is not the first thing to be evaluated, and a different error appears for a signal assignment of different array lengths, related to the values of the generics (which is why the assert exists). Here is my MCVE:
example.vhd:
library ieee;
use ieee.std_logic_1164.all;
entity example is
generic
(
INPUT_LEN : integer := 4;
OUTPUT_LEN : integer := 5
);
port
(
my_input : in std_logic_vector(INPUT_LEN-1 downto 0);
my_output : out std_logic_vector(OUTPUT_LEN-1 downto 0)
);
end entity example;
architecture rtl of example is
begin
-- We want this evaluated first.
assert (INPUT_LEN = OUTPUT_LEN)
report "INPUT_LEN and OUTPUT_LEN must be equal!"
severity FAILURE;
-- This is actually what is evaluated first.
my_output <= my_input;
end architecture rtl;
As you can see, my_output and my_input are affected by the values of the generics, and I want the assert to happen first so that a helpful error message will be printed to the console, instead of the current Fatal: (vsim-3420) Array lengths do not match. Left is 32 (31 downto 0). Right is 8 (7 downto 0)..
I compile and simulate using the following two ModelSim commands:
vcom -work work example.vhd
vsim -c -lib work example
My question is, is there a directive for vsim that forces ModelSim to evaluate asserts first? Or more broadly, a command that will look for and evaluate asserts before doing anything else? It seems Active-HDL does it by default, but ModelSim doesn't... I've looked through the documentation for vsim and I've tried the -immedassert flag but that didn't change anything.
I'm also working with very old code that gets used in a lot of different places (and is obviously way more complex than my MCVE), so the best solution would not be to modify the source code.
Thanks for any help.
All concurrent statements are elaborated in process statements or process statements and block statements. The two concurrent statements, the signal assignment and assertion have no guaranteed execution order. Counting on implementation defined apparent ordering results in a non-portable design description.
The assertion can still be ordered. It's possible to get assertions during elaboration.
This can be demonstrated by adding (in this case) a function that returns a boolean as an initial value for an object that never happens to get used (and would be eliminated during synthesis):
library ieee;
use ieee.std_logic_1164.all;
entity example is
generic
(
INPUT_LEN : integer := 4;
OUTPUT_LEN : integer := 5
);
port
(
my_input : in std_logic_vector(INPUT_LEN-1 downto 0);
my_output : out std_logic_vector(OUTPUT_LEN-1 downto 0)
);
end entity example;
architecture rtl of example is
function is_it_safe return boolean is
begin
assert (INPUT_LEN = OUTPUT_LEN)
report "INPUT_LEN and OUTPUT_LEN must be equal!"
severity FAILURE;
return TRUE;
end function;
constant safe: boolean := is_it_safe;
begin
-- We want this evaluated first
assert (INPUT_LEN = OUTPUT_LEN)
report " ORIGINAL INPUT_LEN and OUTPUT_LEN must be equal!"
severity FAILURE;
-- This is actually what is evaluated first.
my_output <= my_input;
end architecture rtl;
The added default values for the generics allow the code to analyzed, elaborated and simulated stand alone (as a Minimal, Complete and Verifiable example).
The report message in the original assertion has been changed for easy identification in case any implementation doesn't include line numbers.
Because the two generics have different default values it's is guaranteed to cause an assertion:
ghdl -a example.vhdl
ghdl -e example
ghdl -r example
example.vhdl:20:9:#0ms:(assertion failure): INPUT_LEN and OUTPUT_LEN must be equal!
./example:error: assertion failed
./example:error: error during elaboration
Line 20 is in the function is_it_safe.
The ordering will hold for Modelsim because objects are elaborated before simulation initialization (where one error or the other occurs now). See IEEE Std 1076-2008 14.4 Elaboration of a declaration, 14.4.2.5 Object declarations and 14.7 Execution of a model, 14.7.5.2 Initialization.
The idea here is to establish an ordered single execution of an assertion that was originally a concurrent statement (which is elaborated into a process with no sensitivity list and a final wait statement with no clauses, See 11.5 Concurrent assertion statements).
Note no answer so far answers the narrow question on how to affect process execution order in Modelsim.
It should not be possible to order concurrent statement execution. The order of the list of all processes executed until they suspend at the beginning of simulation (14.7.5.2) would be implementation defined and non-portable. That's already been demonstrated by the Original Poster.
Moving the assertion or providing a new copy in a function used during elaboration can guaranteed the assertion statement is executed before any assignment statement during initialization.
Also note the idea of an assertion testing the equality of the values of two constants of the same type could be viewed as an anti-pattern somewhat as JHBonarius commented. A fix adopted from programming which has little to do with hardware description and only serves to produce a particular message in the face of a lack of standardized error messages.
VHDL will already catch the error in the original code albeit requiring VHDL or tool implementation familiarity.
With the assertion in a function providing an object value the concurrent assertion statement can be eliminated.
VHDL is a strongly typed language. I am not sure about the construct of Modelsim that let you run the assertions first.
All you can try is type cast the my_output <= my_input as my_output <= std_logic_vector(my_input) this will let Modelsim simulate your design but as soon as you try to RUN your design, it will throw an Error.
Without the type-casting, it won't let you even simulate your design.
You can realize sequential processing by putting it in a process. Example:
library ieee;
use ieee.std_logic_1164.all;
entity example is
generic (
INPUT_LEN : integer := 5;
OUTPUT_LEN : integer := 6);
port (
my_input : in std_logic_vector(INPUT_LEN-1 downto 0);
my_output : out std_logic_vector(OUTPUT_LEN-1 downto 0));
end entity;
architecture rtl of example is
begin
assign_my_output: process(my_input) begin
assert (INPUT_LEN = OUTPUT_LEN)
report "INPUT_LEN and OUTPUT_LEN must be equal!"
severity FAILURE;
my_output <= my_input;
end process;
end architecture rtl;
vcom -work work example.vhd
vsim work.example
run 1 ns
# ** Failure: INPUT_LEN and OUTPUT_LEN must be equal!
I am trying convert two std_logic bits to an integer as follows
LIBRARY IEEE;
USE IEEE.std_logic_1164.ALL;
USE IEEE.numeric_std.ALL;
ENTITY TEST IS
PORT (sw1, sw0 : IN std_logic;
x : OUT integer RANGE 3 DOWNTO 0);
END ENTITY TEST;
ARCHITECTURE dflow OF TEST IS
SIGNAL mes_sel : integer RANGE 3 DOWNTO 0;
BEGIN
mes_sel <= to_integer(unsigned(std_logic_vector(SW1 & SW0)));
x <= mes_sel;
END ARCHITECTURE dflow;
but the compiler does not like the mes_sel assignment. I get the following compiler error message:
Error (10327): VHDL error at Q4.vhd(92): can't determine definition of operator ""&"" -- found 4 possible definitions
Can I not concatenate 2 bit of std_logic to a vector and then convert? Or is it something else?
regards
D
The error message tells you roughly what's wrong, and it's not a problem with the assignment.
GHDL gives a better diagnosis:
ghdl -a test.vhd
test.vhd:13:57: can't resolve overload for operator "&"
test.vhd:13:57: possible interpretations are:
../../src/ieee/numeric_std.v93:66:18: array type "signed"
../../src/ieee/numeric_std.v93:65:20: array type "unsigned"
../../src/ieee/std_logic_1164.v93:69:30: array type "std_logic_vector"
../../src/ieee/std_logic_1164.v93:54:31: array type "std_ulogic_vector"
ghdl: compilation error
VHDL allows overloaded operators, distinguishable by the types of their arguments (in this case, std_logic) and their return types, (in this case ... well... what?)
There are apparently 4 types which have a std_logic_vector() type conversion function declared on them, as well as a & operator taking two std_logic arguments; and ghdl (unlike whatever tool you're using) helpfully lists them.
In such cases, VHDL (unlike some other languages) insists that you pick one, rather than arbitrarily making a hidden (and possibly wrong) choice for you.
You can do this with a type mark. As you actually want an unsigned, the obvious choice is unsigned'() (note the "'" symbol, also used for attributes).
mes_sel <= to_integer(unsigned'(SW1 & SW0));
Note that if VHDL allowed anything simpler, like to_integer(SW1 & SW0) it would be positively dangerous as there is nothing to distinguish between signed and unsigned conversions, making the conversion at least non-obvious, and quite possibly wrong.
I'm trying to simulate the following code :
entity schal is port ( SW : in bit_vector(7 downto 0);
LED : out bit_vector(7 downto 0));
end schal;
architecture BEHAVIOUR of schal is
begin
INOUT_PROS : process (SW)
begin
LED <= SW;
end process INOUT_PROS;
end BEHAVIOUR;
I wrote this do file
vsim work.schal
restart
view wave
radix hex
add wave -height 25 -radix default sim:/schal/*
force SW 01000001
run 20ns
force SW 01000000
run 20ns
here is what I get :
as you can see the simulation affect only the first bit but not the whole vector ?
any idea how should I adjust the do file to get the right simulation ?
I think your force command is not using the correct syntax. You are trying to force a binary value, but the correct way to do this would be force SW 2#01000001, with the 2# specifying a binary value.
In ModelSim, go to Help > Documentation > PDF Bookcase, then open the 'Command Reference Manual'. This contains documentation on all commands, including force.
This is a Read-The-Fine-Manual moment. See the <value> argument description under the force command Arguments section in the Command Reference Manual.
A one-dimensional array of character enumeration can be forced as a sequence of character literals or as a based number with a radix of 2, 8, 10 or 16. For example, the following values are equivalent for a signal of type bit_vector (0 to 3):
You could note that IEEE Std 1076-2008 15.5.3 Based literals tells us:
A based literal is an abstract literal expressed in a form that specifies the base explicitly. The base shall be at least two and at most sixteen.
There are VHDL standard compliant based literals that can't be expressed with the force command.
Also notice the question's use of
force SW 01000001
is compatible with the sequence of character literals example in the Command Reference Manual. See the following NOTE:
For based numbers in VHDL, ModelSim translates each 1 or 0 to the appropriate value for the number’s enumerated type. The translation is controlled by the translation table in the pref.tcl file. If ModelSim cannot find a translation for 0 or 1, it uses the left bound of the signal type (type’left) for that value.
Also note from the question's value and waveform that the right most position of SWs enumeration translates properly. This suggests that the behavior doesn't match the force command <value> description.
In VHDL terms you're being force to use a bit string literal as demonstrated in scary_jeff's answer and not a string literal for providing the value. (Both sans quotation marks).
The character literal sequence is correct according to the example but does not translate correctly. You could wonder if quotation marks would help - how would otherwise force a string type object's value containing a leading space?
As an early MTI Modelsim user the simulator originally only supported VHDL. The problem is either the simulator or the example.
And of course there's the use of a VHDL test bench instead of embedding simulation sequence in a do file.
This method would be portable between VHDL simulators:
entity schal_tb is
end entity;
architecture foo of schal_tb is
signal SW: bit_vector(7 downto 0);
signal LED: bit_vector(7 downto 0);
begin
DUT:
entity work.schal
port map (
SW => SW,
LED => LED
);
STIMULUS:
process
begin
SW <= "01000001";
wait for 20 ns;
SW <= "01000000";
wait for 20 ns;
wait for 60 ns; -- to show 100 ns on waveform
wait; -- suspends process permenently
end process;
end architecture;
And gives:
There are also online VHDL Testbench outline generators such as the Doulos VHDL Testbench generator or this Online VHDL Testbench Template Generator.