I can't understand why my waveform is coming out this way - vhdl

I am very new to VHDL coding and I have been trying to debug my code for a 32-bit adder/subtractor. The N-bit adder/subtractor is composed multiple 1-bit adder/subtractor using a generate statement. I have been testing it for 6-bit inputs using simulation. The waveform is constantly incorrect and I have tried changing just about everything. Maybe, it is a problem with the delays and the generate statement not cycling through correctly. (I am just beginning to learn how to code in vhdl.)
My 1-bit adder/subtractor
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity addsub_1bit is
Port ( in_0 : in STD_LOGIC;
in_1 : in STD_LOGIC;
cin : in STD_LOGIC;
AddOrSub : in STD_LOGIC;
sum_sub : out STD_LOGIC;
cout_bout : out STD_LOGIC);
end addsub_1bit;
architecture data_flow_addsub_1bit of addsub_1bit is
begin
sum_sub <= (in_1 and (not in_0) and (not cin)) or ((not in_1) and in_0 and (not cin)) or ((not in_1) and (not in_0) and cin) or (in_1 and in_0 and cin) after 19 ns;
cout_bout <= (in_1 and in_0 and (not AddOrSub)) or ((not in_1)and in_1 and cin) or ((not in_1)and cin and AddOrSub) or (in_0 and cin) or (in_1 and cin and AddOrSub) after 19 ns;
end data_flow_addsub_1bit;
The N-bit adder/subtractor:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
ENTITY adder_sub32 is
GENERIC (BW : INTEGER :=32);
PORT ( a_32 : IN STD_LOGIC_VECTOR (BW -1 downto 0);
b_32 : IN STD_LOGIC_VECTOR (BW -1 downto 0);
cin : IN STD_LOGIC;
sub : IN STD_LOGIC;
sum_32 : out STD_LOGIC_VECTOR (BW -1 downto 0);
cout : INOUT STD_LOGIC ;
ov : OUT STD_LOGIC ); -- ov stands for overflow
END adder_sub32 ;
ARCHITECTURE adder_sub32_arch OF adder_sub32 IS
signal tmp : std_logic_vector (BW downto 0);
BEGIN
tmp(0) <= cin;
gen: for i IN 0 TO BW-1 GENERATE
as1: entity work.addsub_1bit
PORT MAP(
in_0 => a_32(i),
in_1 => b_32(i),
cin => tmp(i),
AddOrSub => sub,
sum_sub => sum_32(i),
cout_bout => tmp(i+1));
end GENERATE;
ov <= tmp(BW) after 95 ns;
END ARCHITECTURE;
My testbench:
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
ENTITY adder_sub32_TB_SHan_53967364 IS
END adder_sub32_TB_SHan_53967364;
ARCHITECTURE behavior OF adder_sub32_TB_SHan_53967364 IS
-- Component Declaration for the Unit Under Test (UUT)
COMPONENT adder_sub32 IS
GENERIC (BW : INTEGER :=32);
PORT ( a_32 : IN STD_LOGIC_VECTOR (BW -1 downto 0);
b_32 : IN STD_LOGIC_VECTOR (BW -1 downto 0);
cin : IN STD_LOGIC ;
sub : IN STD_LOGIC ;
sum_32 : out STD_LOGIC_VECTOR (BW -1 downto 0);
cout : INOUT STD_LOGIC ;
ov : OUT STD_LOGIC ); -- ov stands for overflow
END COMPONENT;
signal a : std_logic_vector(5 downto 0); --:= (others => '0');
signal b : std_logic_vector(5 downto 0); --:= (others => '0');
signal cin : std_logic;
signal sub : std_logic;
signal cout : std_logic;
signal sum_32 : std_logic_vector(5 downto 0);
signal ov : std_logic;
BEGIN
test1: adder_sub32
GENERIC MAP (6)
PORT MAP (a_32 => a,b_32 => b,cin => cin,sub => sub,sum_32 => sum_32,cout => cout,ov => ov);
sub <= '0';
cin <= '0';
a <= "101010";
b <= "110101";
END;
The waveform I got:

