VHDL: Signal defined in the architecture not taking the assigned value - vhdl

I'm trying to write VHDL code for a 3 input simple adder. When I type the following code, S gets the correct output value but S1 gets zero, and hence add_out also gets the wrong value.
library ieee;
use ieee.std_logic_1164.all;
entity adder is
port( A,B : in std_logic_vector(3 downto 0);
C : in std_logic;
carry_out : out std_logic;
S : out std_logic_vector(3 downto 0);
addOut : out std_logic_vector(4 downto 0));
end adder;
architecture behavioral of adder is
signal S1 : std_logic_vector(3 downto 0);
begin
proc : process(A,B,C) is
variable carry : std_logic;
begin
carry := C;
for i in 0 to 3 loop
S(i) <= A(i) xor B(i) xor carry;
S1(i) <= A(i) xor B(i) xor carry;
carry := (A(i) and B(i)) or (B(i) and carry) or (A(i) and carry);
end loop;
carry_out <= carry;
addOut <= carry & S1;
end process proc;
end behavioral;
Why is the signal S1 not getting the same value as S?

S1 probably (almost certainly) DOES get the same value as S.
However you wouldn't expect to see that value of S1 on addOut, thanks to the mistake in the process sensitivity list. Study the semantics of signal assignment, (aka "postponed assignment") and delta cycles, and all will become clear. (My usual explanation on this topic, if you'll excuse some self publicity)
Specifically, you have a new value on S1, but no means to wake up the process again to propagate it to any other signal.
The best fix is probably to move the addOut and carryOut assignments outside the process, where they will immediately reflect any changes on their own inputs, and reduce the likelihood of sim/synth mismatches.

Related

VHDL : Internal signals are undefined even when defined in the architecture declaration section

So I've been working on some homework for my VHDL course and I can't seem to understand this problem.
The point here is to create the adder/subtractor of an ALU that works both on 2's complement and unsigned 32-bit buses, which is why I have a condition called sub_mode ( A - B = A + !B + 1 ) which will also be the carry-in when activated.
The rest of the different inputs and outputs are pretty self-explanatory.
My problem is with the testbenching of such component where, even though carry_temp and r_temp have been initialized in declaration section of the architecture, end up showing up undefined. I have guessed that it is due to the for loop within the process screwing everything up. Would that be an accurate guess? And if yes, is it possible to proceed to add two bit buses together without having to fully create an n-bit adder made from n 1-bit adder components?
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity add_sub is
port(
a : in std_logic_vector(31 downto 0);
b : in std_logic_vector(31 downto 0);
sub_mode : in std_logic;
carry : out std_logic;
zero : out std_logic;
r : out std_logic_vector(31 downto 0)
);
end add_sub;
architecture synth of add_sub is
signal cond_inv : std_logic_vector(31 downto 0);
signal carry_temp : std_logic_vector(32 downto 0) := (others => '0');
signal r_temp : std_logic_vector(31 downto 0) := (others => '0');
begin
behave : process(a,b,sub_mode)
begin
if sub_mode = '1' then
cond_inv <= b xor x"ffffffff";
else
cond_inv <= b;
end if;
carry_temp(0) <= sub_mode;
for i in 0 to 31 loop
r_temp(i) <= a(i) xor cond_inv(i) xor carry_temp(i);
carry_temp(i+1) <=
(a(i) and cond_inv(i)) or
(a(i) and carry_temp(i)) or
(cond_inv(i)and carry_temp(i));
end loop;
if r_temp = x"00000000" then
zero <= '1';
else
zero <= '0';
end if;
r <= r_temp;
carry <= carry_temp(32);
end process behave;
end synth;

Incompatibile Slices in VHDL

