Issue with using component and forloop in VHDL - vhdl

I am trying to create a component for division in VHDL, below is my code. I dont know where i am going wrong. My logic is:
At every step,
• shift divisor right and compare it with current dividend
• if divisor is larger, shift 0 as the next bit of the quotient
• if divisor is smaller, subtract to get new dividend and shift 1
as the next bit of the quotient.
I have used '-' sign here but in actual i have to use gates so either i have to use my subtraction component or just create a subtractor here.
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.std_logic_arith.all;
ENTITY divprog IS
PORT(
a: IN std_logic_vector(3 downto 0);
b: IN std_logic_vector(3 downto 0);
err: OUT std_logic;
reslow: OUT std_logic_vector(3 downto 0);
reshigh: OUT std_logic_vector(3 downto 0));
END divprog;
architecture behaviour of divprog is
signal ax,bx,bsub,res :std_logic_vector(7 downto 0) := (others => '0');
signal quo: std_logic_vector(3 downto 0) := (others => '0');
signal intcarry: std_logic_vector(8 downto 0):= (others => '0');
BEGIN
--sub1: subtractor PORT MAP(aa,bb,x,ss);
Process is
variable i : POSITIVE := 1;
BEGIN
ax <= "0000" & a;
bx <= b & "0000";
if(b > "0000") then
while (i <=3) loop
bx <= '0'&bx(7 downto 1);
IF (ax < bx) then
quo <= quo(2 downto 0)& '0';
--bx <= '0'&bx(7 downto 1);
res <=ax;
elsif(ax >= bx) then
res <= ax - bx;
quo <=quo(2 downto 0)& '1';
end if;
i := i + 1;
ax <= res;
end loop;
reshigh <= quo;
reslow <= res(3 downto 0);
end IF;
wait for 100 ns;
END PROCESS;
end behaviour;
Can please someone help me with this?
Thanks

The functional problem is related to variable i. It gets stuck at 4 after the first 100ns. It should be set to 1 between BEGIN and END PROCESS.

Related

Spikes or glitches in Modelsim