The final sum is correct ("101010" + "110101" = "011111") in this case, but not in all cases.
EDIT2: Let's take a closer look, why the carry is not rippling as expected in your addition. The bits 0 (LSB) to 5 of the operands together, request that the carry-in is propagated from bit 0 to the carry-in of bit 6. Bits 6 of the operands generate a carry, which is carry-out of the adder. As the cin of bit 0 is '0', all intermediate carry-ins will be '0' too, but it should ripple through the carry-chain.
Now lets, take a look at the one-bit adder. You are adding two numbers, so that, AddOrSub is '0'. With this, the equation of cout_bout can be simplified to:
cout_bout <= (in_1 and in_0) or (in_0 and cin);
This equation is definitly wrong, because the carry-in is not propagated when in_1 = '1' and in_0 = '0'. Thus, some of the intermediate carries will be computed to '0' just after 19 ns without waiting for the rippling carry. The corresponding sum bit will be valid after 38 ns as shown in your waveform. The final value of the sum is not affected because this shortcuted carry is identical to the expected rippling carry. Please consider here, that all the 1-bit adder (generated by the generate statement) work concurrently.
To fix the equation, I recommend to write a testbench for the 1-bit adder. This testbench would have to check all possible 16 input combinations of in_0, in_1, cin, and AddOrSub.
Another testcase would be to add the above two operands with an cin of '1'.
(End of EDIT2.)
The ov is correct too in this case, but not in all cases.
EDIT: You mixed up the overflow ov with the carry-out cout. The overflow flag indicates an overflow in the signed number space. For the addition, the overflow flag is '1' if and only if:
the addition of two positive numbers results in a negative sum, or
the addition of two negative numbers results in a positive sum.
For subtraction it is the other way round.
Because this is a homework question, I will not solve it completely. But I will give a you a testcase where your current logic fails: if you add 1 ("000001") plus -1 ("111111"), then the sum must be zero, the overflow '0' and the carry-out '1'. (End of Edit.)
The cout is 'U' because you haven't connected it in adder_sub32. The carry-out is the top-most bit in your carry-chain, and thus:
cout <= tmp(BW);
And you should fix the direction of cout in adder_sub32. The carry-out is just an output of this component. So declare it as out instead of inout.

Related

Vivado stops simulation on feedback circuit

