Design vision error OPT-1206 AFTER VHDL - vhdl

I am facing an problem in design vision like definition is:
"The register THRESHOLD is constant and will be removed"
Since I declared a signal and I initialized to some value to make it constant. I want these constant values for some comparison purposes ....what to DO next??
begin
P : PROCESS(CLK,RST)
VARIABLE THRESHOLD: signed(10 DOWNTO 0);
BEGIN
IF(RST='1')THEN -- RESET CONDITION
THRESHOLD:="00011111111";
ELSIF(RISING_EDGE(CLK))THEN
H1<=(SIGNED("000"&P2)+SIGNED("00"&P3(7 DOWNTO 0)&'0')+SIGNED("000"&P6))-(SIGNED("000"&P4)+SIGNED("00"&P7(7 DOWNTO 0)&'0')+SIGNED("000"&P8));
IF(H1>=THRESHOLD) THEN
MAG_DL<="11111111";
ELSE
IF H1(10)='0' THEN
MAG_DL<=H1(7)&H1(6)&H1(5)&H1(4)&H1(3)&H1(2)&H1(1)&H1(0);
ELSE
H2<=NOT (H1(10)&H1(9)&H1(8)&H1(7)&H1(6)&H1(5)&H1(4)&H1(3)&H1(2)&H1(1)&H1(0));
H2<=H2+("00000000001");
IF(H2 >="11111111") THEN
MAG_DL<="11111111";
ELSE
MAG_DL<=H2(7)&H2(6)&H2(5)&H2(4)&H2(3)&H2(2)&H2(1)&H2(0);
END IF;
END IF;

Variables are supposed to vary. Yours doesn't change, so the compiler notices that and very nicely optimises it for you - and lets you know.
Constants do not vary - the compiler won't even let you try and change them. So if you want a constant value, tell the compiler that's your intention:
constant THRESHOLD : signed (10 downto 0) := "some value";

Related

Prevent sharing of adder logic

Suppose the following VHDL component:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity adder is
port
(
iClk : in std_logic;
iDataA : in unsigned(7 downto 0);
iDataB : in unsigned(7 downto 0);
iDataC : in unsigned(7 downto 0);
oResultA : out unsigned(7 downto 0);
oResultB : out unsigned(7 downto 0)
);
end entity;
architecture behaviour of adder is
begin
process
begin
wait until rising_edge(iClk);
if iDataB /= 0 then
oResultA <= iDataA + iDataB;
else
oResultB <= iDataA + iDataC;
end if;
end process;
end behaviour;
As it can be seen it contains two additions. I expected that the synthesized logic would also contain two adders. Instead Quartus seems to think it’s a good idea to use only a single adder and mux the second input to it (see RTL below). In my opinion this does not make any sense. It saves no hardware resources because the mux requires the same number of logic elements as the adder would have required. Additionally the mux needs to wait until the if condition is evaluated, which results in worse timing.
I’ve had this happen with a much larger component and a large state machine, which lead to timing violations. How do I prevent this sort of “optimization”? I’ve set the optimization mode to “Performace (Aggressive – increases runtime and area)”, but it doesn’t seem to make a difference. The only thing which lead to the expected result was to introduce additional signals like so:
tmpA <= iDataA + iDataB;
tmpB <= iDataA + iDataC;
process
begin
wait until rising_edge(iClk);
if iDataB /= 0 then
oResultA <= tmpA;
else
oResultB <= tmpB;
end if;
end process;
Is there a better way to do this, as it makes the code really hard to read. I'm using Quartus 20.1 with a Max10 FPGA.
RTL view:
Check that an option (in Advanced Synthsizer Settings) called "Auto Resource Sharing" is off. Resource sharing enables a synthesiser to do this adder-sharing that you want not to do.
OR
Put your adders in a different layer of hierarchy (ie in a separate entity) and then set an attribute to prevent it being optimised called keep:
attribute keep: boolean;
attribute keep of my_adder0: label is true;
attribute keep of my_adder1: label is true;
where my_adder0 and my_adder1 are the labels of your adder instances.

Undefined signal in simulation

