Using Fixed point in VHDL - vhdl

In my filter design , I am using fixed point arithmetic and using sfixed for signals. The design synthesizes with all timing met but my functional simulation and post synth/P&R simulation do not match after arith logic blocks.. Giving a small ex below, where I see that crf_int_r does not match in Post synth simulation.. Can someone help me understand , whether it is not synthesized properly or some other issue for a mismatch between functional and post synth simulation..Using Xilinx ISE 14.7 and VHDL 200X option in ISE.
signal add_alpha1_r : sfixed(5 downto -13) ;
signal add_alpha2_r : sfixed(6 downto -13) ;
signal crf_r : sfixed(17 downto -13) ;
signal crf_int_r : sfixed(17 downto -7) ;
signal alpha_log : sfixed(4 downto -13) ;
signal imgdel_r_d4 : sfixed(4 downto -13) ;
signal imgsum_d2 : sfixed(4 downto -13) ;
add_alpha1_r <= imgdel_r_d4 - imgsum_d2 ; --19.13
add_alpha2_r <= alpha_log + add_alpha1_r ; -- 20.13
crf_r <= add_alpha2_r * beta ; -- 31.13
crf_int_r <= crf_r(17 downto -7);

You encountered a synthesis bug. Making a Minimal, Complete, and Verifiable example from the code presented in the comments, I have tried to synthesize this with ISE 14.7 and VHDL-200X option on:
library ieee;
use ieee.std_logic_1164.all;
library ieee_proposed;
use ieee_proposed.fixed_pkg.all;
entity sfixed_test is
port (alpha_log : out sfixed(4 downto -13));
end sfixed_test;
architecture rtl of sfixed_test is
constant alpha : sfixed(10 downto 0) := "00001111000"; -- 120
type rom_t is array(0 to 2047) of sfixed(4 downto -13);
constant alpha_rom : rom_t := (120 => "111111111111111111",
others => "000000000000000000");
begin -- rtl
alpha_log <= alpha_rom(to_integer(alpha));
end rtl;
XST reports the following warning:
Warning: "::fixed_pkg:TO_INTEGER (sfixed): metavalue detected, returning 0"
A quick look into the RTL or Technology Map Viewer shows, that all outputs were connected to ground instead of VCC as intended in my example.
The problem is the implementation of to_integer as described bewlow. You can work around this, if you change the reading from the ROM to:
alpha_log <= alpha_rom(to_integer(unsigned(std_logic_vector(alpha))));
and also include the package ieee.numeric_std. Then everything works fine.
Further notes: The warning message refers to line 5085 ff. of ieee_proposed/fixed_pkg_c.vhd shipped with ISE. It reads:
if (Is_X (arg)) then
assert NO_WARNING
report fixed_pkg'instance_name
& "TO_INTEGER (sfixed): metavalue detected, returning 0"
severity warning;
return 0;
end if;
Is_X(arg) checks whether the argument contains a U, X, Z, W, or -. It fails here if arg (which is alpha) is a constant. But, it works when alpha is a signal (input).

Related

GTKW Unable to block on application (GHDL macos)

