I was trying to make both, the ripple carry and the look ahead N-bits adder, when I made the N-bits full-adder I decided to reuse it to the look ahead, but just doesn't feels right to me.
Full adder:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity FullAdder is
Port (
FA_A : in STD_LOGIC;
FA_B : in STD_LOGIC;
FA_Cin : in STD_LOGIC;
FA_S : out STD_LOGIC;
FA_Cout : out STD_LOGIC
);
end FullAdder;
architecture Behavior of FullAdder is
begin
FA_S <= FA_A XOR FA_B XOR FA_Cin ;
FA_Cout <= (FA_A AND FA_B) OR (FA_Cin AND FA_A) OR (FA_Cin AND FA_B);
end Behavior;
The N-bits block:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity FullAdderNBits is
Generic( N : integer := 8 );
Port (
A : in STD_LOGIC_VECTOR(0 to N-1);
B : in STD_LOGIC_VECTOR(0 to N-1);
Cin : in STD_LOGIC;
S : out STD_LOGIC_VECTOR(0 to N-1);
Cout : out STD_LOGIC
);
end FullAdderNBits;
architecture Behavior of FullAdderNBits is
signal temp_B : STD_LOGIC_VECTOR(0 to N-1);
signal carries : STD_LOGIC_VECTOR(0 to N);
component FullAdder Port(
FA_A : in STD_LOGIC;
FA_B : in STD_LOGIC;
FA_Cin : in STD_LOGIC;
FA_S : out STD_LOGIC;
FA_Cout : out STD_LOGIC
);
end component;
begin
temp_B <= not B when Cin = '1' else B;
carries(N) <= Cin;
ForGenerate: for i in (N-1) downto 0 generate
UX: FullAdder port map(
A(i),
temp_B(i),
carries(i+1),
S(i),
carries(i)
);
end generate ForGenerate;
Cout <= carries(0);
end Behavior;
Look Ahead:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity LookAheadAdder is
Port (
LAA_A : in STD_LOGIC;
LAA_B : in STD_LOGIC;
LAA_Cin : in STD_LOGIC;
LAA_S : out STD_LOGIC;
LAA_Cout : out STD_LOGIC
);
end LookAheadAdder;
architecture Behavior of LookAheadAdder is
signal P : STD_LOGIC;
signal G : STD_LOGIC;
begin
P <= LAA_A xor LAA_B;
G <= LAA_A and LAA_B;
LAA_S <= P xor LAA_Cin;
LAA_Cout <= G or (P and LAA_Cin);
end Behavior;
Same N-bits block, just changed the component:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity LookAheadNBitsAdder is
Generic( N : integer := 8 );
Port (
A : in STD_LOGIC_VECTOR(0 to N-1);
B : in STD_LOGIC_VECTOR(0 to N-1);
Cin : in STD_LOGIC;
S : out STD_LOGIC_VECTOR(0 to N-1);
Cout : out STD_LOGIC
);
end LookAheadNBitsAdder;
architecture Behavior of LookAheadNBitsAdder is
signal temp_B : STD_LOGIC_VECTOR(0 to N-1);
signal carries : STD_LOGIC_VECTOR(0 to N);
component LookAheadAdder Port(
LAA_A : in STD_LOGIC;
LAA_B : in STD_LOGIC;
LAA_Cin : in STD_LOGIC;
LAA_S : out STD_LOGIC;
LAA_Cout : out STD_LOGIC
);
end component;
begin
temp_B <= not B when Cin = '1' else B;
carries(N) <= Cin;
ForGenerate: for i in (N-1) downto 0 generate
UX: LookAheadAdder port map(
A(i),
temp_B(i),
carries(i+1),
S(i),
carries(i)
);
end generate ForGenerate;
Cout <= carries(0);
end Behavior;
How can I test with one is faster? I dont have a FPGA so can I do it with ModelSim? I tried simulate but doesn't looks like the propagation make any delay, the wave just jump from a state to another.
Both of these are written as combinational logic. Meaning the input will immediately propagate to the output. The only way to see which is "faster" would be to introduce a clock and start counting clock cycles. You can see which would use less resources on the chip, but if they're both written in combinational logic (not sequential) then in simulation the output will be immediate.
Related
Heyo!
I've been trying to get into programming vhdl again for some upcoming classes and tried to do an simple 8-bit adder and wanted to test it with a testbench. (I'm working with the Vivado Xilinx Software btw~)
I don't get any syntax errors, but it shows the variables as "U" (I guess undefined?)
Hope it's easy to see what I did (and why lol). Yea but I can't really find the problem??
My code:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity addierer is
Port ( a : in STD_LOGIC_VECTOR(7 downto 0);
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 addierer;
architecture Behavioral of addierer is
COMPONENT volladdierer is
Port ( a : in STD_LOGIC;
b : in STD_LOGIC;
cin : in STD_LOGIC;
s : out STD_LOGIC;
cout : out STD_LOGIC
);
end COMPONENT;
signal c : STD_LOGIC_VECTOR(6 downto 0);
begin
PROCESS (a,b,cin)
BEGIN
s(0) <= a(0) xor b(0) xor cin; --erstes s wird noch mit cin berechnet
c(0) <= (cin and b(0)) or (cin and a(0)) or (a(0) and b(0)); --sowie das erste cout
for i in 1 to 7 loop --Schleife um Stellen der Arrays durchzugehen
s(i) <= a(i) xor b(i) xor c(i-1);
c(i) <= (c(i-1) and b(i)) or (c(i-1) and a(i)) or (a(i) and b(i));
end loop;
cout <= c(6);
END PROCESS;
end Behavioral;
testbench I used:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity testbench_addierer is
-- Port ( );
end testbench_addierer;
architecture Behavioral of testbench_addierer is
SIGNAL a : STD_LOGIC_VECTOR(7 downto 0);
SIGNAL b : STD_LOGIC_VECTOR(7 downto 0);
SIGNAL cin : STD_LOGIC;
SIGNAL s : STD_LOGIC_VECTOR(7 downto 0);
SIGNAL cout : STD_LOGIC;
COMPONENT addierer IS
PORT(
a : IN STD_LOGIC_VECTOR(7 downto 0);
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;
begin
U1: addierer
PORT MAP(
a => a,
b => b,
cin => cin,
s => s,
cout => cout
);
process
begin
a <= "00000000" after 0ms;
a <= "00000001" after 10ms;
a <= "01010101" after 20ms;
b <= "00000000" after 0ms;
b <= "10001001" after 10ms;
b <= "00000001" after 20ms;
cin <= '0' after 0ms;
cin <= '0' after 10ms;
cin <= '0' after 20ms;
end process;
end Behavioral;
Thanks already and hmu if something's unclear in my code!!
(and pls keep in mind I'm an total beginner.. xD)
I have a VHDL component that is connected to a UART receiver. The uart has 2 output signals, one for the byte received and one for a flag that is set to 1 when the byte is done being received.
I have written the following module that should increment a counter for every new char and show it lighting up some leds.
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
use ieee.numeric_std.all;
entity test is
port (
clk : in std_logic;
rst : in std_logic;
ena : in std_logic;
rx : in std_logic;
led0 : out std_logic;
led1 : out std_logic;
led2 : out std_logic;
led3 : out std_logic;
led4 : out std_logic;
led5 : out std_logic;
led6 : out std_logic;
led7 : out std_logic
);
end test;
architecture arch of test is
component UART_RX
generic (
g_CLKS_PER_BIT : integer := 115 -- Needs to be set correctly
);
port (
i_Clk : in std_logic;
i_RX_Serial : in std_logic;
o_RX_DV : out std_logic;
o_RX_Byte : out std_logic_vector(7 downto 0)
);
end component;
signal sig_Din : std_logic_vector(7 downto 0);
signal sig_Dout : std_logic_vector(7 downto 0);
signal sig_RxErr : std_logic;
signal sig_RxRdy : std_logic;
signal sig_TxBusy : std_logic;
signal sig_StartTx: std_logic;
begin
UUT : UART_RX
generic map (
g_CLKS_PER_BIT => 434
)
port map (
i_clk => clk,
i_rx_serial => rx,
o_rx_dv => sig_RxRdy,
o_rx_byte => sig_Dout
);
process(clk)
variable position : integer := 0;
variable position_v : std_logic_vector(7 downto 0) := "00000000";
begin
if(sig_RxRdy = '1') then
position := position + 1;
position_v := std_logic_vector((unsigned(position_v1), 1));
led0 <= position_v(0);
led1 <= position_v(1);
led2 <= position_v(2);
led3 <= position_v(3);
led4 <= position_v(4);
led5 <= position_v(5);
led6 <= position_v(6);
led7 <= position_v(7);
end if;
end process;
end arch;
Is there any problem with the implementation? Every new char i send ends up incrementing the counter by more than 1. And is not even the same value every time.
I must not be understanding how FPGAs actually work because this is simple and I can't get it to work.
You are using sig_RxRdy as condition for incrementing. But we can not see how that signal behaves as it comes out of a module for which we have no code.
From the behavior you describe the o_rx_dv output (where sig_RxRdy comes from) is likely to be high for more then one of your clk cycles. As the UART input comes from an external source the time it is high may be variable which makes that you counter increment differs.
Solution is to detect a rising edge on sig_RxRdy by using a delayed version:
prev_sig_RxRdy <= sig_RxRdy;
sig_RxRdy_rising <= sig_RxRdy and not prev_sig_RxRdy;
Then increment your counters on that signal. This only works if o_rx_dv is already synchronous to your clock.
I tried to simulate a TFF using Xilinx ISE web pack and ModelSim using following block diagram and structural Code was written using VHDL. But I am unable to get the correct waveform. Due to the T-flip flop is sequential circuit, first I gave the output value as 1 or 0 for one output (Q) to start to the process.
T flip flop truth table and block diagram
simulation waveform
code for AND gate:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity AND_GATE is
Port ( X : in STD_LOGIC;
Y : in STD_LOGIC;
W : in STD_LOGIC;
Z : out STD_LOGIC);
end AND_GATE;
architecture Behavioral of AND_GATE is
begin
Z <= X AND Y AND W;
end Behavioral;
code for NOR gate:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity NOR_GATE is
Port ( A : in STD_LOGIC;
B : in STD_LOGIC;
C : out STD_LOGIC);
end NOR_GATE;
architecture Behavioral of NOR_GATE is
begin
c <= A NOR B;
end Behavioral;
code for T-FF:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity TFF_2 is
Port ( T : in STD_LOGIC;
CLK : in STD_LOGIC;
Q : inout STD_LOGIC;
s : inout STD_LOGIC);
end TFF_2;
architecture STRUCTURAL of TFF_2 is
--declare components being used in T -FF
component TFF is
Port ( T : in STD_LOGIC;
CLK : in STD_LOGIC;
RST : in STD_LOGIC;
Q : out STD_LOGIC);
end component;
component NOR_GATE is
Port ( A : in STD_LOGIC;
B : in STD_LOGIC;
C : out STD_LOGIC);
end component;
component AND_GATE is
Port ( X : in STD_LOGIC;
Y : in STD_LOGIC;
W : in STD_LOGIC;
Z : out STD_LOGIC);
end component;
--declare signals
signal S1, S2 : STD_LOGIC;
begin
C1 : AND_GATE port map (Q, T, CLK, S1);
C2 : AND_GATE port map (S, T, CLK, S2);
C3 : NOR_GATE port map (S1, S, Q);
C4 : NOR_GATE port map (S2, Q, S);
end STRUCTURAL;
These files synthesized without any errors but in the simulation expected output was not given.
There are a few suggestions I have.
There are non initialised variables. Add := '0'; at the end of the declarations. Simulation might show "X" or unknown. The Synthesised design will work OK, being the hardware will go to one or zero, but simulators need to be directed.
Some of your output variables have feedback into inputs. The design is asynchronous, being that you are not using a clock of some description to time the iterations. Consider using a process and something like if rising_edge(clk)
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
I'm learning VHDL and I've come to a halt. I'd like to create a simple gate out of smaller gates (a NAND gate here). Here's the code:
library IEEE;
use IEEE.STD_LOGIC_1164.all;
entity ANDGATE2 is
port(
x,y : in STD_LOGIC;
z : out STD_LOGIC
);
end ANDGATE2;
architecture ANDGATE2 of ANDGATE2 is
begin
z <= x AND y;
end ANDGATE2;
library IEEE;
use IEEE.STD_LOGIC_1164.all;
entity NOTGATE1 is
port(
x : in STD_LOGIC;
z : out STD_LOGIC
);
end NOTGATE1;
architecture NOTGATE1 of NOTGATE1 is
begin
z <= NOT x;
end NOTGATE1;
library ieee;
use ieee.std_logic_1164.all;
entity NANDGATE2 is
port(
x : in STD_LOGIC;
y : in STD_LOGIC;
z : out STD_LOGIC
);
end NANDGATE2;
architecture NANDGATE2 of NANDGATE2 is
signal c, d: std_logic;
component NOTGATE1
port(
n_in : in STD_LOGIC;
n_out : out STD_LOGIC
);
end component;
component ANDGATE2
port(
a_in1, a_in2 : in STD_LOGIC;
a_out : out STD_LOGIC
);
end component;
begin
N0: ANDGATE2
port map(x, y, c);
N1: NOTGATE1
port map(c, d);
z <= d;
end NANDGATE2;
Here's the code from some tutorial I've been using as a template; it compiles with no problems.
library ieee;
use ieee.std_logic_1164.all;
-- definition of a full adder
entity FULLADDER is
port
(
a, b, c: in std_logic;
sum, carry: out std_logic
);
end FULLADDER;
architecture fulladder_behav of FULLADDER is
begin
sum <= (a xor b) xor c ;
carry <= (a and b) or (c and (a xor b));
end fulladder_behav;
-- 4-bit adder
library ieee;
use ieee.std_logic_1164.all;
entity FOURBITADD is
port
(
a, b: in std_logic_vector(3 downto 0);
Cin : in std_logic;
sum: out std_logic_vector (3 downto 0);
Cout, V: out std_logic
);
end FOURBITADD;
architecture fouradder_structure of FOURBITADD is
signal c: std_logic_vector (4 downto 0);
component FULLADDER
port
(
a, b, c: in std_logic;
sum, carry: out std_logic
);
end component;
begin
FA0: FULLADDER
port map (a(0), b(0), Cin, sum(0), c(1));
FA1: FULLADDER
port map (a(1), b(1), C(1), sum(1), c(2));
FA2: FULLADDER
port map (a(2), b(2), C(2), sum(2), c(3));
FA3: FULLADDER
port map (a(3), b(3), C(3), sum(3), c(4));
V <= c(3) xor c(4);
Cout <= c(4);
end fouradder_structure;
My code compiles with no errors, but with two warnings:
# Warning: ELAB1_0026: p2.vhd : (85, 0): There is no default binding for component "andgate2".(Port "a_in1" is not on the entity).
# Warning: ELAB1_0026: p2.vhd : (87, 0): There is no default binding for component "notgate1".(Port "n_in" is not on the entity).
What gives?
You need to use the same port names on your component and entity declarations.
Right now, for example in your NOTGATE1 entity declaration, you have input port x and output port z, but in the NANDGATE2 architecture, you declare the NOTGATE1 component to have ports n_in and n_out.
This won't cause problems during compilation, since compilation looks at a single unit at a time, and won't see the actual entities. In the elaboration phase, your tools will try to match up the entities to components, but this will fail since the ports don't match.
Not 100% sure, but I think the pins in your component declarations need to match up to the ones in your entity blocks:
component NOTGATE1
port(
x : in STD_LOGIC;
z : out STD_LOGIC
);
end component;
component ANDGATE2
port(
x,y : in STD_LOGIC;
z : out STD_LOGIC
);
Always use explicit port bindings in your port maps, like
port map(a_in1 => x,
a_in2 => y,
a_out => c);
It will make your code also more clear. In big projects it is the first rule of thumb.