I am trying to verify a design written in VHDL using SystemVerilog's assertions. however I got a problem when I have a non defined signal'X'
Just for example here is a code of a Comparator:
entity FP_comparator_V2 is
port (
comp_in1 : in std_logic_vector(31 downto 0);
comp_in2 : in std_logic_vector(31 downto 0);
less : out std_logic;
equal : out std_logic;
greater : out std_logic
);
end FP_comparator_V2;
architecture behav of FP_comparator_V2 is
-- signal, component etc. declarations
begin
-- architecture body
process(comp_in1, comp_in2)
begin
if comp_in1 = comp_in2 then
equal <= '1';
less <= '0';
greater <= '0';
else
equal <= '0';
...
end if;
end process;
end behav;
and the assertions
property FP_Comparator_V2_1_1;
#(posedge `assertion_check_clk29M4912 or negedge `assertion_check_clk29M4912)
(fp_comp_intf.Comp_in1 === fp_comp_intf.Comp_in2) |-> (fp_comp_intf.equal);
endproperty
DS_3_4_69_1_1:
assert property(FP_Comparator_V2_1_1);
cover property(FP_Comparator_V2_1_1);
property FP_Comparator_V2_1_2;
#(posedge `assertion_check_clk29M4912 or negedge `assertion_check_clk29M4912)
(fp_comp_intf.Comp_in1 !== fp_comp_intf.Comp_in2) |-> (!fp_comp_intf.equal);
endproperty
DS_3_4_69_1_2:
assert property(FP_Comparator_V2_1_2);
cover property(FP_Comparator_V2_1_2);
When Comp_int1 and Comp_int2 have defined values the simulation works fine if one of them have a undefined value also works fine but when both signals have undefined value it gives error For example :
Comp_int1= 48xx_xxxx; Comp_int2=47xx_xxxx ==>Equal = 1
I suppose it compares bit by bit so Equal should be '0' Please if you know a book or a website explaining the behavior of signals after synthesis or the logic behind undefined signals I would be thankful if you put it in a comment
thank you
I would suggest eliminating undefined values for signals in the design first. You can do this by initializing values to those signals in all possible cases. This helps in eliminating the X-propagation in the design.

VHDL-2008 to_01 conversion