I am learning VHDL and for first project I picked up simple Brainfuck processor. When I try to compile it, I get error about incompatibile slices. I am using EdWinXP. How do I fix my code? Are there many mistakes in my code? Is there alternative of VHDL that would be simpler for C programmer?
use ieee.std_logic_1164.all;
entity BFCPU is
port (
I0 : in std_logic; --INPUT
I1 : in std_logic; --PROGRAM
I2 : in std_logic; --PROGRAM READY
O1 : out std_logic; --PROGRAM NEEDED
O2 : out std_logic; --OUTPUT
O3 : out std_logic; --OUTPUT WRITTEN
O4 : out std_logic); --INPUT NEEDED
--O5 : out std_logic); --INPUT POOLING CLOCK
end BFCPU;
architecture work of BFCPU is
type t_Memory is array (0 to 127) of std_logic_vector(7 downto 0);
signal rammem : t_Memory;
signal pointer : std_logic;
begin
pointer <= 0;
workflow: process (I2) is
begin
if I1=1 then
rammem(pointer) <= std_logic_vector(unsigned(rammem(pointer)) + 1);
elsif I1=2 then
rammem(pointer) <= std_logic_vector(unsigned(rammem(pointer)) - 1);
elsif I1=3 then
pointer <= pointer - 1;
elsif I1=4 then
pointer <= pointer + 1;
elsif I1=5 then
O2 <= rammem(pointer);
elsif I1=6 then
O4 <= not O4;
inwait: while( I0 = 0 ) loop
if not (I0 = 0) then
rammem(pointer) <= I0;
end if;
end loop inwait;
O4 <= not O4;
end if;
end process workflow;
end work;
What you're writing below the begin statement and outside a process is always true, so this isn't sequential in any form. Imagine like an FPGA pin, which is soldered to ground.
You try to manipulate the pointer signal from within a process, but you can't because your pointer is fixed to '0'.
If you want the pointer initializing to '0', as it looks like, you have to put this line within the process. However, i see you try to call arithmetic operations with the pointer signal, but you are defining the signal as std_logic. std_logic can represent '0', '1' and several other states, like High-Z, but not a number. You should take an integer or natural for calculations.

VHDL- increment and decrement push button

