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

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.

Related

Error in to_integer

library ieee;
use ieee.std_logic_1164.ALL;
use ieee.numeric_bit.ALL;
use ieee.numeric_std.ALL;
entity multiplexer is
port (A,B: in std_logic_vector (7 downto 0);
CI: in std_logic;
CO: out std_logic;
ANS: out std_logic_vector (7 downto 0);
OP: in std_logic_vector(1 downto 0);
EN: in std_logic);
end multiplexer;
architecture archi of multiplexer is
signal tmp: std_logic_vector (8 downto 0);
begin
process (EN) begin
if (EN = '1') Then
case OP is
when "00" =>
tmp <= std_logic_vector((TO_INTEGER(A)+TO_INTEGER(B)+TO_INTEGER (CI)),9);
ANS<= tmp(7 downto 0);
CO <= tmp(8);
when "01" =>
tmp <= std_logic_vector((to_integer(A)-to_integer(B)+to_integer (CI)),9);
ANS<= tmp(7 downto 0);
CO <= tmp(8);
when others => NULL;
end case;
else
NULL;
end if;
end process;
end archi;
The errors are coming in the To_integer part. I donot know what I am doing wring over here? Also previously I had used the numeric_arith and numeric_unsigned.all and then the subprograms were conv_integer the program compiled but there were no output in the ANS and CO areas. They were defined as undefined. I am attaching the wave output for reference. Please help.
Previous wave output
The issue appears to be having use clauses containing references to both package numeric_std and numeric_bit.
See IEEE 1076-2008 12.4 Use clauses, para 8:
In order to determine which declarations are made directly visible at a given place by use clauses, consider the set of declarations identified by all use clauses whose scopes enclose this place. Any declaration in this set is a potentially visible declaration. A potentially visible declaration is actually made directly visible except in the following three cases:
a) A potentially visible declaration is not made directly visible if the place considered is within the immediate scope of a homograph of the declaration.
b) If two potentially visible declarations are homographs and one is explicitly declared and the other is implicitly declared, then the implicit declaration is not made directly visible.
c) Potentially visible declarations that have the same designator and that are not covered by case b) are not made directly visible unless each of them is either an enumeration literal specification or the declaration of a subprogram.
Noting you have two potentially visible declarations, e.g.:
The errors are :** Error: C:/altera/16.0/multiplexer2.vhd(17): (vcom-1078) Identifier "unsigned" is not directly visible.
Potentially visible declarations are: ieee.NUMERIC_STD.UNSIGNED (subtype declaration) ieee.NUMERIC_BIT.UNSIGNED (type declaration)
unsigned, a type declaration is not visible under rule c) above.
As Jim notes you don't use type unsigned based on type bit_vector, all object declarations present are based on std_logic and not bit.
Further, 16.8.5.1 General paras 1
Four VHDL packages for arithmetic using bit and standard logic values are defined by this standard. The NUMERIC_BIT and NUMERIC_BIT_UNSIGNED packages are based on the VHDL type BIT, while the NUMERIC_STD and NUMERIC_STD_UNSIGNED packages are based on the type STD_ULOGIC.
and para 6 (in part):
The four packages are mutually incompatible, and only one shall be used in any given design unit.
You've demonstrated that incompatibility, attempting to use a declaration that is neither an enumeration literal nor subprogram (not subject to overload resolution).
If you're tool had been -2008 aware it should have provided an error (shall is mandatory, see 1.3.1) and use clauses for both made visible in the same declarative region are detectable (although not a convenient error to detect).
In general you should use the minimum number of use clauses necessary, providing resources needed for a design description to avoid these sorts of issues.
Commenting out the use clause referencing numeric_bit is not sufficient. The base type of CI is std_ulogic (it's type is std_logic). You can convert a std_logic to an unsigned excepted by expressing CI as a an array type:
library ieee;
use ieee.std_logic_1164.ALL;
-- use ieee.numeric_bit.ALL;
use ieee.numeric_std.ALL;
entity multiplexer is
port (
A,B: in std_logic_vector (7 downto 0);
CI: in std_logic;
CO: out std_logic;
ANS: out std_logic_vector (7 downto 0);
OP: in std_logic_vector(1 downto 0);
EN: in std_logic);
end multiplexer;
architecture archi of multiplexer is
signal tmp: std_logic_vector (8 downto 0);
begin
tmp <= std_logic_vector(unsigned(A)+unsigned(B)+unsigned'(""& CI)) when EN =
'1' and OP = "00" else
std_logic_vector(unsigned(A)-unsigned(B)+unsigned'(""& CI)) when EN = '0' and
OP = "01" else
(others => '0');
-- tmp <= std_logic_vector(unsigned(A)+unsigned(B)+unsigned(CI)) when EN =
-- '1' and OP = "00" else
-- std_logic_vector(unsigned(A)-unsigned(B)+unsigned(CI)) when EN = '0' and
-- OP = "01" else
-- (others => '0');
ANS<= tmp(7 downto 0);
CO <= tmp(8);
end archi;
unsigned'(""& CI) qualifies the expression "" & CI (a null array concatenated with CI as type unsigned.
See 9.3.5 Qualified expressions, para 1:
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.
For the array type unsigned concatenation operators are predefined for concatenation between a value of a single dimensional array type and it's element type. See 9.2.5 Adding operators. The string literal "" has a length of zero (15.7 String literals, 5.3.2.2 Index constraints and discrete ranges, para 4), and it's type is context defined by the qualified expression (See 9.3.2 Literals para 5).
Making the above changes and your multiplexer analyzes. It's functionality is not tested lacking a Minimal, Complete, and Verifiable example.
1. to_integer
Look for documentation for numeric_std package. You can't put std_logic_vector to to_integer function. You have to first cast it to unsigned:
signal a: std_logic_vector(8 downto 0);
signal b: std_logic_vector(8 downto 0);
signal res: integer;
res <= to_integer(unsigned(a) + unsigned(b));
But actually, in your case you don't have to do it at all. Just cast std_logic_vector to unsigned (or signed), and then you can safely add it:
tmp <= std_logic_vector(unsigned(A)+unsigned(B)+unsigned(CI));
2. UUU thing
First - as I already told you - you must have all inputs in sensitivity list, if you want to do it without clock. But this will not help, because you are using signals. Remember, that when you assign something to signal, it is not done immediately, but it is only sceduled, to be done after the process. So after line:
tmp <= std_logic_vector((TO_INTEGER(A)+TO_INTEGER(B)+TO_INTEGER(CI)),9);
tmp does not yet contain result, but still has UUU. Then in lines:
ANS<= tmp(7 downto 0);
CO <= tmp(8);
you assign U to ANS and CO. What you can do is to use variables in process, or even better - to put lines:
ANS<= tmp(7 downto 0);
CO <= tmp(8);
outside of the process:
library ieee;
use ieee.std_logic_1164.ALL;
use ieee.numeric_std.ALL;
entity multiplexer is
port (
A,B: in std_logic_vector (7 downto 0);
CI: in std_logic;
CO: out std_logic;
ANS: out std_logic_vector (7 downto 0);
OP: in std_logic_vector(1 downto 0);
EN: in std_logic);
end multiplexer;
architecture archi of multiplexer is
signal tmp: std_logic_vector (8 downto 0);
begin
process (EN) begin
if (EN = '1') Then
case OP is
when "00" =>
tmp <= std_logic_vector(unsigned(A)+unsigned(B)+unsigned(CI));
when "01" =>
tmp <= std_logic_vector(unsigned(A)-unsigned(B)+unsigned(CI));
when others => NULL;
end case;
else
NULL;
end if;
end process;
ANS<= tmp(7 downto 0);
CO <= tmp(8);
end archi;
or even get rid of process at all:
architecture archi of multiplexer is
signal tmp: std_logic_vector (8 downto 0);
begin
tmp <= std_logic_vector(unsigned(A)+unsigned(B)+unsigned(CI)) when EN = '1' and OP = "00" else
std_logic_vector(unsigned(A)-unsigned(B)+unsigned(CI)) when EN = '1' and OP = "01" else
(others => '0');
ANS<= tmp(7 downto 0);
CO <= tmp(8);
end archi;

std_logic_vector to integer conversion vhdl

I faced with conversion problem/I read a lot of similar topics but my code still not working.Could you pls give me some hints. Quartus give me error:
Error (10476): VHDL error at true_dual_port_ram_single_clock.vhd(44): type of identifier "random_num_i" does not agree with its usage as "std_logic_vector" type
LIBRARY ieee;
USE ieee.std_logic_1164.all;
use IEEE.std_logic_signed.all;
use IEEE.std_logic_unsigned.all;
use IEEE.NUMERIC_STD.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
entity write_ram is
generic(width : integer := 32);
port(clock_i : IN STD_LOGIC;
we_w : IN STD_LOGIC;
wr_addr : IN INTEGER RANGE 0 to 31;
read_add : IN INTEGER RANGE 0 to 31;
q_out : out STD_LOGIC_VECTOR(2 DOWNTO 0)
);
end write_ram;
architecture rtl of write_ram is
--- Component decalarartion
component random is
port(clk : in std_logic;
random_num : out std_logic_vector(width - 1 downto 0) --output vector
);
end component;
component single_clock_ram is
port(clock : IN STD_LOGIC;
data : IN INTEGER RANGE 0 to 31;
write_address : IN INTEGER RANGE 0 to 31;
read_address : IN INTEGER RANGE 0 to 31;
we : IN STD_LOGIC;
q : OUT STD_LOGIC_VECTOR(2 DOWNTO 0)
);
end component;
for all : random use entity work.random(rtl);
for all : single_clock_ram use entity work.single_clock_ram(rtl);
Signal random_num_i : INTEGER RANGE 0 to 31; --interanal signals
begin
-- Component Instantiation
C1 : random Port map(
clk => clock_i,
--random_num <=to_integer(to_signed(random_num_i))
random_num => random_num_i
);
random_num <= to_integer(to_signed(random_num_i)); -- error
C2 : single_clock_ram
Port map(
clock => clock_i,
we => we_w,
read_address => read_add,
write_address => wr_addr,
data => random_num_i,
q => q_out
);
end rtl;
Your question isn't an MCVE with the configuration specifications for random and single_clock_ram present. You didn't supply the entity declarations and architecture bodies (rtl) for them.
With them commented out this analyzes:
library ieee;
use ieee.std_logic_1164.all;
-- use ieee.std_logic_signed.all; -- NOT USED
-- use ieee.std_logic_unsigned.all; -- NOT USED
use ieee.numeric_std.all;
-- use ieee.std_logic_arith.all; -- NOT USED
entity write_ram is
generic (width: integer := 32);
port (clock_i: in std_logic;
we_w: in std_logic;
wr_addr: in integer range 0 to 31;
read_add: in integer range 0 to 31;
q_out: out std_logic_vector(2 downto 0)
);
end entity write_ram;
architecture rtl of write_ram is
--- component declaration
component random is
port (clk: in std_logic;
random_num: out std_logic_vector(width - 1 downto 0) --output vector
);
end component;
component single_clock_ram is
port (clock: in std_logic;
data: in integer range 0 to 31;
write_address: in integer range 0 to 31;
read_address: in integer range 0 to 31;
we: in std_logic;
q: out std_logic_vector(2 downto 0)
);
end component;
-- for all: random use entity work.random(rtl);
-- for all: single_clock_ram use entity work.single_clock_ram(rtl);
signal random_num_i: integer range 0 to 31; -- internal signals
signal random_num: std_logic_vector(width - 1 downto 0); -- added
begin
-- component instantiation
c1: random port map (
clk => clock_i,
-- random_num <=to_integer(to_signed(random_num_i))
-- random_num => random_num_i -- DELETED
random_num => random_num -- ADDED
);
-- random_num <= to_integer(to_signed(random_num_i)); -- error DELETED
random_num_i <= to_integer(signed(random_num)); -- ADDED
c2: single_clock_ram
port map (
clock => clock_i,
we => we_w,
read_address => read_add,
write_address => wr_addr,
data => random_num_i,
q => q_out
);
end architecture rtl;
Note there's been a random_num std_logic_vector declared to hook up to the output of random, which is converted an integer random_num_i used as an input to single_clock_ram data. The output q from the single_clock_ram looks a bit suspicious, should that be an integer or a wider std_logic_vector?
First, delete the non-standard libraries.
use IEEE.std_logic_signed.all;
use IEEE.std_logic_unsigned.all;
use IEEE.STD_LOGIC_ARITH.ALL;
leaving only std_logic_1164 and numeric_std.
The others introduce a bunch of overlapping declarations which make it difficult to determine what is going on - and if there are several declarations for the same operator with the same argument and result types, the compiler makes them all invisible rather than picking an arbitrary one.
Then, decide what you are trying to do. This is currently ambiguous and contradictory.
(1)You have a generic (width : integer :=32); and a port declaration
random_num : out std_logic_vector (width-1 downto 0)
which suggest you are dealing with 32 bit words.
(2) You have a ranged integer : Signal random_num_i: INTEGER RANGE 0 to 31; which (a) should be a ranged NATURAL to make it even clearer that negative values are errors, and (b) suggests you are dealing with 5 bit words.
Which is it? What exactly are you trying to do?
And here, you are apparently trying to connect them together in a port map...
C1: random Port map (
clk => clock_i,
--random_num <=to_integer(to_signed(random_num_i))
random_num =>random_num_i
);
random_num <=to_integer(to_signed(random_num_i)); -- error
There are a number of things wrong here.
1) A simple port mapping like random_num =>random_num_i requires that both sides have the same type. This would work if both sides actually WERE the same type : for example, if you added a signal declaration
random_num_slv : std_logic_vector (width-1 downto 0);
then the port mapping random_num =>random_num_slv would work. Now you can convert to the required type random_num_i in a signal assignment.
random_num_i <= to_integer (unsigned(random_num_slv));
There are still problems with this : a 32-bit output is likely to overflow a 5-bit integer.
While adding an intermediate signal random_num_slv may look inefficient and redundant, it keeps the design clean and simple, which matters when dealing with tools that don't understand type conversions in ports.
Make sure you know how to use intermediate signals even if there's a cleaner approach. It can save you when all else fails.
(2) The commented out port mapping
random_num <=to_integer(to_signed(random_num_i))
would be the way to do it, except for three things ...
(a) <= is a signal assignment, you need => a n association operator
(b) you're converting an integer to an integer, and driving a std_logic_vector with it. That really won't work...
(c) the component port is an OUTPUT so you shouldn't be driving it in the first place.
What you probably meant was
to_integer(unsigned(random_num)) => random_num_i
and this would be the cleanest way to do it if your tools support conversions in port maps properly.
Notes:
again it has the overflow problem, a 32-bit vector won't fit a 5 bit integer.
You can convert from std_logic_vector to either signed or unsigned by casting unsigned rather than a conversion function to_signed as they are closely related types. Integers are not "closely related" to these, so need a conversion function to_integer.
As negative numbers aren't permitted by the declaration of random_num_i, use unsigned rather than signed.
(3) The existing signal assignment
random_num <=to_integer(to_signed(random_num_i)); -- error
again contains several errors. The biggest is that there is no random_num port visible outside the component declaration. Simply delete this line, you need to use one of the port mappings.
Further considerations:
(1) Some type conversions are inevitable. But if you are doing too many, that generally points to a design error, like the use of std_logic_vector everywhere, even for thengs like addresses which are inevitably unsigned integers so either unsigned ornatural would be a better choice. Keep the design as simple and readable as possible. I think your use of integer here is generally good but natural would be better (unless you need negative addresses!)
(2) If you're adding the flexibility of a generic like width, use it correctly and consistently - OR - check it's valid.
Here, as described above, your design ONLY works correctly without surprises IF this entity is instantiated with width => 5.
So, check the value and abort if this precondition is not met.
assert Width = 5 report "Width of " & natural'image(width) & " not supported!"
severity FAILURE;
OR make the design work for all reasonable values of the generic, for example by making other quantities dependent on it in valid ways. For example:
constant DEPTH : natural := 2**WIDTH - 1;
signal random_num_i : natural range 0 to DEPTH;
and so on...

VHDL Increment 10-bit Program Counter by 1

I am trying to make a 32-bit CPU using a modified MIPS instruction set in VHDL. I am currently trying to get my Program Counter to increment by 1 for the next instruction, unless it is a jump instruction which then the Program Counter will equal the Jump value.
entity PC is
Port ( PC_IN : in STD_LOGIC_VECTOR (9 downto 0); --New PC in value (PC+1 or jump)
PC_OUT : out STD_LOGIC_VECTOR (9 downto 0); --PC out to instruction memory
Jump_Inst : in STD_LOGIC_VECTOR(9 downto 0); --Jump address
Jump : in STD_LOGIC; --Jump MUX
clk : in STD_LOGIC);
end PC;
architecture Behavioral of PC is
begin
PC_IN <= (PC_IN + "0000000001") when (Jump = '0')
else Jump_Inst;
process(clk)
begin
if rising_edge(clk) then --If it is the next clock cycle (i.e time for the next instruction)
PC_OUT <= PC_IN;
end if;
end process;
end Behavioral;
I am getting errors at this line PC_IN <= (PC_IN + "0000000001") when (Jump = '0'). The errors consist of cannot update 'in' object pc_in and 0 definitions of operator "+" match here, so it doesn't like me using the + operator and maybe pc_in needs to be an output?
Does anyone know how to get my program counter to increment by 1 for the next instruction? Any help would be appreciated. Thanks.
PC_IN is defined as a std_logic_vector. You don't show the libraries in use, but by default there are no defined operators for + for std_logic_vector in std_logic_1164. Note your error message:
0 definitions of operator "+" match here
This is your hing that + isn't defined in this context. In order to use the + operator, you need to include a library that has that support and use the appropriate type.
Your other error:
cannot update 'in' object pc_in
Tells you that you cannot set an in port. Notably, PC_IN is an input, yet you are trying to drive PC_IN. Perhaps you mean to drive PC_OUT?
I won't mention the alternate method, but you should probably use numeric_std in this case. For example:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
...
PC_OUT <= std_logic_vector(unsigned(PC_IN) + 1) when (Jump = '0') else Jump_Inst;

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

Implementing an Accumulator in VHDL

I am trying to implement a signed accumulator using Core Gen in Xilinx. According to my understanding an accumulator performs the function of a normal register which is just routing the input to the output, but I wanted clarification on that.
I added the Accumulator IPcore (.xco) module to the project and I have a main file which basically contains the component declaration and the port map. I have a single step process too. Everything compiles and I can see the result on the board but don't quite understand what's going on...
When I input 1000 the 8 bit output on the LEDs is 11111000. Another input of 1111 gives me 11110111. I am attaching the code here for the main vhd file called Accm and the .vho file.
----------------------------------------------------------------------------------
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
--use IEEE.NUMERIC_STD.ALL;
-- Uncomment the following library declaration if instantiating
-- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;
entity Accm is
port( b: in std_logic_vector(3 downto 0);
sclr, clk, b1, b2 : in std_logic;
q : out std_logic_vector(7 downto 0)
);
end Accm;
architecture Behavioral of Accm is
-- signal declaration
type tell is (rdy,pulse,not_rdy);
signal d_n_s: tell;
signal en: std_logic;
-- component declaration
COMPONENT my_accm
PORT (
b : IN STD_LOGIC_VECTOR(3 DOWNTO 0);
clk : IN STD_LOGIC;
sclr : IN STD_LOGIC;
q : OUT STD_LOGIC_VECTOR(7 DOWNTO 0)
);
END COMPONENT;
-- port map
begin
A1 : my_accm
PORT MAP (
b => b,
clk => en,
sclr => sclr,
q => q
);
process(clk)
begin
if clk'event and clk='1' then
case d_n_s is
when rdy => en <= '0';
if b1='1' then d_n_s <= pulse; end if;
when pulse => en <= '1';
d_n_s <= not_rdy;
when not_rdy => en <='0';
if b2='1' then d_n_s <= rdy; end if;
end case;
end if;
end process;
-- .VHO CODE
------------- Begin Cut here for COMPONENT Declaration ------ COMP_TAG
COMPONENT my_accm
PORT (
b : IN STD_LOGIC_VECTOR(3 DOWNTO 0);
clk : IN STD_LOGIC;
sclr : IN STD_LOGIC;
q : OUT STD_LOGIC_VECTOR(7 DOWNTO 0)
);
END COMPONENT;
-- COMP_TAG_END ------ End COMPONENT Declaration ------------
-- The following code must appear in the VHDL architecture
-- body. Substitute your own instance name and net names.
------------- Begin Cut here for INSTANTIATION Template ----- INST_TAG
your_instance_name : my_accm
PORT MAP (
b => b,
clk => clk,
sclr => sclr,
q => q
);
end Behavioral;
I am also pasting an image of the accumualtor I generated in CoreGen.
I'D appreciate it if someone could explain me what is going on in this program. Thanks!
"Accumulator" can mean many things. In the hardware Xilinx library, the component you instantiated is an adder in front of a register. The adder is adding the current value of the accumulator register with the input term. The accumulator register is wider than the input so you can accumulate (add together) many input terms without overflowing the output.
When your circuit starts, the accumulator contains zero. You input 1000 (-8) which when added to zero becomes 11111000 (-8 sign extended) on the output. You then add 1111 (-1), and the output becomes 11110111 (-9 sign extended).
Once you are done "accumulating", assert SCLR to clear the accumulator register back to zero (or use SSET or SINIT, as appropriate for your logic).
This should all be covered by the documentation for the Xilinx library (try clicking the "datasheet" button in the corgen dialog).
Actually, I think I get it now. It's just acting like an Adder with signed inputs. I think I am correct on this but would appreciate any clarification!

Resources