I'm trying to do a circuit consisting of a 2 to 1 multiplexer (8-bit buses), an 8-bit register and an 8-bit adder. These components are all tested and work as expected.
The thing is: if I try to send the output of the Adder to one of the inputs of the
multiplexer (as seen in the image by the discontinued line), the simulation will stop rather suddenly. If I don't do that and just let ain do its thing, everything will run just as it should, but I do need the output of the adder to be the one inputted to the multiplexer.
The simulation is the following:
The code is:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity Sumitas is
port (m : in STD_LOGIC;
clk : in STD_LOGIC;
ain : in STD_LOGIC_VECTOR (7 downto 0);
Add : out STD_LOGIC_VECTOR (7 downto 0));
end Sumitas;
architecture rtl of Sumitas is
component Adder8bit
port (a, b : in STD_LOGIC_VECTOR (7 downto 0);
Cin : in STD_LOGIC;
S : out STD_LOGIC_VECTOR (7 downto 0);
Cout : out STD_LOGIC);
end component;
component GenericReg
generic (DataWidth : integer := 8);
port (en : in STD_LOGIC;
dataIn : in STD_LOGIC_VECTOR (DataWidth - 1 downto 0);
dataOut : out STD_LOGIC_VECTOR (DataWidth - 1 downto 0));
end component;
component GenericMux2_1
generic (DataWidth : integer := 8);
port (a, b : in STD_LOGIC_VECTOR (DataWidth - 1 downto 0);
Z : in STD_LOGIC;
S : out STD_LOGIC_VECTOR (DataWidth - 1 downto 0));
end component;
constant DW : integer := 8;
signal AddOut_s, MuxOut_s : STD_LOGIC_VECTOR (7 downto 0);
signal PCOut_s : STD_LOGIC_VECTOR (7 downto 0);
begin
m0 : GenericMux2_1
generic map (DataWidth => DW)
port map (a => "00000000",
b => AddOut_s,
Z => m,
S => MuxOut_s);
PC : GenericReg
generic map (DataWidth => DW)
port map (en => clk,
dataIn => MuxOut_s,
dataOut => PCOut_s);
Add0 : Adder8bit
port map (a => "00000001",
b => PCOut_s,
Cin => '0',
S => AddOut_s,
Cout => open);
Add <= AddOut_s;
end rtl;
and the testbench:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity bm_Sumitas is
end bm_Sumitas;
architecture benchmark of bm_Sumitas is
component Sumitas
port (m : in STD_LOGIC;
clk : in STD_LOGIC;
ain : in STD_LOGIC_VECTOR (7 downto 0);
Add : out STD_LOGIC_VECTOR (7 downto 0));
end component;
signal clk_s, m_s : STD_LOGIC;
signal Add_s, ain_s : STD_LOGIC_VECTOR (7 downto 0);
constant T : time := 2 ns;
begin
benchmark : Sumitas
port map (m => m_s,
clk => clk_s,
ain => ain_s,
Add => Add_s);
clk_proc: process
begin
clk_s <= '0';
wait for T/2;
clk_s <= '1';
wait for T/2;
end process;
bm_proc : process
begin
m_s <= '0';
wait for 10 ns;
m_s <= '1';
wait for 100 ns;
end process;
ains_proc : process
begin
ain_s <= "00001111";
for I in 0 to 250 loop
ain_s <= STD_LOGIC_VECTOR(TO_UNSIGNED(I, ain_s'length));
wait for T;
end loop;
end process;
end benchmark;
How can I do the thing I want? I'm ultimately trying to simulate a computer I designed. I have every component already designed and I'm coupling them together.
Constructing a Minimal, Complete, and Verifiable example requires filling in the missing components:
library ieee;
use ieee.std_logic_1164.all;
entity Adder8bit is
port (a, b : in STD_LOGIC_VECTOR (7 downto 0);
Cin : in STD_LOGIC;
S : out STD_LOGIC_VECTOR (7 downto 0);
Cout : out STD_LOGIC);
end entity;
architecture foo of adder8bit is
signal sum: std_logic_vector (9 downto 0);
use ieee.numeric_std.all;
begin
sum <= std_logic_vector ( unsigned ('0' & a & cin) +
unsigned ('0' & b & cin ));
s <= sum(8 downto 1);
cout <= sum(9);
end architecture;
library ieee;
use ieee.std_logic_1164.all;
entity GenericReg is
generic (DataWidth : integer := 8);
port (en : in STD_LOGIC;
dataIn : in STD_LOGIC_VECTOR (DataWidth - 1 downto 0);
dataOut : out STD_LOGIC_VECTOR (DataWidth - 1 downto 0));
end entity;
architecture fum of genericreg is
begin
dataout <= datain when en = '1';
end architecture;
with behavioral model substitutes.
(It's not that much work, copy the component declarations paste them, substitute entity for component and add the reserved word is, followed by simple behaviors in architectures.)
It reproduces the symptom you displayed in your simulation waveform:
You can see the essential point of failure occurs when the register enable (ms_s) goes high.
The simulator will report operation on it's STD_OUTPUT:
%: make wave
/usr/local/bin/ghdl -a bm_sumitas.vhdl
/usr/local/bin/ghdl -e bm_sumitas
/usr/local/bin/ghdl -r bm_sumitas --wave=bm_sumitas.ghw --stop-time=40ns
./bm_sumitas:info: simulation stopped #11ns by --stop-delta=5000
/usr/bin/open bm_sumitas.gtkw
%:
Note the simulation stopped at 11 ns because of a process executing repeatedly in delta cycles (simulation time doesn't advance).
This is caused by a gated relaxation oscillator formed by the enabled latch, delay (a delta cycle) and having at least one element of latch input inverting each delta cycle.
The particular simulator used has a delta cycle limitation, which will quit simulation when 5,000 delta cycles occur without simulation time advancing.
The genericreg kept generating events with no time delay in assignment, without an after clause in the waveform, after 0 fs (resolution limit) is assumed.
Essentially when the enable is true the signal will have at least one element change every simulation cycle due to the increment, and assigns the signal a new value for at least one element each simulation cycle without allowing the advancement of simulation time by not going quiescent.
You could note the simulator you used should have produced a 'console' output with a similar message if it were capable (and enabled).
So how it this problem cured? The easiest way is to use a register (not latch) sensitive to a clock edge:
architecture foo of genericreg is
begin
dataout <= datain when rising_edge(en);
end architecture;
Which gives us the full simulation:

N-bits adder/subtractor using ripple of full adders- problem with carryout

I am trying to create N-bits adder/subtractor using a ripple of full adders.
The input is N-bits A, N-bits B, and the result should be at length of 2N (it outputs ALU with 2 buses High and low of N-bits each, so I am trying to extend the signed bit).
The problem arises with carryout in subtraction. For example, when doing 3-2 (assume N=3 so that it's 011-010 and with two's compliment it's 011+110) I get 001 with carry 1. The problem is that this carry is garbage and can't be extended, but in other case it's necessary. For example, when trying do (-3)+(-3) (101+101, again N=3), then I get 010 with carry of 1. This time the carry really indicate the sign, so I would like to extend it.
Here is my code:
entity FullAdder is
Port (
A : in std_logic;
B : in std_logic;
Cin : in std_logic;
sum : out std_logic;
Cout : out std_logic
);
end FullAdder;
architecture gate of FullAdder is
begin
sum <= A xor B xor Cin ;
Cout <= (A and B) OR (Cin and A) OR (Cin and B) ;
end gate;
here is the N-bit Adder
entity NbitsAdder is
generic(N: integer := 8);
Port(
A : in std_logic_vector((N-1) downto 0);
B : in std_logic_vector((N-1) downto 0);
Cin: in std_logic;
SUM : out std_logic_vector((N-1) downto 0);
Cout : out std_logic
);
end NbitsAdder;
architecture NbitsAdderGate of NbitsAdder is
...
signal temp : std_logic_vector (N downto 0);
begin
temp (0) <= Cin;
arrrayOfFullAdders : for i in 0 to N-1 generate
adder_i: FullAdder port map ( A(i), B(i), temp(i), SUM(i), temp (i+1) );
end generate;
Cout <= temp(N); --which will be extend
end NbitsAdderGate;
And this is the ADDER or SUBTRACTOR
entity NbitsAddOrSub is
generic(N: integer := 8);
port(
A : in std_logic_vector ((N-1) downto 0);
B : in std_logic_vector ((N-1) downto 0);
addOrSub : in std_logic;
sumLo : out std_logic_vector ((N-1) downto 0);
sumHi : out std_logic_vector ((N-1) downto 0)
);
end NbitsAddOrSub;
architecture NbitsAddOrSubGate of NbitsAddOrSub is
signal tempB: std_logic_vector ( (N-1) downto 0);
signal CoutTemp: std_logic;
begin
loop1 : for i in 0 to N-1 generate
xor_i: xorGate port map ( B(i), addOrSub, tempB(i));
end generate;
theOperation : NbitsAdder generic map (N)
port map ( A => A, B => tempB, Cin => addOrSub, sum => sumLo, Cout => CoutTemp);
sumHi <= (N-1 downto 0 => CoutTemp); -- tring to extend the sign bit
end NbitsAddOrSubGate;
In signed addition the carry has no meaning. You get the sign bit from the MSB of the sum and not from the carry. In your second example there is an underflow because -3+-3 is smaller than 2^((N=3)-1), thus the result is incorrect.
To sign-extend the result you should first check the overflow/underflow conditions for signed addition. If no overflow/underflow has occured, you look at the MSB of the sum and extend that bit

Unsigned multiplication in VHDL 4bit vector?

im making an ALU with an option to do A + 2B
but im having trouble getting my head around multiplying the 2B and getting the proper answer in my test bench.
EG: A = 0110 B = 0011
Equation is A + 2B
and im getting 0110
a snippit of my code is
entity ALU is
port( A :IN STD_LOGIC_VECTOR(3 DOWNTO 0) ;
B :IN STD_LOGIC_VECTOR(3 DOWNTO 0) ;
S0 :IN STD_LOGIC ;
S1 :IN STD_LOGIC ;
M :IN STD_LOGIC ;
C0 :IN STD_LOGIC ;
Cout :OUT STD_LOGIC ;
Z :OUT STD_LOGIC ;
F :OUT STD_LOGIC_VECTOR(3 DOWNTO 0));
SIGNAL VariableAlu : STD_LOGIC_VECTOR(3 DOWNTO 0);
SIGNAL FTEMP : STD_LOGIC_VECTOR(3 DOWNTO 0);
SIGNAL FTEMP2 : STD_LOGIC_VECTOR(4 DOWNTO 0);
SIGNAL ZTEMP : STD_LOGIC;
SIGNAL BTEMP1 : STD_LOGIC_VECTOR(4 DOWNTO 0);
END ALU ;
PROCESS(A,B,S0,S1,M,C0)
BEGIN
VariableAlu <= (S0 & S1 & C0 & M);
--M = 1 ARITHMETIC
(part that shifts it, lab teacher told us to do this)
BTEMP1(4 DOWNTO 1)<= B;
BTEMP1(0)<= '0';
when "1111" => FTEMP2 <= ((A) + BTEMP1);
any help would be greatly appreciated.
In addition to what GSM said, you can also just write what you want. I.e. a multiplication by 2. Synthesis software is smart enough to recognize what you are doing.
What you have to remember is that the result will be too large, so it has to be resized.
library IEEE;
use IEEE.std_logic_1164.all;
entity input_output_adder is
port (
input_a : in std_logic_vector(4 downto 0);
input_b : in std_logic_vector(4 downto 0);
output : out std_logic_vector(4 downto 0)
);
end entity;
architecture rtl of input_output_adder is
use IEEE.numeric_std.all;
begin
output <= std_logic_vector(unsigned(input_a) + resize((unsigned(input_b) * 2), 5));
end architecture;
This will result in only LUTs... nu multipliers.
Result from Vivado:
Result from Quartus:
There are a few things to note about your code. Firstly, for any arithmetic, avoid using SLV and stick with unsigned or signed types from the numeric_std library.
Your explicit shift (multiplication by 2) for the operand B:
BTEMP1(4 DOWNTO 1)<= B;
BTEMP1(0)<= '0';
Is, a) not required, and b) verbose. You can achieve this by simply doing BTEMP <= B & '0';, or better yet, don't even use an intermediary signal and assign directly to FTEMP2 in the switch statement. eg.
when "1111" => FTEMP2 <= std_logic_vector(unsigned(A) + unsigned(B&'0'));
Note the conversions in the above line. They are required, as by default, SLV's do not support the + operator (unless you use the std_logic_unsigned or std_logic_signed libraries). You will need to include the numeric_std library for this.
EDIT:
I also forgot to mention that FTEMP will potentially overflow for the given function; F <= A + 2B, where A and B are both 4 bits and F is 5 bits.

Query on VHDL generics in packages

I have written a simple VHDL code to add two matrices containing 32 bit floating point numbers. The matrix dimensions have been defined in a package. Currently, I specify the matrix dimensions in the vhdl code and use the corresponding type from the package. However, I would like to use generic in the design to deal with matrices of different dimensions. For this I would have to somehow use the right type defined in the package. How do I go about doing this?
My current VHDL code is as below.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
use work.mat_pak.all;
entity newproj is
Port ( clk : in STD_LOGIC;
clr : in STD_LOGIC;
start : in STD_LOGIC;
A_in : in t2;
B_in : in t2;
AplusB : out t2;
parallel_add_done : out STD_LOGIC);
end newproj;
architecture Behavioral of newproj is
COMPONENT add
PORT (
a : IN STD_LOGIC_VECTOR(31 DOWNTO 0);
b : IN STD_LOGIC_VECTOR(31 DOWNTO 0);
clk : IN STD_LOGIC;
sclr : IN STD_LOGIC;
ce : IN STD_LOGIC;
result : OUT STD_LOGIC_VECTOR(31 DOWNTO 0);
rdy: OUT STD_LOGIC
);
END COMPONENT;
signal temp_out: t2 := (others=>(others=>(others=>'0')));
signal add_over: t2bit:=(others=>(others=>'0'));
signal check_all_done,init_val: std_logic:='0';
begin
init_val <= '1';
g0: for k in 0 to 1 generate
g1: for m in 0 to 1 generate
add_instx: add port map(A_in(k)(m), B_in(k)(m), clk, clr, start, temp_out(k)(m), add_over(k)(m));
end generate;
end generate;
g2: for k in 0 to 1 generate
g3: for m in 0 to 1 generate
check_all_done <= add_over(k)(m) and init_val;
end generate;
end generate;
p1_add:process(check_all_done,temp_out)
begin
AplusB <= temp_out;
parallel_add_done <= check_all_done;
end process;
end Behavioral;
My package is as below
library IEEE;
use IEEE.STD_LOGIC_1164.all;
use IEEE.NUMERIC_STD.ALL;
package mat_pak is
subtype small_int is integer range 0 to 2;
type t22 is array (0 to 1) of std_logic_vector(31 downto 0);
type t2 is array (0 to 1) of t22; --2*2 matrix
type t22bit is array (0 to 1) of std_logic;
type t2bit is array (0 to 1) of t22bit; --2*2 matrix bit
type t33 is array (0 to 2) of std_logic_vector(31 downto 0);
type t3 is array (0 to 2) of t33; --3*3 matrix
end mat_pak;
Any suggestions would be welcome. Thank you.
There are some logical issues with your design.
First, there's some maximum number of ports for a sub-hierarchy a design can tolerate, you have 192 'bits' of matrix inputs and outputs. Do you really believe this number should be configurable?
At some point it will only fit in the very large FPGA devices, and shortly thereafter not fit there either.
Imagining some operation taking a variable number of clocks in add and parallel_add_done signifies when an aplusb datum is available comprised of elements of the matrix array contributed by all instantiated add components, the individual rdy signals are ANDed together. If the adds all take the same amount of time you could take the rdy from anyone of them (If you silicon is not that deterministic it would not be usable, there are registers in add).
The nested generate statements all assign the result of the AND between add_over(k,m) and init_val (which is a synthesis constant of 1). The effect or wire ANDing add_over(k.m) bits together (which doesn't work in VHDL and is likely not achievable in synthesis, either).
Note I also showed the proper indexing method for the two dimensional arrays.
Using Jonathan's method of sizing matrixes:
library ieee;
use ieee.std_logic_1164.all;
package mat_pak is
type matrix is array (natural range <>, natural range <>)
of std_logic_vector(31 downto 0);
type bmatrix is array (natural range <>, natural range <>)
of std_logic;
end package mat_pak;
library ieee;
use ieee.std_logic_1164.all;
use work.mat_pak.all;
entity newproj is
generic ( size: natural := 2 );
port (
clk: in std_logic;
clr: in std_logic;
start: in std_logic;
a_in: in matrix (0 to size - 1, 0 to size - 1);
b_in: in matrix (0 to size - 1, 0 to size - 1);
aplusb: out matrix (0 to size - 1, 0 to size - 1);
parallel_add_done: out std_logic
);
end entity newproj;
architecture behavioral of newproj is
component add
port (
a: in std_logic_vector(31 downto 0);
b: in std_logic_vector(31 downto 0);
clk: in std_logic;
sclr: in std_logic;
ce: in std_logic;
result: out std_logic_vector(31 downto 0);
rdy: out std_logic
);
end component;
signal temp_out: matrix (0 to size - 1, 0 to size - 1)
:= (others => (others => (others => '0')));
signal add_over: bmatrix (0 to size - 1, 0 to size - 1)
:= (others => (others => '0'));
begin
g0:
for k in 0 to size - 1 generate
g0x:
for m in 0 to size - 1 generate
add_instx: add
port map (
a => a_in(k,m),
b => b_in(k,m),
clk => clk,
sclr => clr,
ce => start,
result => temp_out(k,m),
rdy => add_over(k,m)
);
end generate;
end generate;
aplusb <= temp_out;
p1_add:
process (add_over)
variable check_all_done: std_logic;
begin
check_all_done := '1';
for k in 0 to size - 1 loop
for m in 0 to size -1 loop
check_all_done := check_all_done and add_over(k,m);
end loop;
end loop;
parallel_add_done <= check_all_done;
end process;
end architecture behavioral;
We find that we really want to AND the various rdy outputs (add_over array) together. In VHDL -2008 this can be done with the unary AND, otherwise you're counting on a synthesis tool to flatten the AND (and they generally do).
I made the assignment to aplusb a concurrent assignment.
So I dummied up an add entity with an empty architecture, the above then analyzes, elaborates and simulates, which shows that none of the connectivity has length mismatches anywhere.
I'm not quite sure to understand perfectly, but I'll try to answer anyway ;)
You can use unconstrained array like this:
package mat_pak is
type matrix is array(natural range <>, natural range <>) of std_logic_vector(31 downto 0);
end package mat_pack;
entity newproj is
Generic ( size : natural );
Port ( clk : in STD_LOGIC;
clr : in STD_LOGIC;
start : in STD_LOGIC;
A_in : in matrix(0 to size-1, 0 to size-1);
B_in : in matrix(0 to size-1, 0 to size-1);
AplusB : out matrix(0 to size-1, 0 to size-1);
parallel_add_done : out STD_LOGIC);
end newproj;

Two's complement VHDL

I am just trying to make a simple two's complement device in VHDL but it is throwing back this really annoying error and I'm unsure what I have done wrong. Probably something very silly...The error is
"Error (10327): VHDL error at twocompliment.vhd(21): can't determine definition of operator ""nand"" -- found 0 possible definitions"
The code is
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity twoscompliment is
generic
(
Nbits : positive := 8
);
port
(
--Inputs
A : in std_logic_vector (Nbits-1 downto 0);
--Outputs
Y : out std_logic_vector (Nbits downto 0)
);
end twoscompliment;
architecture twoscompliment_v1 of twoscompliment is
begin
Y <= std_logic_vector(unsigned(A NAND '1') + '1');
end twoscompliment_v1;
Any help would be awesome!
It seems to me you are trying to negate the input number... Maybe I'm missing something vital, but the other answers give a solution which, whilst achieving the goal, appear to be one step more obfuscated than they need to be.
Barring the ugly conversions, what's wrong with
y <= std_logic_vector(-signed(resize(unsigned(A)), y'length));
Of course, I would argue that if A and Y are supposed to be representing signed numbers (or unsigned numbers), they should be expressed as such:
library ieee;
use ieee.numeric_std.all;
entity twoscomplement is
generic
(
Nbits : positive := 8
);
port
(
A : in unsigned (Nbits-1 downto 0);
Y : out signed (Nbits downto 0)
);
end entity twoscomplement;
architecture a1 of twoscomplement is
begin
Y <= -signed(resize(A, Y'length));
end architecture;
Let's check the results:
entity test_twoscomplement is
end entity;
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
architecture test of test_twoscomplement is
signal A : unsigned (7 downto 0);
signal Y : signed(8 downto 0);
begin
dut : entity work.twoscomplement port map (A => A, Y=>Y);
process
begin
for i in 0 to 255 loop
A <= to_unsigned(i, A'length);
wait for 1 ns;
assert to_integer(Y) = -i severity error;
end loop;
report "tests done";
wait;
end process;
end architecture;
Running with GHDL:
$ ghdl -a twoscomp.vhd
$ ghdl --elab-run test_twoscomplement
twoscomp.vhd:40:8:#256ns:(report note): tests done
Success!
Try this:
architecture twoscompliment_v1 of twoscompliment is
signal temp : std_logic_vector(Nbits-1 downto 0);
begin
temp <= not A;
Y <= std_logic_vector(unsigned(temp + 1));
end twoscompliment_v1;
architecture twoscompliment_v1 of twoscompliment is
constant ONE: UNSIGNED(Y'RANGE) := (0 => '1', others => '0');
begin
Y <= std_logic_vector(unsigned (not A) + ONE);
end twoscompliment_v1;
Hi gentleman basically 2's complement is done by inverting the binary bits of a
given no. i.e changing ones to zeroes and zeroes to ones, after that add the
binary bit '1' to the Least significant bit of the given binary number. Now I
have a program
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity twoscomplementconversion is Port (
bin : in STD_LOGIC_VECTOR (3 downto 0);
twos : out STD_LOGIC_VECTOR (3 downto 0)
);
end twoscomplementconversion;
architecture Behavioral of twoscomplementconversion is
component fourbitadder45 Port (
a : in std_logic_vector (3 downto 0);
b : in std_logic_vector(3 downto 0);
cin : in std_logic;
cout : out std_logic;
sum : out std_logic_vector (3 downto 0)
);
end component;
signal onebit : std_logic_vector(3 downto 0):="0001";
signal cin1 : std_logic:='0';
signal notbin : std_logic_vector(3 downto 0);
signal cout1 : std_logic;
begin
notbin <= not(bin);
twos1: fourbitadder45 port map (
a => notbin,
b => onebit,
cin => cin1,
cout => cout1,
sum => twos
);
end Behavioral;
The four bit adder program is given below:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity fourbitadder45 is Port (
a : in std_logic_vector (3 downto 0);
b : in std_logic_vector(3 downto 0);
cin : in std_logic;
cout : out std_logic;
sum : out std_logic_vector (3 downto 0)
);
end fourbitadder45;
architecture Behavioral of fourbitadder45 is
component fulladder2 Port (
a : in std_logic;
b : in std_logic;
cin : in std_logic;
cout : out std_logic;
sum : out std_logic
);
end component;
signal c:std_logic_vector (3 downto 1);
begin
fa1 :fulladder2 port map (a => a(0), b => b(0), cin => cin, cout => c(1), sum => sum(0));
fa2 :fulladder2 port map (a => a(1), b => b(1), cin => c(1), cout => c(2), sum => sum(1));
fa3 :fulladder2 port map (a => a(2), b => b(2), cin => c(2), cout => c(3), sum => sum(2));
fa4 :fulladder2 port map (a => a(3), b => b(3), cin => c(3), cout => cout, sum => sum(3));
end Behavioral;
four bit adder contains 4 full adders so the full adder program is given below:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity fulladder2 is Port (
a : in std_logic;
b : in std_logic;
cin : in std_logic;
cout : out std_logic;
sum : out std_logic
);
end fulladder2;
architecture Behavioral of fulladder2 is
begin
sum <= a xor b xor cin;
cout <= ((a and b) or (b and cin) or (cin and a));
end Behavioral;
I hope that answers the question. This is a method there are many different methods

Resources