I've been learning VHDL for a while and I'm making a project right now. I made a NCO (Numerically controlled Oscillator) and a cordic algorithm to produce sine and cosine with a certain frequency.
I don't know why I get spikes on my waves in Modelsim. I guess they are caused by the case statement when it changes the quadrant for the cordic algorithm to work with angles between -180 and +180.
I've read that it could be a "normal" behavior of Modelsim because of the iterations of the simulator (VHDL delta cycles). But I don't know how and if I should fix them.
LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE ieee.numeric_std.all;
ENTITY phase_accumulator_module IS
GENERIC (
LGTBL: INTEGER := 16; --lunghezza table log base 2
W: INTEGER := 32;
OW: INTEGER := 16
);
PORT (
clk: IN STD_LOGIC;
reset: IN STD_LOGIC;
i_dphase: IN STD_LOGIC_VECTOR(W-1 DOWNTO 0);
o_val: BUFFER STD_LOGIC_VECTOR(W-1 DOWNTO 0);
o_val_test:BUFFER STD_LOGIC_VECTOR(OW-1 DOWNTO 0);
o_val_laser: BUFFER STD_LOGIC_VECTOR(W-1 DOWNTO 0);
quadrant: BUFFER STD_LOGIC_VECTOR(1 DOWNTO 0)
);
END phase_accumulator_module;
ARCHITECTURE behave OF phase_accumulator_module IS
SIGNAL r_step,r_step_laser,r_step_test: STD_LOGIC_VECTOR(W-1 DOWNTO 0) := (OTHERS => '0');
SIGNAL r_phase,r_phase_laser,r_phase_test: STD_LOGIC_VECTOR(W-1 DOWNTO 0) := (OTHERS => '0');
SIGNAL r_phase_pipe,r_phase_laser_pipe: STD_LOGIC_VECTOR(W-1 DOWNTO 0) := (OTHERS => '0');
CONSTANT P: INTEGER := LGTBL;
BEGIN
R_Step_pro: PROCESS(clk,reset)
BEGIN
IF(reset='1') THEN
r_step <= (OTHERS=>'0');
r_step_test <= (OTHERS=>'0');
r_step_laser <= (OTHERS=>'0');
ELSE IF(rising_edge(clk)) THEN
r_step <= i_dphase; -- 2^W*f/fs
r_step_test <= i_dphase; --test signal
r_step_laser <= STD_LOGIC_VECTOR(SHIFT_RIGHT(UNSIGNED(i_dphase),1));
END IF;
END IF;
END PROCESS R_Step_pro;
R_phase_pro: PROCESS(clk,reset)
BEGIN
IF(reset='1') THEN
r_phase <= (OTHERS=>'0');
r_phase_test <= (OTHERS=>'0');
r_phase_laser <= (OTHERS=>'0');
o_val <= (OTHERS=>'0');
o_val_test <= (OTHERS=>'0');
o_val_laser <= (OTHERS=>'0');
ELSE IF(rising_edge(clk)) THEN
r_phase <= STD_LOGIC_VECTOR(UNSIGNED(r_phase) + UNSIGNED(r_step));
r_phase_test <= STD_LOGIC_VECTOR(UNSIGNED(r_phase_test) + UNSIGNED(r_step_test)); --test signal
r_phase_laser <= STD_LOGIC_VECTOR(UNSIGNED(r_phase_laser) + UNSIGNED(r_step_laser));
quadrant <= r_phase(W-1 DOWNTO w-2);
CASE quadrant IS
WHEN "00" | "11" =>
r_phase_pipe <= r_phase;
r_phase_laser_pipe <= r_phase_laser;
WHEN "01" =>
r_phase_pipe <= "00" & r_phase(W-3 DOWNTO 0);
r_phase_laser_pipe <= "00" & r_phase_laser(W-3 DOWNTO 0);
WHEN "10" =>
r_phase_pipe <= "11" & r_phase(W-3 DOWNTO 0);
r_phase_laser_pipe <= "11" & r_phase_laser(W-3 DOWNTO 0);
WHEN OTHERS =>
null;
END CASE;
o_val_test <= r_phase_test(W-1 DOWNTO W-P);
o_val <= r_phase_pipe;
o_val_laser <= r_phase_laser_pipe;
END IF;
END IF;
END PROCESS R_phase_pro;
END behave;
This is the cordic algotithm vhdl file:
LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE ieee.numeric_std.all;
ENTITY signal_gen_cordic_module IS
GENERIC (
bits: INTEGER := 16;
bits_out_c: INTEGER := 32;
iter : INTEGER := 32
);
PORT (
clk: IN STD_LOGIC;
reset: IN STD_LOGIC;
locked: IN STD_LOGIC;
z0: IN STD_LOGIC_VECTOR (bits_out_c-1 DOWNTO 0);
quadrant: IN STD_LOGIC_VECTOR(1 DOWNTO 0);
sine,cosine: BUFFER STD_LOGIC_VECTOR(bits-1 DOWNTO 0)
);
END signal_gen_cordic_module;
ARCHITECTURE behave OF signal_gen_cordic_module IS
TYPE temp IS ARRAY (0 TO iter-1) OF STD_LOGIC_VECTOR(bits_out_c-1 DOWNTO 0);
SIGNAL x_temp,y_temp,z_temp: temp;
CONSTANT x0: SIGNED(bits_out_c-1 DOWNTO 0) := "00000000000000000010111100011010"; --0.6072*2^16
CONSTANT y0: SIGNED(bits_out_c-1 DOWNTO 0) := "00000000000000000000000000000000";
SIGNAL x00,y00: SIGNED(bits_out_c-1 DOWNTO 0);
TYPE atand IS ARRAY (0 TO iter-1) OF STD_LOGIC_VECTOR(bits_out_c-1 DOWNTO 0);
CONSTANT arctan: atand :=
(
x"20000000",
x"12E4051E",
x"09FB385B",
x"051111D4",
x"028B0D43",
x"0145D7E1",
x"00A2F61E",
x"00517C55",
x"0028BE53",
x"00145F2F",
x"000A2F98",
x"000517CC",
x"00028BE6",
x"000145F3",
x"0000A2FA",
x"0000517D",
x"000028BE",
x"0000145F",
x"00000A30",
x"00000518",
x"0000028C",
x"00000146",
x"000000A3",
x"00000051",
x"00000029",
x"00000014",
x"0000000A",
x"00000005",
x"00000003",
x"00000001",
x"00000001",
x"00000000"
);
BEGIN
PROCESS(clk,reset)
BEGIN
IF(reset='1') THEN
cosine <= (OTHERS=>'0');
sine <= (OTHERS=>'0');
FOR i IN iter-1 DOWNTO 0 LOOP
x_temp(i) <= (OTHERS=>'0');
y_temp(i) <= (OTHERS=>'0');
z_temp(i) <= (OTHERS=>'0');
END LOOP;
ELSE IF(rising_edge(clk)) THEN
IF(locked='1') THEN
IF(quadrant="00" OR quadrant="11") THEN
x00 <= x0;
y00 <= y0;
ELSE IF(quadrant="01") THEN
x00 <= -y0;
y00 <= x0;
ELSE
x00 <= y0;
y00 <= -x0;
END IF;
END IF;
x_temp(0) <= STD_LOGIC_VECTOR(x00);
y_temp(0) <= STD_LOGIC_VECTOR(y00);
z_temp(0) <= z0;
FOR i IN 0 TO iter-2 LOOP
IF(z_temp(i)(z0'HIGH)='1') THEN
x_temp(i+1) <= STD_LOGIC_VECTOR(SIGNED(x_temp(i)) + SHIFT_RIGHT(SIGNED(y_temp(i)),i));
y_temp(i+1) <= STD_LOGIC_VECTOR(SIGNED(y_temp(i)) - SHIFT_RIGHT(SIGNED(x_temp(i)),i));
z_temp(i+1) <= STD_LOGIC_VECTOR(SIGNED(z_temp(i)) + SIGNED(arctan(i)));
ELSE
x_temp(i+1) <= STD_LOGIC_VECTOR(SIGNED(x_temp(i)) - SHIFT_RIGHT(SIGNED(y_temp(i)),i));
y_temp(i+1) <= STD_LOGIC_VECTOR(SIGNED(y_temp(i)) + SHIFT_RIGHT(SIGNED(x_temp(i)),i));
z_temp(i+1) <= STD_LOGIC_VECTOR(SIGNED(z_temp(i)) - SIGNED(arctan(i)));
END IF;
END LOOP;
cosine <= STD_LOGIC_VECTOR(RESIZE(SIGNED(x_temp(iter-1)),bits));
sine <= STD_LOGIC_VECTOR(RESIZE(SIGNED(y_temp(iter-1)),bits));
END IF;
END IF;
END IF;
END PROCESS;
END behave;
My modelsim version is 10.5b. Thank you for any help! :)

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;

How to fill a vector bit by bit

I have a 12 bits vector called RDIBits and a in std_logic called InUartToUart. My question is: every time the clock goes to '1', i receive a bit in InUartToUart, and i want to concat all the 12 bits that i will receive in the RDIBits vector. Basically, its a serial communication, thats why i receive 1 bit each time. Is there any simple way to do this? Something similar to RDIBits += InUartToUart in JAVA.
I would code this slightly differently. Maybe consider this.
Sorry about the formatting, Im new to this site. I have also shown how you can initialise the variable.
signal RDIBits : std_logic_vector(11 downto 0) := (Others => '0');
...
process(clk)
begin
if ( rising_edge(clk) ) then
RDIBits(11 downto 1) <= RDIBits(10 downto 0);
RDIBits(0) <= InUartToUart;
end if;
end process;
I added some more things, like the entity, the IOs and a counter for the output register.
LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE ieee.numeric_std.all;
ENTITY my_uart IS
PORT(
clk : IN std_logic; -- system clock
rst : IN std_logic; -- reset high active
---------------------------------------------
InUartToUart : IN std_logic;
DataOut : OUT std_logic_vector(11 downto 0)
);
END ENTITY;
ARCHITECTURE struct OF my_uart IS
signal RDIBits : std_logic_vector(11 downto 0);
signal counter : integer range 0 to 12;
begin
calc_proc: process(clk, rst)
begin
if (rst = '1') then
RDIBits <= (others => '0');
counter <= 0;
elsif ( rising_edge(clk) ) then
if (counter < 12) then
RDIBits <= RDIBits(10 downto 0) & InUartToUart;
counter <= counter + 1;
elsif (counter = 12) then
DataOut <= RDIBits;
counter <= 0;
end if;
end if;
end process;
END STRUCT;
This is a typical shift register application. For example:
signal RDIBits : std_logic_vector(11 downto 0);
...
process(clk)
begin
if ( rising_edge(clk) ) then
RDIBits <= RDIBits(10 downto 0) & InUartToUart;
end if;
end process;

Why is this Shift Register not loading properly in VHDL?

I have a custom designed shift register that has as input DL(leftmost input), DR(rightmost), CLR that clears and loads DR, S that shifts right and W that loads leftmost. After testing it, the rightmost is being loaded but not the left. I have reread the code multiple times, but I can't figure out what is wrong. Here's the code:
library IEEE;
use IEEE.std_logic_1164.all;
entity shiftregister is
port (
CLK, CLR: in STD_LOGIC;
S: in STD_LOGIC; --Shift right
W: in STD_LOGIC; --Write
Cin: in STD_LOGIC; --possible carry in from the addition
DL: in STD_LOGIC_VECTOR (7 downto 0); --left load for addition result
DR: in STD_LOGIC_VECTOR (7 downto 0); --right load for initial multiplier
Q: out STD_LOGIC_VECTOR (15 downto 0)
);
end shiftregister ;
architecture shiftregister of shiftregister is
signal IQ: std_logic_vector(15 downto 0):= (others => '0');
begin
process (CLK)
begin
if(CLK'event and CLK='1') then
if CLR = '1' then
IQ(7 downto 0) <= DR; --CLR clears and initializes the multiplier
IQ(15 downto 8) <= (others => '0');
else
if (S='1') then
IQ <= Cin & IQ(15 downto 1);
elsif (W='1') then
IQ(15 downto 8) <= DL;
end if;
end if;
end if;
end process;
Q<=IQ;
end shiftregister;
Waveform
TestBench
library IEEE;
use IEEE.std_logic_1164.all;
entity register_tb is
end register_tb;
architecture register_tb of register_tb is
component shiftregister is port (
CLK, CLR: in STD_LOGIC;
S: in STD_LOGIC; --Shift right
W: in STD_LOGIC; --Write
Cin: in STD_LOGIC; --possible carry in from the addition
DL: in STD_LOGIC_VECTOR (7 downto 0); --left load for addition result
DR: in STD_LOGIC_VECTOR (7 downto 0); --right load for initial multiplier
Q: out STD_LOGIC_VECTOR (15 downto 0)
);
end component;
signal CLK: std_logic:='0';
signal CLR: std_logic:='1';
signal Cin: std_logic:='0';
signal S: std_logic:='1';
signal W: std_logic:='0';
signal DL, DR: std_logic_vector(7 downto 0):="00000000";
signal Q: std_logic_vector(15 downto 0):="0000000000000000";
begin
U0: shiftregister port map (CLK, CLR, S, W, Cin, DL,DR,Q);
CLR <= not CLR after 20 ns;
CLK <= not CLK after 5 ns;
W <= not W after 10 ns;
DL <= "10101010" after 10 ns;
DR <= "00110011" after 10 ns;
end register_tb;
Your simulation shows that your S input is always high. The way you have your conditions setup, this means that the last elsif statement will not execute because S has priority over W. If you want your write to have priority over your shift operation, you should switch your conditions
if (W='1') then
IQ(15 downto 8) <= DL;
elsif (S='1') then
IQ <= Cin & IQ(15 downto 1);
end if;
Based on your comment for the desired behaviour, you could do something like this:
if (S='1' and W='1') then
IQ <= Cin & DL & IQ(7 downto 1);
elsif (W='1') then -- S=0
IQ(15 downto 8) <= DL;
elsif (S='1') then -- W=0
IQ <= Cin & IQ(15 downto 1);
end if; -- W=0 & S=0
Some improvements:
(1) Remove all signal but CLK from sensitivity list. Your process has no async signals, so only clock is needed in sensitivity list.
process(CLK)
(2) Assign zero only to the required bits -> question of taste ;)
IQ(7 downto 0) <= DR; --CLR clears and initializes the multiplier
IQ(15 downto 8) <= (others => '0');
(3) A elsif statement can clarify the assignment precedence:
if (S='1') then
IQ <= Cin & IQ(15 downto 1);
elsif (W='1') then
IQ(15 downto 8) <= DL;
end if;
(4) Line Q <= IQ; produces a second 16-bit register. I think this is not intended. Move this line outside of the process.

How Can i eliminate inout signal for my vhdl Adder?

I have written the following VHDL code which is the component of a Fast Adder. The fast adder consists of an 8by8 register hooked up to adder whose code is below. How can i eliminate the use of inout Read_Adress. I want Read_Adress to be out std_logic_vector not inout?
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.std_logic_unsigned.all;
Entity Adder is
port(
Clock_50_MHZ :in std_logic;
En :in std_logic;
Data_Registerfile : in std_logic_vector(7 downto 0);
Read_Address: inout std_logic_vector(2 downto 0) := "000";
Output : out std_logic_vector(11 downto 0)
);
end Adder;
Architecture arch of Adder is
Signal result : unsigned (11 downto 0):="000000000000";
Signal regData: std_logic_vector(7 downto 0);
Begin
regData <= Data_Registerfile;
Process(Clock_50_MHZ)
Begin
if rising_edge(Clock_50_MHZ) then
if (En = '1') then
if(Read_Address = "000") then
result <= "000000000000" + unsigned(regData);
Read_Address <= Read_Address + 1;
elsif(Read_Address = "111") then
Output <= std_logic_vector( result + unsigned(regData) );
Read_Address <= "000";
else
result <= result + unsigned(regData);
Read_Address <= Read_Address + 1;
end if;
end if;
end if;
End Process;
end arch;
This is a classic inconvenience in VHDL: you can't use your out ports as
signals (if you are used to Verilog, you often find yourself wanting to do
that).
The best way that I know of is to create an extra dummy signal:
signal Read_Address_tmp : std_logic_vector(2 downto 0) := "000";
do the computation with that:
Process(Clock_50_MHZ)
Begin
if rising_edge(Clock_50_MHZ) then
if (En = '1') then
if(Read_Address_tmp = "000") then
result <= "000000000000" + unsigned(regData);
Read_Address_tmp <= Read_Address_tmp + 1;
elsif(Read_Address_tmp = "111") then
Output <= std_logic_vector( result + unsigned(regData) );
Read_Address_tmp <= "000";
else
result <= result + unsigned(regData);
Read_Address_tmp <= Read_Address_tmp + 1;
end if;
end if;
end if;
End Process;
and then link it to your output:
Read_Address <= Read_Address_tmp;
Owen's answer is the usual way, historically.
The "new" VHDL 2008 allows reading of out-mode ports now. If your tools don't support it, log a bug with the vendor. See the bottom of this page from "VHDL 2008 - just the new stuff"
http://books.google.co.uk/books?id=ETxLguPMEY0C&pg=PA163&lpg=PA163#v=onepage&q&f=false

Resources