Undefined Initial Signals VHDL - vhdl

I have to implement a mini-router in VHDL. The design requirements for this are:
I've written the implementation, and a testbench. However, looking at the simulation waveform, some of my initial signals are undefined and I'm not sure why.
This is the source code:
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_unsigned.all;
use IEEE.numeric_std.all;
entity mini_router is
port (
clk : in std_logic;
reset : in std_logic; -- synchronous negative reset
data1 : in std_logic_vector(9 downto 0);
req1 : in std_logic;
grant1 : out std_logic;
data2 : in std_logic_vector(9 downto 0);
req2 : in std_logic;
grant2 : out std_logic;
data_out : out std_logic_vector(7 downto 0);
valid : out std_logic
);
end entity;
architecture arch of mini_router is
signal aux : std_logic_vector(9 downto 0);
signal aux1 : std_logic_vector(1 downto 0);
signal aux2 : std_logic_vector(1 downto 0);
signal aux_valid : std_logic;
signal aux_grant1 : std_logic;
signal aux_grant2 : std_logic;
begin
mini_router: process(clk)
variable r : std_logic:= '1';
begin
-- conta le volte in cui c'è stato data conflict
if rising_edge(clk) then -- chiuso
if reset = '0' then
aux <= (others => '0');
aux_valid <= '0';
aux_grant1 <= '0';
aux_grant2 <= '0';
elsif reset = '1' then
if (req1 xor req2) = '1' then --chiuso -- un solo req è alto
if req1 ='1' then --chiuso
aux <= data1;
aux_grant1 <= '1';
aux_grant2 <= '0';
aux_valid <= '1';
else
aux <= data2;
aux_grant1 <= '0';
aux_grant2 <= '1';
aux_valid <= '1';
end if;
----entrambi i req sono alti
elsif (req1 and req2) = '1' then -- chiuso
if ((unsigned(aux1)) > (unsigned(aux2))) then
aux <= data1;
aux_grant1 <= '1';
aux_grant2 <= '0';
aux_valid <= '1';
elsif ((unsigned(aux1)) < (unsigned(aux2))) then
aux <= data2;
aux_grant2 <= '1';
aux_grant1 <= '0';
aux_valid <= '1';
elsif ((unsigned(aux1)) = (unsigned(aux2))) then -- stesso livello di priorità -- alternativa:(aux1 xnor aux2)="11"
if r = '1' then
aux <= data1;
aux_grant1<= '1';
aux_grant2 <= '0';
aux_valid <= '1';
r := not (r);
else
aux <= data2;
aux_grant2 <= '1';
aux_grant1<= '0';
aux_valid <= '1';
r := not (r);
end if;
end if;
elsif (req1 nor req2) = '1' then
aux_valid <= '0';
aux <= (others => '0');
aux_grant1 <= '0';
aux_grant2 <= '0';
end if;
end if; -- if del reset
end if; -- if del clock
end process;
data_out <= aux(9 downto 2);
aux1 <= data1 (1 downto 0);
aux2 <= data2 (1 downto 0);
valid <= aux_valid;
grant1 <= aux_grant1;
grant2 <= aux_grant2;
end architecture;
This is the testbench:
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
entity mini_router_tb is
end mini_router_tb;
architecture arc of mini_router_tb is
constant T_CLK : time := 10 ns; --- frequenza di clock: 125 MHz
signal clk_tb : std_logic := '1';
signal reset_tb : std_logic := '0'; -- reset attivo basso sincrono
signal data1_tb : std_logic_vector(9 downto 0) := (others => '0');
signal req1_tb : std_logic:= '0';
signal grant1_tb : std_logic;
signal data2_tb : std_logic_vector(9 downto 0) := (others => '0');
signal req2_tb : std_logic:= '0';
signal grant2_tb : std_logic;
signal data_out_tb : std_logic_vector(7 downto 0);
signal valid_tb : std_logic;
signal end_sim : std_logic := '1'; -- signal to use to stop the simulation when there is nothing else to test
component mini_router is
port (
clk : in std_logic;
reset : in std_logic; -- synchronous negative reset
data1 : in std_logic_vector(9 downto 0);
req1 : in std_logic;
grant1 : out std_logic;
data2 : in std_logic_vector(9 downto 0);
req2 : in std_logic;
grant2 : out std_logic;
data_out : out std_logic_vector(7 downto 0);
valid : out std_logic
);
end component;
begin
clk_tb <= (not(clk_tb)and(end_sim)) after T_CLK/2;
DUT : mini_router
port map (
clk => clk_tb,
reset => reset_tb,
data1 => data1_tb,
req1 => req1_tb,
grant1 => grant1_tb,
data2 => data2_tb,
req2 => req2_tb,
grant2 => grant2_tb,
data_out => data_out_tb,
valid => valid_tb
);
-- process used to make the testbench signals change synchronously with the rising edge of the clock
stimuli_process: process(clk_tb,reset_tb)
variable t : integer := 0; -- variabile che conta i cicli di clock
begin
if (rising_edge(clk_tb)) then
case (t) is
when 1 => data1_tb <= (9 downto 3 => '0') & "100"; -- data1= 4; data_out=0 per il reset
data2_tb <= (9 downto 4 => '0') & "1101";-- data2= 13;
req1_tb <= '1' ; req2_tb<= '0';
when 2 => reset_tb <= '1';
data1_tb <= (9 downto 3 => '0') & "100"; -- data1= 4; data_out=1
data2_tb <= (9 downto 4 => '0') & "1101"; -- data2= 13;
req1_tb <= '1' ; req2_tb<= '0';
when 3 => data1_tb <= (9 downto 3 => '0') & "100"; -- data1= 4;
data2_tb <= (9 downto 4 => '0') & "1101";-- data2= 13; data_out=3
req1_tb <= '0' ; req2_tb<= '1';
when 4 => data1_tb <= (9 downto 5 => '0') & "11100"; --data1=28
data2_tb <= (9 downto 4 => '0') & "1101"; -- data2= 13; data_out=3 priorità maggiore
req1_tb <= '1' ; req2_tb<= '1';
when 5 => data1_tb <= (9 downto 5 => '0') & "00111"; --data1=7; data_out=1 priorità maggiore
data2_tb <= (9 downto 5 => '0') & "11101"; -- data2= 29;
req1_tb <= '1' ; req2_tb<= '1';
when 6 => data1_tb <= (9 downto 5 => '0') & "00111"; --data1=7; data_out=1
data2_tb <= (9 downto 5 => '0') & "11111"; -- data2= 31;
req1_tb <= '1' ; req2_tb<= '1';
when 7 => data1_tb <= (9 downto 5 => '0') & "00111"; --data_out=0;
data2_tb <= (9 downto 5 => '0') & "11111";
req1_tb <= '0' ; req2_tb<= '0';
when 8 => data1_tb <= (9 downto 5 => '0') & "10111"; --data1=7; data_out non assunto=5
data2_tb <= (9 downto 5 => '0') & "11111"; -- data2= 31; data_out=7
req1_tb <= '1' ; req2_tb<= '1';
when 9 => end_sim <= '0'; -- stops the simulation when t = 10
when others => null; -- non accade nulla negli altri casi
end case;
t := t + 1;
end if;
end process;
end architecture;