I am getting some unexpected behavior when using the to_01 conversion function in VHDL-2008. My expectation would be that vector bits that can clearly be interpreted as high or low are mapped to '1' and '0' respectively. The remaining vector bits should be converted to '0' bits.
However, with the code depicted below, I get the whole vector converted to all '0's.
Is this behavior correct? Or is this a bug in the simulator software (ALDEC Riviera-PRO)?
Is there any IEEE function that meets my expectations or do I have to write my own function to achieve that?
library ieee;
use ieee.std_logic_1164.all;
entity test_to_01 is
end entity test_to_01;
architecture rtl of test_to_01 is
signal s_test_in : std_logic_vector(8 downto 0) := "UX01ZWLH-";
signal s_test_out : std_logic_vector(8 downto 0);
begin
s_test_out <= to_01(s_test_in);
end architecture rtl;
The observed behavior is the correct behavior. A little history about this follows.
In 2008, we propagated all of the strength reduction operations to all std_logic family packages. For better or worse, the historical implementation of to_01 comes from numeric_std and was implemented exactly as it is now. The following is an older implementation I was able to find on the web:
function TO_01(S : SIGNED ; xmap : STD_LOGIC:= '0') return SIGNED is
variable RESULT: SIGNED(S'length-1 downto 0);
variable bad_element : boolean := FALSE;
alias xs : SIGNED(s'length-1 downto 0) is S;
begin
for i in RESULT'range loop
case xs(i) is
when '0' | 'L' => RESULT(i):='0';
when '1' | 'H' => RESULT(i):='1';
when others => bad_element := TRUE;
end case;
end loop;
if bad_element then
assert NO_WARNING
report "numeric_std.TO_01: Array Element not in {0,1,H,L}"
severity warning;
for i in RESULT'range loop
RESULT(i) := xmap; -- standard fixup
end loop;
end if;
return RESULT;
end TO_01;
One of the prime directives of the VHDL WG is to not break old code. In this case it looks like this objective put forward an implementation that perhaps is less desirable.
If you want something different, you can always put it forward for the next revision of the standard. It would have to have a different name. Note we are currently closing on VHDL-2018 now, so it would be the revision after that.
Note that IEEE P1076 WG is an individual based working group. This means experienced users, such as yourself, are participating. Typically the amount of work done in a standards revision is overwhelming. As a result, we always need more active participants. Particularly working on the packages. See eda-twiki.org and http://www.eda-twiki.org/cgi-bin/view.cgi/P1076/WebHome
I found a workaround:
s_test_out <= to_stdlogicvector(to_bitvector(s_test_in));

Will a VHDL compiler optimise this away or not?

If I have an operation like the one below that depends on a constant parameter will the compiler see that this if statement will always be the first case and therefore optimise it away or not?
entity Thing is
generic(
constant N : integer := 32;
constant M : integer := 24
);
...
architecture behaviour of Thing is
...
process(clk)
begin
if(rising_edge(clk)) then
...
if N > M then
-- do a thing
else
-- do a different thing
end if;
...
end if;
end process;
end behaviour;
In any synthesis tool that I have used, any constants (including generics) get propagated through the design in order to produce the simplest possible output. This is good for performance in general.

VHDL Parametric case

I've some problem with my synthesis tool. I'm writing a module and I'm tryng to make it parametric and scalable. In my design I've a FSM and some counters. The counters have a parametric width ( they are function of the width of the datapath ). The problem is that I'm using that counter to drive a case statements. The synthesizer gives me back this error :
2049990 ERROR - (VHDL-1544) array type case expression must be of a locally static subtype
I've also tried to use subtype, but it doesnt work. The declaration is :
constant LENGTH_COUNTER_WORD : integer := integer(ceil(log2(real(WIDTH_DATA/WIDTH_WORD))));
subtype type_counter_word is std_logic_vector( LENGTH_COUNTER_WORD - 1 downto 0);
signal counter_word : std_logic_vector( LENGTH_COUNTER_WORD - 1 downto 0);
The case :
case type_counter_word'(counter_word) is
when (others => '1') =>
do_stuff();
when others =>
do_other_stuff();
end case;
I cannot switch to VHDL-2008. I've read I can use variable, but I'd like to find a different solution, if it exists. I cannot imagine there isn't any way to give parameters to synthesizer before the synthesis.
This is fixed in VHDL-2008. You can only work around it in earlier standards by using cascaded if statements (with the attendant priority logic). Variables don't make a difference when determining if choices are locally static.
I'm not sure how complicated your do_stuff() and do_other_stuff() operations are, but if you are just doing simple signal assignments, you could look into the and_reduce() function in the ieee.std_logic_misc library.
As an example:
output <= '1' when and_reduce(type_counter_word'(counter_word)) = '1' else '0';
Otherwise, as Kevin's answer suggests, a process block using if statements might be your best option.
About the time of Kevin's good enough answer, I had written this to demonstrate:
library ieee;
use ieee.std_logic_1164.all;
use ieee.math_real.all;
entity counterword is
generic (
WIDTH_DATA: positive := 16;
WIDTH_WORD: positive := 8
);
end entity;
architecture foo of counterword is
constant LENGTH_COUNTER_WORD : integer :=
integer(ceil(log2(real(WIDTH_DATA/WIDTH_WORD))));
subtype type_counter_word is
std_logic_vector( LENGTH_COUNTER_WORD - 1 downto 0);
signal counter_word : std_logic_vector( LENGTH_COUNTER_WORD - 1 downto 0);
procedure do_stuff is
begin
end;
procedure do_other_stuff is
begin
end;
begin
UNLABELLED:
process (counter_word)
begin
-- case type_counter_word'(counter_word) is
-- when (others => '1') =>
-- do_stuff;
-- when others =>
-- do_other_stuff;
-- end case;
if counter_word = type_counter_word'(others => '1') then
do_stuff;
else
do_other_stuff;
end if;
end process;
end architecture;
Note because type_counter_word is a subtype you can provide the subtype constraints in a qualified expression for the aggregate:
if counter_word = type_counter_word'(others => '1') then
From IEEE Std 1076-2008:
9.3.5 Qualified expressions
A qualified expression is a basic operation (see 5.1) that is used to explicitly state the type, and possibly the subtype, of an operand that is an expression or an aggregate.
This example analyzes, elaborates and simulates while doing nothing in particular. It'll call the sequential procedure statement do_other_stuff, which does nothing.
(For do_stuff and do_other stuff, empty interface lists aren't allowed).

Resources