I am able to successfully analyze and run a simple VHDL counter in GHDL on macos, but when launching GTKW, the use of a generic causes problems.
The error message is
Unable to block on application (GetProcessPID() returned 184467095516)
Any ideas what this means or what gives rise to this error? (Couldn't find anything Googling it)
It seems to be connected to this line
signal count: unsigned (G_NBITS-1 downto 0)
From this code segment
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity counter_simple is
generic(
G_NBITS : integer range 1 to 32 := 3
);
port(
clk : in std_logic;
reset_n : in std_logic;
--count_out : out std_logic_vector(G_NBITS-1 downto 0)
count_out : out std_logic_vector(2 downto 0)
);
end;
architecture rtl of counter_simple is
--signal count: unsigned (G_NBITS-1 downto 0)
-- ABOVE LINE CRASHES gtkwave
-- Unable to block on application (GetProcessPID() returned 184467095516)
-- so instead:
signal count: unsigned (2 downto 0);
begin
counting : process (clk, reset_n)
begin
if (reset_n = '0') then
count <= (others => '0');
elsif rising_edge(clk) then
count <= count +1;
end if;
end process;
--count_out <= std_logic_vector(count(G_NBITS-1 downto 0));
count_out <= std_logic_vector(count(2 downto 0));
end rtl;
Printing the counter with report, in a testbench (around this counter) is fine in both cases, i.e. in both cases the counter runs 0..7.
So the simulation runs but there appears to be something offensive in the .ghw file.
I haven't had much luck with answers here, but I did read-up on the .ghw file that is output by GHDL, and it is a custom format readable by GTKW.
I tried an alternative format, vcd, and that seems to be fine:
Instead of the default
ghdl -r counter_simple_tb --stop-time=10ns --wave=counter_simple.ghw
Use VCD
ghdl -r counter_simple_tb --stop-time=10ns --vcd=counter_simple.vcd
(Note: you have to use the --vcd switch. Filename extension alone is not enough)
As a workaround this will do.
Hopefully this helps others stuck on this too.
It's of course possible that all this has been fixed in the meantime, as the macos binary for GHDL (v 0.29, 32bit) is quite a few versions behind the latest (v 1.0)
$ ghdl -v
GHDL 0.29 (20100109) [Sokcho edition]
and I am running it on a 64bit machine.

Use of conv_integer in VHDL

I am in the process of trying to write some code that will simply just shift a 32 bit vector left or right, with a 5 bit input that will be used for the shift amount (shamt). The issue I am having is trying to convert an std_logic_vector to an integer. My code is this:
library ieee;
use ieee.STD_LOGIC_1164.all;
use ieee.STD_LOGIC_ARITH.all;
entity shiftlogical is
port(x : in std_logic_vector(31 downto 0);
shamt : in std_logic_vector( 4 downto 0);
y : out std_logic_vector(31 downto 0));
end shiftlogical;
architecture beh of shiftlogical is
signal shift : integer;
signal temp : std_logic_vector(31 downto 0);
begin
shift <= conv_integer(unsigned(shamt));
temp <= x(shift downto 0);
y <= temp;
end beh;
The code is not complete I know, but to test some ideas I am trying to pass "00010" (2) into shamt, but shift comes out to be -2147483648. But I cannot figure out why it is doing this, nor can I find any resources online that shows anything different than what I am doing. I greatly appreciate any help.
-2147483648 (-2**31) is the default initial value for integers, being the leftmost, most negative value in its range. It suggests that the signal assignment to shift has not executed. Most likely because it is a continuous assignment and there hasn't been an event on shamt to cause it to update.
std_logic_arith is not an IEEE standard library. You should use to_integer() from ieee.numeric_std instead. It is also beneficial to keep numeric ports as unsigned or signed so that your intent is clear and to minimize type conversions. Also, you cannot directly assign the variable length slice of x to temp since their lengths do not match. You should use resize() (from numeric_std) to extend the length back to 32-bits or rethink your approach.
I fixed the obvious typo in the entity name, started the simulation (ModelSim) and forced the signal shamt to "00010". Then just after trying to run for 1 ps, ModelSim complains about:
Fatal: (vsim-3420) Array lengths do not match. Left is 32 (31 downto 0). Right is 0 (-2147483648 downto 0 (null array)).
Time: 0 ps Iteration: 0 Process: /shiftlogical/line__16 File: shiftlogical.vhdl
Fatal error in Architecture beh at shiftlogical.vhdl line 16
That is because all your concurrent statements are executed in parallel. The new signal values are scheduled for the next delta cycle within the simulation. Thus, the line
temp <= x(shift downto 0);
is executed with the old value of shift which is the initial value of this signal. The initial value of an integer is -2**31 as also Kevin pointed out.
Of course you can initialize the signal shift, but the only value which will not result in an error will be 31 because in this asignment the signal on the left and the expression on the right must match in array (std_logic_vector) size. The signal shamt must be forced to "11111" as well, so that shift keeps 31.
You cannot easily fix this, because for a left shift you must add zeros at the right (LSB) and for a right shift zeros or the sign at the left (MSB).
#Martin Zabel what I had really tested there was to see if shift would hold an integer value which it did until I tried to pass it in for temp <= x(shift downto 0); What I realized was that the signal needed to really be a variable to work as intended and as follows my code consists of:
library ieee;
use ieee.STD_LOGIC_1164.all;
use ieee.STD_LOGIC_ARITH.all;
entity shiftlogical is
port(x: in std_logic_vector(31 downto 0);
shamt: in std_logic_vector(4 downto 0);
dir: in std_logic;
y: out std_logic_vector(31 downto 0));
end shiftlogical;
architecture beh of shiftlogical is
begin
process(dir)
variable shift : integer;
begin
shift := conv_integer(unsigned(shamt));
if(dir = '0') then --Left shift
y(31 downto shift) <= x(31-shift downto 0);
y(shift downto 0) <= (others => '0');
elsif(dir = '1') then --Right shift
y(31-shift downto 0) <= x(31 downto shift);
y(31 downto 31-shift) <= (others => '0');
else --Always left shift
y(31 downto shift) <= x(31-shift downto 0);
y(shift downto 0) <= (others => '0');
end if;
end process;
end beh;

2's compliment input and using vhdl library for signed input

My input data is 2's compliment and I designed the input is signed number and the all of operation is used signed number,the library i used ieee.numeric_std.all, but when i do ‘+’ an error occurred "found '0' definitions of operator "+", cannot determine exact overloaded matching definition for "+"". So I changed another to another library ieee.std_logic_arith.all ans make the add operation as a component, it works.
when i simulate my code by using testbench, error occurred: Entity port xin does not match with type signed of component port.
I think this error is about my library.
can anyone help me ?
new
i do not use adder as a component and the below code works
adder: process(clk)
begin
if (clk'event and clk = '1')then
if enable1='1' then
add1 <= (x0(7)&x0) + (x15(8)&x15);
add2 <= (x1(7)&x1) + (x14(8)&x14);
add3 <= (x2(7)&x2) + (x13(8)&x13);
add4 <= (x3(7)&x3) + (x12(8)&x12);
add5 <= (x4(7)&x4) + (x11(8)&x11);
add6 <= (x5(7)&x5) + (x10(8)&x10);
add7 <= (x6(7)&x6) + (x9(8)&x9);
add8 <= (x7(7)&x7) + (x8(8)&x8);
end if;
end if;
end process adder;
and the library of my testbench use use ieee.numeric_std.all;
USE ieee.std_logic_1164.ALL;
use ieee.numeric_std.all;
use ieee.std_logic_textio.all;
use std.textio.all;
ENTITY tb_signedinput IS
END tb_signedinput;
ARCHITECTURE behavior OF tb_signedinput IS
-- Component Declaration
COMPONENT signedinput is
port( Clk : in std_logic;
reset : in std_logic;
enable1 : in std_logic;
Xin : in signed(7 downto 0);
Yout : out signed(19 downto 0)
);
END COMPONENT;
--Inputs
signal Clk : std_logic := '0';
signal reset : std_logic := '0';
signal Xin : signed(7 downto 0) := (others => '0');
signal enable1 : std_logic := '0';
--Outputs
signal Yout : signed(19 downto 0);
-- Array
constant MEMSIZE: integer :=99;
type testarray is array (MEMSIZE downto 0) of signed(7 DOWNTO 0);
signal testvectors: testarray;
shared variable vectornum,outnum: integer;
-- Clock period definitions
constant Clk_period : time := 10 ns;
BEGIN
-- Component Instantiation
uut: signedinput PORT MAP( Clk => Clk,
reset => reset,
Xin => Xin,
enable1 =>enable1,
Yout => Yout );
the error still occur:
Entity port xin does not match with type std_logic_vector of component port
Entity port yout does not match with type std_logic_vector of component port
therefore, I changed my adder again to
add1 <= resize(x0,9) + x15;
syntax good but same error in testbench..
Is error about my ISE type or library type?
Thank you!
Your addition expression in adder1 is invalid because you're trying to index element "8" when the range of a1 and a2 is 7 downto 0.
Assuming thet you're trying to sign extend it would look something more like this:
q <=(a1(7)&a1 + a2(7)&a2);
The "+" operator has higher precedence than "&" so you are trying to add a1 + a2(7) which is signed + std_logic. This doesn't have an overload defined in numeric_std in addition to being logically wrong.
This works:
q <=(a1(7)&a1) + (a2(7)&a2);
But it isn't the canonical way to implement sign extension when using numeric_std. You only need the left side term to have the same size as q. The signed "+" operator will take care of sign extending its right hand side automatically.
q <= resize(a1, q'length) + a2; -- Sign extend a1 and add
This gives cleaner code that says what it's doing without relying on the non-standard std_logic_arith.
The actual error about the type mismatch on xin isn't apparent from your code. It is possible that you have an older version of signedinput compiled with a different type on its port and haven't updated the library.
Kevin made it look tough, so I figured I'd show something that makes for a good explanation:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity adder1 is
port (
a1: in signed (7 downto 0);
a2: in signed (7 downto 0);
clk: in std_logic;
enable1: in std_logic;
q: out signed (8 downto 0)
);
end entity;
architecture behavioral of adder1 is
begin
UNLABELLED:
process(clk)
begin
if clk'event and clk ='1' then
if enable1 = '1' then
q <= a1(7) & a1 + a2 ;
end if;
end if;
end process;
end architecture;
The assignment to q looks naked so it's worth explaining.
The "+" in numeric_std for signed will sign extend the shorter operand to match the length of the longer operand.
The rest is priority magic.
"+" and "&" are the same priority, which means they're evaluated in left to right textual order, meaning the sign extension with the concatenation operator is performed first (see IEEE Std 1076-2008, 9.2 Operators).
The "+" operator sees the left operand as longer and matches the right operand to it's length, (see package numeric_std "+" for L,R: signed). It does this by using signed RESIZE on both operands after finding the MAX of the length of both, along with converting metavalues to 'X's.
It works if the right operand is longer too:
q <= a1 + (a2(7) & a2) ;
And here we need parentheses to associate the result of the concatenation operator as the right operand of the adding operator, because the two operators are the same priority and would otherwise be encountered in textual order.
There's no reason to call resize yet again, it's only a one bit sign extension by concatenation, based on knowing the sign is embodied in the left hand element (bit) of a two's compliment number.
The term canonical is not found in the VHDL standard.
As far as Xin, I'd agree with Kevin, something likely needs to be reanalyzed so that both references to signed are found in the same package.
Each declaration used in a design is unique. If say the actual in the port map depends on the type signed declaration in package std_logic_arith and the formal were to depend on the declaration of signed in package numeric_std they would be of different types.

VHDL code in NCLaunch giving errors not given in Xilinx

I am trying to make a dataflow design for a comparator in VHDL. It compiles and simulates fine in Xilinx, but I have to use Cadence/NCLaunch. When I copied the same code to gedit and ran it, it gives an error about a semicolon.
my code is :
library ieee;
use ieee.std_logic_1164.all;
-----------------------------------------------------
entity Comparator is
port( A: in std_logic_vector (3 downto 0);
B: in std_logic_vector (3 downto 0);
AeqB: out std_logic;
AltB: out std_logic;
AgtB: out std_logic);
end Comparator;
architecture dataflow of Comparator is
signal AeB : std_logic;
signal AlB : std_logic;
signal AgB : std_logic;
signal i : std_logic_vector (3 downto 0);
signal j : std_logic_vector (3 downto 0);
begin
B1: BLOCK BEGIN
AeB <= i(3) AND i(2) AND i(1) and i(0);
AgB <= j(3) or j(2) or j(1) or j(0);
AlB <= AeB nor AgB;
END BLOCK B1;
B2: BLOCK BEGIN
i <= a xnor b;
END BLOCK B2;
B3: BLOCK BEGIN
j(3) <= (not b(3)) and a(3);
j(2) <= i(3) and not b(2) and a(2);
j(1) <= i(3) and i(2) and not b(1) and a(1);
j(0) <= i(3) and i(2) and i(1) and not b(0) and a(0);
END BLOCK B3;
B4: BLOCK BEGIN
AeqB <= AeB;
AltB <= AlB;
AgTB <= AgB;
END BLOCK B4;
end dataflow;
...and the error I get is:
i <= a xnor b;
|
ncvhdl_p: *E,EXPSMI (/ugrad/syedhuq/ECE425/Lab2/Comparator.vhd,29|11): expecting a semicolon (';') [9.5.1].
As far as I can tell, I have a semicolon there...also if I replace the statement with four individual statements like
i(n) <= a(n) xnor b(n); //[n = 1, 2, 3, 4],
i get the same error 4 times. Can anyone help me out with this??
Also, it compiles fine in Synopsys (VCSMX) and so does the testbench file, but during the linking process it tells me :
Design unit 'COMPARATOR(BEHAVE)' from library '.' cannot be opened for
reading.
Possible causes:
[1] Incorrect logical to physical mapping in synopsys_sim.setup file.
[2] Intermediate file generation was prematurely terminated during analysis.
Reanalyze the design unit and resolve any errors that occur during analysis.
the relevant line from the testbench code is:
for x1: Comparator use entity work.Comparator(Behave);
I'm not familiar with Cadence/NCLaunch, but knowing your code analyzes correctly in an IEEE 1076-1993 compliant tool, and noting where error is (you indicated character position 11 in line 29, noting it appears to be character position 17), I'd say off hand it either doesn't have "xnor" un-commented in package std_logic_1164 (both the specification and the body), or it's a VHDL87 compliant tool, or there's some missing tool set or command line argument to use use the proper std_logic_1164 package.
In the distributed source for std_logic_1164, available from
http://standards.ieee.org/downloads/1076/1076.2-1996/
-- --------------------------------------------------------------------
-- version | mod. date:|
-- v4.200 | 01/02/92 |
-- --------------------------------------------------------------------
You'll find that xnor is commented out by default, when after VHDL92 (-1993, don't ask) was approved it was supposed to be un-commented.
-- -----------------------------------------------------------------------
-- Note : The declaration and implementation of the "xnor" function is
-- specifically commented until at which time the VHDL language has been
-- officially adopted as containing such a function. At such a point,
-- the following comments may be removed along with this notice without
-- further "official" ballotting of this std_logic_1164 package. It is
-- the intent of this effort to provide such a function once it becomes
-- available in the VHDL standard.
-- -----------------------------------------------------------------------
-- function "xnor" ( l, r : std_logic_vector ) return std_logic_vector;
-- function "xnor" ( l, r : std_ulogic_vector ) return std_ulogic_vector;
9.5.1 refers to Conditional signal assigns in IEEE=1076-1993.
The analyzer is acting like it doesn't recognize xnor as a operator and if you look in -1993 7.2.1 Logical operators:
The logical operators and, or, nand, nor,xor, xnor, and not are
defined for predefined types BIT and BOOLEAN. They are also defined
for any one-dimensional array type whose element type is BIT or
BOOLEAN.
Which tells us in an IEEE 1076-1993 compliant tool the declarations for xnor would come from the std_logic_1164 package.
I had a quick gander through some NCSIM, etc. online user guides and tutorials and didn't see anything relating to the problem. It's likely the std_logic_1164 package hadn't had xnor un-commented in both the declaration and body.
The issue may be the the providence (age) or the particular tool copy you are using and may require sysadmin help to correct. In the mean time you can either write your own xnor function (shown), if running into any difficulties try and use not( a xor b) instead.
architecture dataflow of Comparator is
function "xnor" ( l : std_logic; r : std_logic ) return ux01 is
begin
return not (l xor r);
end "xnor";
signal AeB : std_logic;
signal AlB : std_logic;
signal AgB : std_logic;
signal i : std_logic_vector (3 downto 0);
signal j : std_logic_vector (3 downto 0);
begin
Also see Weird XNOR behaviour in VHDL

Never-ending synthesis with integer incrementation

I have a piece of VHDL code that compile but when I try to synthesize it I get stuck, meaning the synthesization never ends and I have in the console:
Analyzing Entity Interpretor in library work (Architecture ).
I've tried to understand why but I can't. All I know is that if I comment the line CPT_PAN <= CPT_PAN - 1; then all of sudden I can synthesize.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity Interpretor is
Port (SCAN_CODE : IN STD_LOGIC_VECTOR(7 downto 0));
end Interpretor;
architecture Behavioral of Interpretor is
Signal CPT_PAN : Integer range 0 to 255 := 0;
begin
process(SYS_CLK)
begin
if (SYS_CLK'EVENT and SYS_CLK = '1') then
if SCAN_CODE = "01101011" then
if CPT_PAN /= 0 then
CPT_PAN <= CPT_PAN - 1; -- Line to be commented to synthesize
end if;
end if;
end if;
end process;
end Behavioral;
Which synthesis tool? It would be useful to know.
Xilinx XST 14.3 simply reports <sys_clk> is not declared. and exits.
Add an input port for it, and it synthesises correctly, producing no hardware!
Add an output,
entity Interpretor is
Port (
SYS_CLK : in std_logic;
SCAN_CODE : IN STD_LOGIC_VECTOR(7 downto 0);
Zero : Out Boolean
);
end Interpretor;
and a line to the architecture
Zero <= CPT_Pan = 0;
and it generates pretty much what you would expect. It still optimises away to nothing since CPT_Pan is initialised to 0, and that case is not handled at all by the process.
Dare I ask if you simulated this before trying to synthesise?

Resources