Your reset logic is synchronous, because the outmost condition is rising_edge(clk). Therefore the internal signals are undefined until the first raising edge of the clock.
Change to an asynchronous reset like this (excerpt):
if reset = '0' then
-- reset statements
elsif rising_edge(clk) then
-- work statements
end if;
Please be aware that even with an asynchronous reset the signals will be undefined until reset is activated or the clock raises. This reflects the actual behavior of a real device.

The reason your signals are initially set to U or X is because the values of all signals, variables, etc. are initialized to the left hand side of the type definition.
From the IEEE 1076 code (see here):
-------------------------------------------------------------------
-- logic state system (unresolved)
-------------------------------------------------------------------
type STD_ULOGIC is ( 'U', -- Uninitialized
'X', -- Forcing Unknown
'0', -- Forcing 0
'1', -- Forcing 1
'Z', -- High Impedance
'W', -- Weak Unknown
'L', -- Weak 0
'H', -- Weak 1
'-' -- Don't care
);
--------------------------------
And std_logic is just a resolved version of std_ulogic. So any signal of type std_logic will have its default value be U, unless set otherwise.
Consider the following code:
signal A : std_logic;
signal B : std_logic := '1';
Signal A would be U until set otherwise. Signal B will be 0 until set otherwise.
This is why you are seeing U in your simulation. (As for X you see in your waveform window, many simulators that collapse vectors into a single value in the waveform view treat collections with U as X. Expand that vector and I suspect you will see several U's.)

Related

SDRAM Controller in VHDL

I have to develop a SDRAM controller for a class project in VHDL. But this is my first time working with VHDL, that has a very important learning curve.
I have downloaded a SDRAM controller from github (https://github.com/christianmiyoshi/SDRAM_Controller_VHDL/blob/master/sdram_controller.vhd) and I am trying to complete it.
I am trying to write a data in an address and later read it, but I cant read a single data. I dont know if my problem is in the writing or in the reading process.
Can anybody help me, please?
Thank you all!
library ieee;
use ieee.numeric_std.all;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity ram_controller is
port(
clk : in std_logic;
reset: in std_logic;
refresh: in std_logic;
read_write_enable: in std_logic;
write_n: in std_logic;
address: in std_logic_vector(21 downto 0);
data_in: in std_logic_vector(15 downto 0);
dqmu: in std_logic;
dqml: in std_logic;
ready: out std_logic;
done: out std_logic;
data_out: out std_logic_vector(15 downto 0);
single_burst: in std_logic; --0 single y 1 burst
SDRAM_CKE: out std_logic;
SDRAM_CS_N: out std_logic;
SDRAM_RAS_N: out std_logic;
SDRAM_CAS_N: out std_logic;
SDRAM_WE_N: out std_logic;
SDRAM_BA: out std_logic_vector(1 downto 0);
SDRAM_SA: out std_logic_vector(11 downto 0);
SDRAM_DQ: inout std_logic_vector(15 downto 0);
SDRAM_DQM: out std_logic_vector(1 downto 0)
);
end entity;
architecture behavior of ram_controller is
type state_type is (init_ckeLow, init_stableClock, init_wait, init_nopCommand, init_prechargeAll, init_refresh_1, init_mode, init_refresh_2, idle, refresh_state, activate_row, activate_rcd, read_write, ras1, ras2, precharge);
signal state: state_type := init_ckeLow;
signal ticks: std_logic_vector(7 downto 0) := (others => '0');
signal ticks_ref: integer := 0;
signal ticks_ref_refresh: integer := 0;
constant burstMode: std_logic := '0';
constant casLatency: std_logic_vector(2 downto 0) := "010";
constant burstType: std_logic := '0';
constant burstLength: std_logic_vector(2 downto 0) := "000";
--signal highz_output: std_logic:= '0';
constant MODE_REG: std_logic_vector(11 downto 0) := "00" & burstMode & "00" & casLatency & burstType & burstLength;
constant MODE_REG_BURST: std_logic_vector(11 downto 0) := "000000100111";
signal command: std_logic_vector(3 downto 0);
signal row: std_logic_vector(11 downto 0);
signal column: std_logic_vector(7 downto 0);
signal bank: std_logic_vector(1 downto 0);
signal sd_busdir_x: std_logic:='0';
-- Command truth table
-- CS_N, RAS_N, CAS_N, WE_N
constant CMD_ACTIVATE: std_logic_vector(3 downto 0) := "0011";
constant CMD_PRECHARGE: std_logic_vector(3 downto 0) := "0010";
constant CMD_WRITE: std_logic_vector(3 downto 0) := "0100";
constant CMD_READ: std_logic_vector(3 downto 0) := "0101";
constant CMD_MODE: std_logic_vector(3 downto 0) := "0000";
constant CMD_NOP: std_logic_vector(3 downto 0) := "0111";
constant CMD_REFRESH: std_logic_vector(3 downto 0) := "0001";
signal address_buffer: std_logic_vector(21 downto 0) := (others => '0');
signal data_in_buffer: std_logic_vector(15 downto 0) := (others => '0');
signal dqu_buffer: std_logic := '0';
signal dql_buffer: std_logic := '0';
signal ready_buffer: std_logic := '0';
signal done_buffer: std_logic := '0';
signal data_out_buffer: std_logic_vector(15 downto 0) := (others => '0');
signal CKE: std_logic;
signal CS_N: std_logic;
signal RAS_N: std_logic;
signal CAS_N: std_logic;
signal WE_N: std_logic;
signal BA: std_logic_vector(1 downto 0);
signal SA: std_logic_vector(11 downto 0);
signal DQ: std_logic_vector(15 downto 0);
signal DQM: std_logic_vector(1 downto 0);
signal contador : std_logic_vector(15 downto 0) := x"0000";
signal modo: std_logic := '0';
begin
(CS_N, RAS_N, CAS_N, WE_N) <= command;
SDRAM_CKE <= CKE;
SDRAM_CS_N <= CS_N;
SDRAM_RAS_N <= RAS_N;
SDRAM_CAS_N <= CAS_N;
SDRAM_WE_N <= WE_N;
SDRAM_BA <= BA;
SDRAM_SA <= SA;
--SDRAM_DQ <= DQ;
SDRAM_DQM <= DQM;
--SA <= address_buffer;
SDRAM_DQ <= data_in_buffer when sd_busdir_x = '1' else (others => 'Z');
DQM <= dqu_buffer & dql_buffer;
ready <= ready_buffer;
done <= done_buffer;
data_out <= data_out_buffer;
bank <= address(21 downto 20);
row <= address(19 downto 8);
column <= address(7 downto 0);
process(clk, reset)
begin
if reset = '0' then
state <= init_ckeLow;
ticks_ref <= 0;
elsif rising_edge(clk) then
if ticks_ref /= 0 then
ticks_ref <= ticks_ref - 1;
else
-- Micron datasheet instructions
-- Frequency = 100 Mhz => period of 10ns
-- 1: Apply Vdd and Vddq simultaneously
case state is
when init_ckeLow =>
-- 2: Assert and hold CKE ant LVTTL logic low
ticks_ref <= 10;
CKE <= '0';
state <= init_stableClock;
when init_stableClock =>
-- 3: Provide stable clock
ticks_ref <= 10;
state <= init_wait;
when init_wait=>
-- 4: Wait at least 100us
-- 5: bring cke high at some point of the period
-- with command inhibit or nop
--ticks_ref <= 10000;
ticks_ref <= 2; -- debugadd
state <= init_nopCommand;
when init_nopCommand =>
--ticks_ref <= 10000;
ticks_ref <= 2; -- debug
CKE <= '1';
command <= CMD_NOP;
state <= init_prechargeAll;
when init_prechargeAll =>
-- 6: perform precharge all
-- 7: wait at leas t_RP
command <= CMD_PRECHARGE;
BA <= "00";
SA(10) <= '1'; -- all banks
ticks_ref <= 2;
ticks_ref_refresh <= 8;
state <= init_refresh_1;
when init_refresh_1 =>
-- auto refresj period: < 64 ns
if ticks_ref_refresh = 0 then
state <= init_mode;
else
ticks_ref_refresh <= ticks_ref_refresh - 1;
command <= CMD_REFRESH;
ticks_ref <= 7;
end if;
when init_mode =>
command <= CMD_MODE;
if single_burst = '0' then
SA <= MODE_REG;
modo <= '0';
else
SA <= MODE_REG_BURST;
modo <= '1';
end if;
BA <= "00";
ticks_ref <= 2;
ticks_ref_refresh <= 8;
state <= init_refresh_2;
when init_refresh_2 =>
if ticks_ref_refresh = 0 then
state <= idle;
--done_buffer <= '1';
else
ticks_ref_refresh <= ticks_ref_refresh - 1;
command <= CMD_REFRESH;
ticks_ref <= 7;
end if;
when idle =>
done_buffer <= '0';
contador <= (others => '0');
if read_write_enable = '1' then
-- tras: active to precharge: 45 ns min, 120000ns max
state <= activate_row;
command <= CMD_ACTIVATE;
SA <= row;
BA <= bank;
--done_buffer <= '0';
elsif refresh = '1' then
state <= refresh_state;
command <= CMD_REFRESH;
ticks_ref <= 7;
--done_buffer <= '0';
end if;
when refresh_state =>
state <= idle;
--done_buffer <= '1';
when activate_row =>
--trcd 20 ns
command <= CMD_NOP;
state <= activate_rcd;
data_in_buffer <= data_in;
ticks_ref <= 1;
when activate_rcd =>
-- trcs = 20ns min
state <=read_write;
SA <= "0000" & column;
if write_n = '0' then
command <= CMD_WRITE;
dqu_buffer <= dqmu;
dql_buffer <= dqml;
sd_busdir_x <= '1';
else
command <= CMD_READ;
end if;
when read_write =>
--command <= CMD_NOP;
state <= ras1;
--if modo='0' then
--sd_busdir_x <= '0';
--end if;
when ras1 =>
state <= ras2;
command <= CMD_NOP;
when ras2 =>
-- trp = 20ns min
if modo='1' and contador <= x"00FF" then
data_in_buffer <= data_in;
state <= ras2;
contador <= contador +1;
else
contador <= (others => '0');
state <= precharge;
sd_busdir_x <= '0';
command <= CMD_PRECHARGE;
SA(10) <= '1';
data_out_buffer <= SDRAM_DQ;
ticks_ref <= 2;
end if;
when precharge =>
state <= idle;
done_buffer <= '1';
ticks_ref <= 1;
end case;
end if;
end if;
end process;
end architecture;
[enter image description here][1]
[1]: https://i.stack.imgur.com/CaqqL.png

I2Cmaster with MPU6050 in VHDL not working

For my hobby project I try to make a quadcopter which balances itself with the MPU-6050. The flight controller shall be the FPGA Altera cyclone IV, because its fun. I'm coding it in VHDL.
Anyway I'm stuck on the I2C communication with the MPU-6050. As bases I used the I2C master VHDL code from: https://www.digikey.com/eewiki/pages/viewpage.action?pageId=10125324.
I try to read the gyro registers and print them out on 8 leds just to see if I have some communication coming in.
I have tried to run with a 1Hz prescaler all the I2C phases in the state machine and light up some leds just to see if all phases are run through. This is the case. I have assigned the pins 2.5V default, I use 10k pull up resistors. The MPU6050 works perferct on an arduino.
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity mpu6050_2 is
port( clk_50 : in std_logic;
areset : in std_logic;
i2c_SDA : INOUT STD_LOGIC;
i2c_SCL : INOUT STD_LOGIC;
leds : out std_LOGIC_VECTOR(7 downto 0)
);
end entity mpu6050_2;
architecture struc of mpu6050_2 is
component i2c_master is
GENERIC(
input_clk : INTEGER := 50_000_000;
bus_clk : INTEGER := 400_000);
PORT(
clk : IN STD_LOGIC;
reset_n : IN STD_LOGIC;
ena : IN STD_LOGIC;
addr : IN STD_LOGIC_VECTOR(6 DOWNTO 0);
rw : IN STD_LOGIC;
data_wr : IN STD_LOGIC_VECTOR(7 DOWNTO 0);
busy : OUT STD_LOGIC;
data_rd : OUT STD_LOGIC_VECTOR(7 DOWNTO 0);
ack_error : BUFFER STD_LOGIC;
sda : INOUT STD_LOGIC;
scl : INOUT STD_LOGIC);
end component ;
type machine is (config1, config2, gyroH, gyroL);
signal state : machine:= config1; --current state
signal SDA_int : std_LOGIC;
signal SCL_int : std_LOGIC;
signal i2c_ena : std_LOGIC;
signal i2c_busy : std_LOGIC;
signal busy_prev : std_LOGIC;
signal i2c_rw : std_LOGIC;
signal i2c_data_wr : STD_LOGIC_VECTOR(7 DOWNTO 0);
signal gyro_data : std_LOGIC_VECTOR(15 downto 0);
signal i2c_data_rd : std_LOGIC_VECTOR (7 downto 0);
signal i2c_addr : STD_LOGIC_VECTOR(6 DOWNTO 0);
begin
process(areset, clk_50)
VARIABLE busy_cnt : INTEGER := 0; --keeps track of i2c busy signals during transaction
begin
if areset = '0' then
busy_cnt := 0;
i2c_ena <= '0';
state <= config1;
elsif rising_edge(clk_50) then
case state is
when config1 =>
busy_prev <= i2c_busy;
if (busy_prev = '0' and i2c_busy = '1') then
busy_cnt := busy_cnt + 1;
end if;
case busy_cnt is
when 0 =>
i2c_ena <= '1';
i2c_addr <= "1101000"; --MPU6050 adress
i2c_rw <= '0'; --write
i2c_data_wr <= x"6B"; -- hex6B powermanagement
when 1 =>
i2c_rw <= '0'; --write
i2c_data_wr <= "00000000"; -- ON with internal clock
when 2 =>
i2c_ena <= '0';
if(i2c_busy = '0') then
busy_cnt := 0;
state <= config2;
end if;
when others => NULL;
end case;
when config2 =>
busy_prev <= i2c_busy;
if (busy_prev = '0' and i2c_busy = '1') then
busy_cnt := busy_cnt + 1;
end if;
case busy_cnt is
when 0 =>
i2c_ena <= '1';
i2c_addr <= "1101000"; --MPU6050 adress
i2c_rw <= '0'; --write
i2c_data_wr <= x"1B"; -- Gyro config
when 1 =>
i2c_rw <= '0'; --write
i2c_data_wr <= "00000000"; -- 250 degree/sec, no self test
when 2 =>
i2c_ena <= '0';
if(i2c_busy = '0') then
busy_cnt := 0;
state <= gyroH;
end if;
when others => NULL;
end case;
when gyroH =>
busy_prev <= i2c_busy;
if (busy_prev = '0' and i2c_busy = '1') then
busy_cnt := busy_cnt + 1;
end if;
case busy_cnt is
when 0 =>
i2c_ena <= '1';
i2c_addr <= "1101000"; --MPU6050 adress
i2c_rw <= '0'; --write
i2c_data_wr <= x"43"; -- hex43 GYRO_OUT[15:8]
when 1 =>
i2c_rw <= '1'; --read
when 2 =>
i2c_ena <= '0';
if(i2c_busy = '0') then
gyro_data(15 downto 8) <= i2c_data_rd;
busy_cnt := 0;
state <= gyroL;
end if;
when others => NULL;
end case;
when gyroL =>
busy_prev <= i2c_busy;
if (busy_prev = '0' and i2c_busy = '1') then
busy_cnt := busy_cnt + 1;
end if;
case busy_cnt is
when 0 =>
i2c_ena <= '1';
i2c_addr <= "1101000"; --MPU6050 adress
i2c_rw <= '0'; --write
i2c_data_wr <= x"44"; -- hex44 GYRO_OUT[7:0]
when 1 =>
i2c_rw <= '1'; --read
when 2 =>
i2c_ena <= '0';
if(i2c_busy = '0') then
gyro_data(7 downto 0) <= i2c_data_rd;
busy_cnt := 0;
state <= gyroH;
end if;
when others => NULL;
end case;
end case;
end if;
end process;
u0: i2c_master
port map(clk => clk_50, reset_n => areset, ena => i2c_ena, addr => i2c_addr, rw => i2c_rw, data_wr => i2c_data_wr, busy => i2c_busy, data_rd => i2c_data_rd
, sda => SDA_int, scl => SCL_int);
leds(7) <= gyro_data(0); --D4
leds(6) <= gyro_data(1); -- D5
leds(5) <= gyro_data(4); -- D6
leds(4) <= gyro_data(7); -- D7
leds(3) <= gyro_data(8); -- D8
leds(2) <= gyro_data(11); -- D9
leds(1) <= gyro_data(13); -- D10
leds(0) <= gyro_data(15); -- D11
i2c_SDA <= SDA_int;
i2c_SCL <= SCL_int;
end struc;
Result:
all the leds dont change status despite if i rotate the MPU6050. So no communication. Can anyone help me what i'm doing wrong?
First: I'm using the same component in one of my designs and do confirm it works.
I think you are just using the wrong i2c address to begin with.
In datasheets, i2c addresses are usually given including the read/write bit (for the MPU-6050, this is 0x68/01101000 and 0x69/01101001). The i2c master component used, however, expects to build the final i2c address by itself by appending (&) the i2c rw bit to the given address (see line 124 in the original sources), thus you must pass the address from the datasheet shifted by one bit.
Try using 0x34/0110100 as i2c address for read and write instead.
I only looked very briefly into the rest of your code (so there might be other culprits as well), but this should be enough to get you going.

VHDL Parametric Division Circuit - Book: FPGA Prototyping by VHDL Examples, Pong Chu

I'm trying to follow an example on my VHDL book. Its name is FPGA Prototyping by VHDL Examples, Pong Chu. It has a Divider Circuit example in Chapter 6, Listing 5. I understood the general idea of a division operation. To verify the module I wrote a testbench and I saw that it doesn't work properly. If anyone could explain to me where the problem is, I would be very appreciated.
Here are the codes of module and testbench.
Module:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity Divider is
generic(W: integer := 8;
CBIT: integer := 4 );
Port ( clk, reset : in STD_LOGIC;
start : in STD_LOGIC;
dvsr, dvnd : in STD_LOGIC_VECTOR (W-1 downto 0);
ready, done_tick : out STD_LOGIC;
quo, rmd : out STD_LOGIC_VECTOR (W-1 downto 0));
end Divider;
architecture Behavioral of Divider is
type state_type is (idle, op, last, done);
signal state_reg, state_next: state_type;
signal rh_reg, rh_next: UNSIGNED(W-1 downto 0) := (others => '0');
signal rl_reg, rl_next: STD_LOGIC_VECTOR(W-1 downto 0) := (others => '0');
signal rh_temp: UNSIGNED(W-1 downto 0) := (others => '0');
signal d_reg, d_next: UNSIGNED(W-1 downto 0) := (others => '0');
signal n_reg, n_next: UNSIGNED(CBIT-1 downto 0) := (others => '0');
signal q_bit: STD_LOGIC;
begin
-- FSMD State and Data Registers
process(clk, reset)
begin
if reset = '1' then
state_reg <= idle;
rh_reg <= (others => '0');
rl_reg <= (others => '0');
d_reg <= (others => '0');
n_reg <= (others => '0');
elsif rising_edge(clk) then
state_reg <= state_next;
rh_reg <= rh_next;
rl_reg <= rl_next;
d_reg <= d_next;
n_reg <= n_next;
end if;
end process;
-- FSMD Next-State Logic and Data Path Logic
process(state_reg, n_reg, rh_reg, rl_reg, d_reg, start, dvsr, dvnd, q_bit, rh_temp, n_next)
begin
ready <= '0';
done_tick <= '0';
state_next <= state_reg;
rh_next <= rh_reg;
rl_next <= rl_reg;
d_next <= d_reg;
n_next <= n_reg;
case state_reg is
when idle =>
ready <= '1';
if start = '1' then
rh_next <= (others => '0');
rl_next <= dvnd; -- Dividend
d_next <= UNSIGNED(dvsr); -- Divisor
n_next <= TO_UNSIGNED(W+1, CBIT); -- Index
state_next <= op;
end if;
when op =>
--Shift rh and rl left
rl_next <= rl_reg(W-2 downto 0) & q_bit;
rh_next <= rh_temp(W-2 downto 0) & rl_reg(W-1);
--Decrease index
n_next <= n_reg - 1;
if(n_next = 1) then
state_next <= last;
end if;
when last =>
rl_next <= rl_reg(W-2 downto 0) & q_bit;
rh_next <= rh_temp;
state_next <= done;
when done =>
state_next <= idle;
done_tick <= '1';
end case;
end process;
-- Compare and Subtract
process(rh_reg, d_reg)
begin
if rh_reg <= d_reg then
rh_temp <= rh_Reg - d_reg;
q_bit <= '1';
else
rh_temp <= rh_reg;
q_bit <= '0';
end if;
end process;
-- Output
quo <= rl_reg;
rmd <= STD_LOGIC_VECTOR(rh_reg);
end Behavioral;
Testbench:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity tb_Divider is
-- Port ( );
end tb_Divider;
architecture Behavioral of tb_Divider is
signal clk, reset, start, ready, done: STD_LOGIC;
signal dvsr, dvnd: STD_LOGIC_VECTOR(7 downto 0);
signal quo, rmd: STD_LOGIC_VECTOR(7 downto 0);
component Divider is
port( clk, reset : in STD_LOGIC;
start : in STD_LOGIC;
dvsr, dvnd : in STD_LOGIC_VECTOR (7 downto 0);
ready, done_tick : out STD_LOGIC;
quo, rmd : out STD_LOGIC_VECTOR (7 downto 0));
end component Divider;
begin
UUT: Divider port map( clk => clk, reset => reset, start => start, dvsr => dvsr, dvnd => dvnd,
ready => ready, done_tick => done, quo => quo, rmd => rmd);
process
begin
clk <= '0';
wait for 10 ns;
clk <= '1';
wait for 10 ns;
end process;
process
begin
start <= '0';
dvnd <= x"00";
dvsr <= x"00";
wait for 100 ns;
start <= '1';
dvnd <= x"C8";
dvsr <= x"0A";
wait for 10 us;
end process;
end Behavioral;
Result of Testbench:

State machine and unsigned signal

I have a few problems with a fairly simple state machine I made. No matter what I do, the signal startS1, startS2, enS and mS always stays unsigned in simulation even when I hit the reset button and I can't figure out why. There's a component in the mix, but I did test the component and it works perfectly. I hope you can help me!
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity machine_etat is
generic (N_bit : integer := 8);
Port ( LOAD : in STD_LOGIC_VECTOR (N_bit-1 downto 0);
RESET : in STD_LOGIC;
START : in STD_LOGIC;
CLK : in STD_LOGIC;
OUTPUT : out STD_LOGIC_VECTOR (N_bit-1 downto 0));
end machine_etat;
architecture Behavioral of machine_etat is
TYPE machine is (IddleT, DepartT, LoadT, ShiftT, EndT);
SIGNAL Etat1, Etat2 : machine:= IddleT;
SIGNAL mS: STD_LOGIC_VECTOR (1 downto 0);
SIGNAL enS : STD_LOGIC;
SIGNAL outputS : STD_LOGIC_VECTOR (N_bit-1 downto 0);
component Reg_decal is
generic (N_bit : integer := N_bit);
Port ( CLK : in STD_LOGIC;
RESET : in STD_LOGIC;
EN : in STD_LOGIC;
M : in STD_LOGIC_VECTOR (1 downto 0);
LOAD : in STD_LOGIC_VECTOR (N_bit-1 downto 0);
OUTPUT : out STD_LOGIC_VECTOR (N_bit-1 downto 0));
end component;
SIGNAL startS1, startS2 : STD_LOGIC;
begin
OUTPUT <= outputS;
Reg_dec: Reg_decal
generic map (N_bit => N_bit)
port map (CLK => CLK,
RESET => RESET,
EN => enS,
M => mS,
LOAD => LOAD,
OUTPUT => outputS);
Machine1: process (CLK)
begin
if RESET = '1' then
enS <= '0';
mS <= "00";
startS1 <= '0';
startS2 <= '0';
Etat1 <= IddleT;
elsif rising_edge(CLK) then
CASE Etat1 is
WHEN IddleT =>
if startS1 = '1' OR START = '1' then
Etat1 <= DepartT;
else
Etat1 <= IddleT;
end if;
WHEN DepartT =>
Etat1 <= LoadT;
startS1 <= '0';
WHEN LoadT =>
mS <= "11";
enS <= '1';
Etat1 <= ShiftT;
WHEN ShiftT =>
mS <= "00";
Etat1 <= EndT;
WHEN EndT =>
enS <= '0';
startS2 <= '1';
Etat1 <= IddleT;
WHEN Others =>
Etat1 <= IddleT;
end CASE;
end if;
end process;
Machine2: process (CLK)
begin
if RESET = '1' then
Etat2 <= IddleT;
elsif rising_edge(CLK) then
CASE Etat2 is
WHEN IddleT =>
if startS2 = '1' then
Etat2 <= DepartT;
else
Etat2 <= IddleT;
end if;
WHEN DepartT =>
startS2 <= '0';
Etat2 <= LoadT;
WHEN LoadT =>
enS <= '1';
Etat2 <= ShiftT;
WHEN ShiftT =>
mS <= "01";
Etat2 <= EndT;
WHEN EndT =>
Etat2 <= IddleT;
startS1 <= '1';
WHEN Others =>
end CASE;
end if;
end process;
end Behavioral;
Add RESET to your process sensitivity list.

4-Bit ALU to BCD display

I have a mega-assignment and the last part(for extra marks) is to display the output of a designed ALU using two 7-seg displays. These should display the result of the operations performed in the ALU. I am performing logical and arithmetic operations and I can only use the lower display for logical operations. For the arithmetic operations I need to use BCD code to display the answers. My ALU is working fine, I am finding it hard to do the decoder part. I don't even know if I am on the right track. Help!
CODE
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_unsigned.ALL;
entity codeALU is
Port ( A : in STD_LOGIC_VECTOR (3 downto 0);
B : in STD_LOGIC_VECTOR (3 downto 0);
Cin : in STD_LOGIC;
S0 : in STD_LOGIC;
S1 : in STD_LOGIC;
M : in STD_LOGIC;
Cout : out STD_LOGIC;
Z : out STD_LOGIC;
F : out STD_LOGIC_VECTOR (3 downto 0);
bcd1 : out STD_LOGIC_VECTOR (6 downto 0);
bcd2 : out STD_LOGIC_VECTOR (6 downto 0));
end codeALU;
architecture Behavioral of codeALU is
begin
process(A, B, M, Cin, S1, S0)
variable temp : STD_LOGIC_VECTOR (4 downto 0);
variable Fx : STD_LOGIC_VECTOR (3 downto 0);
variable Cx, Zx : STD_LOGIC;
variable Sel : STD_LOGIC_VECTOR (2 downto 0);
begin
Sel := S1 & S0 & Cin;
Cx := '0';
Zx := '0';
if M = '0' then
Z <= '0';
case Sel(2 downto 1) is
when "00" =>
Fx := A AND B;
Zx := '0';
when "01" =>
Fx := A XOR B;
when "10" =>
Fx := A OR B;
when "11" =>
Fx := A XNOR B;
when others =>
null;
end case;
case Fx is
when "0000"=> bcd1 <="0000001"; -- '0'
when "0001"=> bcd1 <="1001111"; -- '1'
when "0010"=> bcd1 <="0010010"; -- '2'
when "0011"=> bcd1 <="0000110"; -- '3'
when "0100"=> bcd1 <="1001100"; -- '4'
when "0101"=> bcd1 <="0100100"; -- '5'
when "0110"=> bcd1 <="0100000"; -- '6'
when "0111"=> bcd1 <="0001111"; -- '7'
when "1000"=> bcd1 <="0000000"; -- '8'
when "1001"=> bcd1 <="0000100"; -- '9'
when others=> bcd1 <="1111111";
end case;
else
case Sel is
when "000" =>
temp := (B(3)&B(3 downto 1) + ('0'&A));
Fx := temp(3 downto 0);
Cx := temp(4);
when "001" =>
temp := (A(3)&A(3 downto 1) + ('0'&B));
Fx := temp(3 downto 0);
Cx := temp(4);
when "010" =>
temp := ('0'&A) + ('0'&B);
Fx := temp(3 downto 0);
Cx := temp(4);
when "011" =>
temp := ('0'&A) + ('0'&B) + ('0'&Cin);
Fx := temp(3 downto 0);
Cx := temp(4);
when "100" =>
temp := ('0'&A) + (not B);
Fx := temp(3 downto 0);
Cx := temp(4);
when "101" =>
temp := (not B) + ('0'&A) + 1;
Fx := temp(3 downto 0);
Cx := temp(4);
when "110" =>
temp := ('0'&A) + ('0'&B(3 downto 1));
Fx := temp(3 downto 0);
Cx := temp(4);
when "111" =>
temp := ('0'&B) + ('0'&A(3 downto 1));
Fx := temp(3 downto 0);
Cx := temp(4);
when others =>
null;
end case;
case Fx is
when "0000"=> bcd2 <="0000001"; -- '0'
when "0001"=> bcd2 <="1001111"; -- '1'
when "0010"=> bcd2 <="0010010"; -- '2'
when "0011"=> bcd2 <="0000110"; -- '3'
when "0100"=> bcd2 <="1001100"; -- '4'
when "0101"=> bcd2 <="0100100"; -- '5'
when "0110"=> bcd2 <="0100000"; -- '6'
when "0111"=> bcd2 <="0001111"; -- '7'
when "1000"=> bcd2 <="0000000"; -- '8'
when "1001"=> bcd2 <="0000100"; -- '9'
when others=> bcd2 <="1111111";
end case;
for i in 0 to 3 loop
Zx := Zx or Fx(i);
end loop;
Z <= not Zx;
end if;
F <= Fx;
Cout <= Cx;
end process;
end Behavioral;
Test Bench
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
use ieee.std_logic_arith.all;
-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
--USE ieee.numeric_std.ALL;
ENTITY test4ALU IS
END test4ALU;
ARCHITECTURE behavior OF test4ALU IS
-- Component Declaration for the Unit Under Test (UUT)
COMPONENT codeALU
PORT(
A : IN std_logic_vector(3 downto 0);
B : IN std_logic_vector(3 downto 0);
Cin : IN std_logic;
S0 : IN std_logic;
S1 : IN std_logic;
M : IN std_logic;
Cout : OUT std_logic;
Z : OUT std_logic;
F : OUT std_logic_vector(3 downto 0);
bcd1 : OUT std_logic_vector(6 downto 0);
bcd2 : OUT std_logic_vector(6 downto 0)
);
END COMPONENT;
--Inputs
signal A : std_logic_vector(3 downto 0) := (others => '0');
signal B : std_logic_vector(3 downto 0) := (others => '0');
signal Cin : std_logic := '0';
signal S0 : std_logic := '0';
signal S1 : std_logic := '0';
signal M : std_logic := '0';
--Outputs
signal Cout : std_logic;
signal Z : std_logic;
signal F : std_logic_vector(3 downto 0) := (others => '0');
signal bcd1 : std_logic_vector(6 downto 0);
signal bcd2 : std_logic_vector(6 downto 0);
-- No clocks detected in port list. Replace <clock> below with
-- appropriate port name
BEGIN
-- Instantiate the Unit Under Test (UUT)
uut: codeALU PORT MAP (
A => A,
B => B,
Cin => Cin,
S0 => S0,
S1 => S1,
M => M,
Cout => Cout,
Z => Z,
F => F,
bcd1 => bcd1,
bcd2 => bcd2
);
-- Stimulus process
stim_proc: process
begin
-- hold reset state for 100 ns.
wait for 100 ns;
A <= "1001";
B <= "1111";
M <= '0';
wait for 50 ns;
S1 <= '0';
S0 <= '0';
wait for 50 ns;
S1 <= '0';
S0 <= '1';
wait for 50 ns;
S1 <= '1';
S0 <= '0';
wait for 50 ns;
S1 <= '1';
S0 <= '1';
wait for 50 ns;
M <= '1';
S1 <= '0';
S0 <= '0';
Cin <= '0';
wait for 50 ns;
S1 <= '0';
S0 <= '0';
Cin <= '1';
wait for 50 ns;
S1 <= '0';
S0 <= '1';
Cin <= '0';
wait for 50 ns;
S1 <= '0';
S0 <= '1';
Cin <= '1';
wait for 50 ns;
S1 <= '1';
S0 <= '0';
Cin <= '0';
wait for 50 ns;
S1 <= '1';
S0 <= '0';
Cin <= '1';
wait for 50 ns;
S1 <= '1';
S0 <= '1';
Cin <= '0';
wait for 50 ns;
S1 <= '1';
S0 <= '1';
Cin <= '1';
wait;
end process;
process
begin
for i in 0 to 9 loop
F <= conv_std_logic_vector(i,4);
wait for 50 ns;
end loop;
end process;
END;
You've issue in your test bench:
Within codeALU entity is F defined as out signal. Within you test bench signal F is used to map F out from component codeALU. In the name less process below in test bench the signal F gets value: F <= conv_std_logic_vector(i,4);
It's unusable behavior. You see it in modelsim as red X's (not defined).

Resources