I am trying to increment and decrement with two push-buttons. The algorithm goes well but I have a little issue. Supposedly I am incrementing , when I try to decrement the accumulator it increments once more , and only after that it start
to decrement. Same if I try to decrement first. If it is someone to help me I will be very thankfully.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
use IEEE.std_logic_unsigned.all;
entity my_offset_controller is
port(clk : in std_logic;
input : in std_logic_vector(15 downto 0);
add_button : in std_logic;
sub_button : in std_logic;
output_res : out std_logic_vector(15 downto 0)
);
end my_offset_controller;
architecture Behavioral of my_offset_controller is
signal buttonState_up : std_logic:='0';
signal accumulator : std_logic_vector(15 downto 0);
signal lastButtonState_up : std_logic:='0';
signal buttonState_down : std_logic:='0';
signal lastButtonState_down : std_logic:='0';
signal buttonPushCounter : integer range 0 to 512 :=0;
process(clk)
begin
if rising_edge(clk) then
buttonState_up <= add_button;
buttonState_down <= sub_button;
if (buttonState_up /= lastButtonState_up) then
if (buttonState_up ='1') then
buttonPushCounter <= buttonPushCounter + 1;
accumulator <= std_logic_vector(to_unsigned(buttonPushCounter,accumulator'length));
end if;
lastButtonState_up <= buttonState_up;
elsif (buttonState_down /= lastButtonState_down) then
if (buttonState_down ='1') then
buttonPushCounter <= buttonPushCounter - 1;
accumulator <= std_logic_vector(to_unsigned(buttonPushCounter,accumulator'length));
end if;
lastButtonState_down <= buttonState_down;
end if;
end if;
end process;
output_res<= accumulator + input ;
This particularly module I use to controll the offset of an signal that I plot on an vga screen.
It's hard to help you without more information. You should provide a testbench with a chronogram to make it easier. Yet, by looking at your process I would say that the problem comes from the following lines:
buttonPushCounter <= buttonPushCounter + 1;
accumulator <= std_logic_vector(to_unsigned(buttonPushCounter,accumulator'length));
What you did there is increment buttonPushCounterat the same time that you update accumulator. This way buttonPushCounter will always be shifted by +1 or -1 depending on the last event.
What I can recommend is to update accumulator at every clock cycle instead of every time an event occurs. For example like this:
if rising_edge(clk) then
accumulator <= std_logic_vector(to_unsigned(buttonPushCounter,accumulator'length));
...

generic adder "inference architecture": simulation error

So, I have to create a generic N-bit adder with carry in and carry out.
I have made two fully working architectures so far, one using the generate function and one using the rtl description as follows:
entity:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity adder_n is
generic (N: integer:=8);
port (
a,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 adder_n;
architectures 1 and 2:
--STRUCT
architecture struct of adder_n is
component f_adder
port (
a,b,cin: in std_logic;
s,cout: out std_logic);
end component;
signal c: std_logic_vector(0 to N);
begin
c(0)<=cin;
cout<=c(N);
adders: for k in 0 to N-1 generate
A1: f_adder port map(a(k),b(k),c(k),s(k),c(k+1));
end generate adders;
end struct;
--END STRUCT
architecture rtl of adder_n is
signal c: std_logic_vector(1 to N);
begin
s<=(a xor b) xor (cin&c(1 to N-1));
c<=((a or b) and (cin&c(1 to N-1))) or (a and b);
cout<=c(N);
end rtl;
Now, my problem is in the third architecture where I'm trying to infer the adder. Even though the following architecture I created compiles just fine, when I try to simulate it, I get a simulation error (on Modelsim), which I have attached at the end of this post.
I'm guessing there's something wrong with the numeric_std definitions. I am trying to avoid the arith library and I'm still trying to get used to the IEEE standard.
Any ideas are welcomed!! Thank you!
Inference arch:
--INFERENCE
architecture inference of adder_n is
signal tmp: std_logic_vector(0 to N);
signal atmp, btmp, ctmp, add_all : integer :=0;
signal cin_usgn: std_logic_vector(0 downto 0);
signal U: unsigned(0 to N);
begin
atmp <= to_integer(unsigned(a));
btmp <= to_integer(unsigned(b));
cin_usgn(0) <= cin;
ctmp <= to_integer(unsigned(cin_usgn));
add_all <= (atmp + btmp + ctmp);
U <= to_unsigned(add_all,N);
tmp <= std_logic_vector(U);
s <= tmp(0 to N-1);
cout <= tmp(N);
end inference;
-- END
Simulation error:
# Cannot continue because of fatal error.
# HDL call sequence:
# Stopped at C:/altera/14.1/modelsim_ase/test1_simon/adder_inference.vhd 58 Architecture inference
The length of U is N+1 (0 to N)
Changing
U <= to_unsigned(add_all,N);
To
U <= to_unsigned(add_all,N+1);
Will prevent a length mismatch between the left hand side and right hand side of the signal assignment in architecture inference of adder_n.
The passed parameter to to_unsigned specifies the length.

Why it is necessary to use internal signal for process?

I'm learning VHDL from the root, and everything is OK except this. I found this from Internet. This is the code for a left shift register.
library ieee;
use ieee.std_logic_1164.all;
entity lsr_4 is
port(CLK, RESET, SI : in std_logic;
Q : out std_logic_vector(3 downto 0);
SO : out std_logic);
end lsr_4;
architecture sequential of lsr_4 is
signal shift : std_logic_vector(3 downto 0);
begin
process (RESET, CLK)
begin
if (RESET = '1') then
shift <= "0000";
elsif (CLK'event and (CLK = '1')) then
shift <= shift(2 downto 0) & SI;
end if;
end process;
Q <= shift;
SO <= shift(3);
end sequential;
My problem is the third line from bottom. My question is, why we need to pass the internal signal value to the output? Or in other words, what would be the problem if I write Q <= shift (2 downto 0) & SI?
In the case of the shown code, the Q output of the lsr_4 entity comes from a register (shift representing a register stage and being connected to Q). If you write the code as you proposed, the SI input is connected directly (i.e. combinationally) to the Q output. This can also work (assuming you leave the rest of the code in place), it will perform the same operation logically expect eliminate one clock cycle latency. However, it's (generally) considered good design practice to have an entity's output being registered in order to not introduce long "hidden" combinational paths which are not visible when not looking inside an entity. It usually makes designing easier and avoids running into timing problems.
First, this is just a shift register, so no combinational blocks should be inferred (except for input and output buffers, which are I/O related, not related to the circuit proper).
Second, the signal called "shift" can be eliminated altogether by specifying Q as "buffer" instead of "out" (this is needed because Q would appear on both sides of the expression; "buffer" has no side effects on the inferred circuit). A suggestion for your code follows.
Note: After compiling your code, check in the Netlist Viewers / Technology Map Viewer tool what was actually implemented.
library ieee;
use ieee.std_logic_1164.all;
entity generic_shift_register is
generic (
N: integer := 4);
port(
CLK, RESET, SI: in std_logic;
Q: buffer std_logic_vector(N-1 downto 0);
SO: out std_logic);
end entity;
architecture sequential of generic_shift_register is
begin
process (RESET, CLK)
begin
if (RESET = '1') then
Q <= (others => '0');
elsif rising_edge(CLK) then
Q <= Q(N-2 downto 0) & SI;
end if;
end process;
SO <= Q(N-1);
end architecture;

Resources