VHDL: muxes between 11 buses 8 bits wide output - vhdl

i recieved this question as a pre interview question "Draw a diagram and write the VHDL code for a module that meets the following requirements:
a. Fully synchronous.
b. Muxes between 11 buses where each bus is 8-bits wide.
c. Has 2 cycles of latency.
d. Optimized for maximum clock frequency."
ive been trying to do it myself reading my old notes and assignments i have done in university but i just don't think i'm on the right track with this. i have the code soo far posted below:
library IEEE;
use IEEE.STD_LOGIC_1164.all;
entity Mux is
port(
A: in STD_LOGIC_vector(7 downto 0);
B: in STD_LOGIC_vector(7 downto 0);
C: in STD_LOGIC_vector(7 downto 0);
D: in STD_LOGIC_vector(7 downto 0);
E: in STD_LOGIC_vector(7 downto 0);
F: in STD_LOGIC_vector(7 downto 0);
G: in STD_LOGIC_vector(7 downto 0);
H: in STD_LOGIC_vector(7 downto 0);
I: in STD_LOGIC_vector(7 downto 0);
J: in STD_LOGIC_vector(7 downto 0);
K: in STD_LOGIC_vector(7 downto 0);
S0: in std_LOGIC_vector(3 downto 0);
Z: out STD_LOGIC_vector(7 downto 0)
);
end Mux;
architecture func of Mux is
begin
process (A,B,C,D,E,F,G,H,I,J,K,S0)
begin
if S0="0001" then
Z<= A;
elsif S0="0010" then
Z<= B;
elsif S0="0011" then
Z<= C;
elsif S0="0100" then
Z<= D;
elsif S0="0101" then
Z<= E;
elsif S0="0110" then
Z<= F;
elsif S0="0111" then
Z<= G;
elsif S0="1000" then
Z<= H;
elsif S0="1001" then
Z<= I;
elsif S0="1010" then
Z<= J;
elsif S0="1011" then
Z<= K;
else
Z<=A;
end if;
end process;
end func;
and this is the code i have for my second file:
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
use IEEE.std_logic_arith.all;
entity mux11test is
end entity mux11test;
architecture test of mux11test is
signal T_A: STD_LOGIC_vector(7 downto 0):="00000001";
signal T_B: STD_LOGIC_vector(7 downto 0):="00000010";
signal T_C: STD_LOGIC_vector(7 downto 0):="00000011";
signal T_D: STD_LOGIC_vector(7 downto 0):="00000100";
signal T_E: STD_LOGIC_vector(7 downto 0):="00000101";
signal T_F: STD_LOGIC_vector(7 downto 0):="00000110";
signal T_G: STD_LOGIC_vector(7 downto 0):="00000111";
signal T_H: STD_LOGIC_vector(7 downto 0):="00001000";
signal T_I: STD_LOGIC_vector(7 downto 0):="00001001";
signal T_J: STD_LOGIC_vector(7 downto 0):="00001010";
signal T_K: STD_LOGIC_vector(7 downto 0):="00001011";
signal T_S: STD_LOGIC_vector( 3 downto 0);
signal T_Z: STD_LOGIC_vector(7 downto 0);
component mux11 IS
port(
A: in STD_LOGIC_vector(7 downto 0);
B: in STD_LOGIC_vector(7 downto 0);
C: in STD_LOGIC_vector(7 downto 0);
D: in STD_LOGIC_vector(7 downto 0);
E: in STD_LOGIC_vector(7 downto 0);
F: in STD_LOGIC_vector(7 downto 0);
G: in STD_LOGIC_vector(7 downto 0);
H: in STD_LOGIC_vector(7 downto 0);
I: in STD_LOGIC_vector(7 downto 0);
J: in STD_LOGIC_vector(7 downto 0);
K: in STD_LOGIC_vector(7 downto 0);
S0: in std_LOGIC_vector(3 downto 0);
Z: out STD_LOGIC_vector(7 downto 0)
);
END COMPONENT ;
signal clk : std_LOGIC;
constant clk_period: time:=100ns;
begin
umux: Mux11 port map(T_A,T_B,T_C,T_D,T_E,T_F,T_G,T_H,T_I,T_J,T_K,T_S,T_Z);
clk_process:process
begin
clk<='0';
wait for clk_period/2;
clk <='1';
wait for clk_period/2;
end process;
PROCESS
begin
if T_S="0001" then
T_Z <= T_A ;
elsif T_S="0010" then
T_Z <= T_B ; wait for 100 ns;
elsif T_S="0011" then
T_Z <= T_C ; wait for 100 ns;
elsif T_S="0100" then
T_Z <= T_D ; wait for 100 ns;
elsif T_S="0101" then
T_Z <=T_E ; wait for 100 ns;
elsif T_S="0110" then
T_Z <= T_F ; wait for 100 ns;
elsif T_S="0111" then
T_Z <= T_G ; wait for 100 ns;
elsif T_S="1000" then
T_Z <= T_H ; wait for 100 ns;
elsif T_S="1001" then
T_Z <= T_I ; wait for 100 ns;
elsif T_S="1010" then
T_Z <= T_J ; wait for 100 ns;
elsif T_S="1011" then
T_Z <= T_K ; wait for 100 ns;
wait;
end if;
end PROCESS;
end architecture test;
is there anyone who could tell me if im on the right path and if this is fully synchronous and how would i start implementing or determining 2 cycles of latency?

I try to write a clear answer to help you.
First of all you need a clock in your design let's call it clk.
entity Mux is
port(
clk: in std_logic;
A: in STD_LOGIC_vector(7 downto 0);
B: in STD_LOGIC_vector(7 downto 0);
C: in STD_LOGIC_vector(7 downto 0);
D: in STD_LOGIC_vector(7 downto 0);
E: in STD_LOGIC_vector(7 downto 0);
F: in STD_LOGIC_vector(7 downto 0);
G: in STD_LOGIC_vector(7 downto 0);
H: in STD_LOGIC_vector(7 downto 0);
I: in STD_LOGIC_vector(7 downto 0);
J: in STD_LOGIC_vector(7 downto 0);
K: in STD_LOGIC_vector(7 downto 0);
S0: in std_LOGIC_vector(3 downto 0);
Z: out STD_LOGIC_vector(7 downto 0));
end Mux;
The idea when you use synchronous processes is to always update your values on an edge of your clock. Let's say the rising edge. Thus your processes have to be only sensitive to your input clk.
P : PROCESS (clk)
BEGIN
IF (rising_edge(clk)) THEN
...
END IF;
END PROCESS;
Concerning your multiplexer, your idea was good. Yet I would suggest to use a CASE statement because it is easier to read than IF ELSIF.
CASE S0 IS
WHEN "0001" => Z <= A;
WHEN "0010" => Z <= B;
...
WHEN "1011" => Z <= K;
END CASE;
EDIT : since I forgot to talk about the 2 cycles latency I'll say two words. There you need two intermediate signals (ie Z_i and Z_ii). Z_ii takes Z_i after one clock cycle and Z takes Z_ii after one clock cycle.
Z_ii <= Z_i;
Z <= Z_ii;
Of course you then need to drive Z_i (and not Z) in you process.

Related

VHDL - Want to create a simple divider

I'm using Vivado 2018.2
I want to make a simple divider, say the input is 153 and the constant is 53. So with 153/53, I want to see 2 and the remainder 47.
The code I have so far errors out (sequential).
entity divider_main is
port(
dividend: in std_logic_vector(7 downto 0);
remainder: out std_logic_vector(5 downto 0);
quotient: out std_logic_vector(2 downto 0)
);
end divider_main;
architecture Behavioral of divider_main is
signal dividend_signal: signed(7 downto 0);
signal remainder_signal: std_logic_vector(5 downto 0);
signal fifty_three: signed(7 downto 0);
signal count: unsigned(2 downto 0);
begin
dividend_signal <= signed(dividend);
fifty_three <= "00011101";
count <= "000";
process(dividend, dividend_signal) is
begin
if dividend_signal < fifty_three then
remainder(5 downto 0) <= std_logic_vector(dividend_signal(5 downto 0));
quotient <= std_logic_vector(count);
dividend_signal <= "00000000";
count(2 downto 0) <= "000";
else
count <= count + 1;
dividend_signal <= dividend_signal - fifty_three;
quotient(2 downto 0) <= "000";
remainder <= "000000";
end if;
end process;
end Behavioral;
I'm new to vhdl so let me know what I am doing wrong!

VHDL-can't add numbers?

Hello I want to build a clock on my ALTERA DE2 that I can adjust the length of by pressing keys.
Now the problem is that when I convert from STD_LOGIC_VECTOR to UNSIGNED the code does not work:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
--use ieee.std_logic_unsigned.all; Do not use with numeric_std
entity Adjust_Clock_4_buttens is
port(
clk,clk1 : in STD_LOGIC;
minutes_plus, minutes_minus,houres_plus,houres_minus : in STD_LOGIC;
minutes : IN STD_LOGIC_VECTOR(5 downto 0);
houres : IN STD_LOGIC_VECTOR(4 downto 0);
output_minutes : out STD_LOGIC_VECTOR(5 downto 0);
output_houres : out STD_LOGIC_VECTOR(4 downto 0);
LED_0 : OUT STD_LOGIC;
LED_1 : OUT STD_LOGIC;
LED_2 : OUT STD_LOGIC;
LED_3 : OUT STD_LOGIC
);
end entity Adjust_Clock_4_buttens ;
architecture behavioral of Adjust_Clock_4_buttens is
signal button1_r : std_logic_vector(2 downto 0);
signal button2_r : std_logic_vector(2 downto 0);
signal button3_r : std_logic_vector(2 downto 0);
signal button4_r : std_logic_vector(2 downto 0);
-- signal minutes_total : unsigned(5 downto 0) := (others => '0');
-- signal houres_total : unsigned(4 downto 0) := (others => '0');
signal minutes_total : unsigned(5 downto 0);
signal houres_total : unsigned(4 downto 0);
begin
process(clk)
begin
if (rising_edge(clk) )then
minutes_total<=unsigned(minutes);
houres_total<=unsigned(houres);
-- Shift the value of button in button_r
-- The LSB is unused and is there solely for metastability
button1_r <= button1_r(button1_r'left-1 downto 0) & minutes_plus;
button2_r <= button2_r(button2_r'left-1 downto 0) & minutes_minus;
button3_r <= button3_r(button3_r'left-1 downto 0) & houres_plus;
button4_r <= button4_r(button4_r'left-1 downto 0) & houres_minus;
if button1_r(button1_r'left downto button1_r'left-1) = "01" then -- Button1 rising --button1_r[2:1]
minutes_total <= (minutes_total + 1);
LED_0<='1';LED_1<='0';LED_2<='0';LED_3<='0';
elsif button2_r(button2_r'left downto button2_r'left-1) = "01" then -- Button2 rising --button1_r[2:1]
minutes_total <= (minutes_total-1 );
LED_0<='0';LED_1<='1';LED_2<='0';LED_3<='0';
end if;
if button3_r(button3_r'left downto button3_r'left-1) = "01" then -- Button1 rising --button1_r[2:1]
houres_total <= (houres_total + 1);
LED_0<='0';LED_1<='0';LED_2<='1';LED_3<='0';
elsif button4_r(button4_r'left downto button4_r'left-1) = "01" then -- Button2 rising --button1_r[2:1]
houres_total<= (houres_total-1 );
LED_0<='0';LED_1<='0';LED_2<='0';LED_3<='1';
end if;
end if;
end process;
output_minutes <= std_logic_vector(minutes_total);
output_houres <= std_logic_vector(houres_total);
end architecture behavioral ;
So in this code I get the time from another block the problem start when I try to add minutes and hours and for some reason it does not react to pressing of the keys. Could anyone explain maybe why is that?
The problem might be that you only have the clock in the sensitivity list of your process. Try adding the buttons in the sensitivity list, since they drive your if conditions. (Not sure if that's the problem but I guess it's worth a try)
minutes_total<=unsigned(minutes);
is on 2 lines, inside and outside of the process, which generates multiple line drivers, and will not work, ever!
(didn't read the rest of the code, there may be other problems, like hours not taking an e)
Now that it's inside the process, you need to rename minutes_total as minute_source, else you're incrementing the value only for the one clock cycle when you have a button edge!

Can't get VHDL Sequential Multiplier to Multiply correctly

I have a School Lab that I must do pertaining to creating a sequential multiplier in VHDL. My issues is happening before making the finite state machine for the sequential multiplier. I can not get the base model to multiply correctly, I think I have a issue in my test bench but am not 100% sure of this. I still have doubt that the issue is in my code.
Top Design (basically calling the D-Flip-Flops, MUX and Adder)
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
--use ieee.std_logic_arith.all;
--use ieee.std_logic_unsigned.all;
entity toplvds is
port( A,B: in std_logic_vector(3 downto 0);
Zero: in std_logic_vector(3 downto 0);
clk, clr, load, loadP, sb: in std_logic;
Po: out std_logic_vector(7 downto 0));
end toplvds;
architecture Behavioral of toplvds is
component dffa
port( dina: in std_logic_vector(3 downto 0);
clr, clk, load: in std_logic;
q: out std_logic_vector(3 downto 0));
end component;
component dffb
port( dinb: in std_logic_vector(3 downto 0);
clr, clk, load, sb: in std_logic;
qb0: out std_logic);
end component;
component mux
port( d0,d1: in std_logic_vector(3 downto 0);
s: in std_logic;
y: out std_logic_vector(3 downto 0));
end component;
component adder
port( a,b: in std_logic_vector(3 downto 0);
cry: out std_logic;
r: out std_logic_vector(3 downto 0));
end component;
component dffP
port( dinp: in std_logic_vector(3 downto 0);
carry: in std_logic;
clr, clk, loadP, sb: in std_logic;
PHout: out std_logic_vector (3 downto 0);
P: out std_logic_vector(7 downto 0));
end component;
signal Wire1: std_logic_vector(3 downto 0);
signal Wire2: std_logic_vector(3 downto 0);
signal Wire3: std_logic;
signal Wire4: std_logic_vector(3 downto 0);
signal Wire5: std_logic_vector(3 downto 0);
signal Wire6: std_logic_vector(3 downto 0);
signal Wire7: std_logic;
begin
Wire1 <= Zero;
u1: dffa port map (dina=>A,clr=>clr,clk=>clk,load=>load,q=>Wire2);
u2: dffb port map (dinb=>B,clr=>clr,clk=>clk,load=>load,sb=>sb,qb0=>Wire3);
u3: mux port map (d0=>Wire2,d1=>Wire1,s=>Wire3,y=>Wire4);
u4: adder port map (a=>Wire6,b=>Wire4,cry=>Wire7,r=>Wire5);
u5: dffp port map (dinp=>Wire5,carry=>Wire7,clr=>clr,clk=>clk,loadP=>loadP,sb=>sb,PHout=>Wire6,P=>Po);
end Behavioral;
D-Flip-Flop for Multiplicand
library ieee;
use ieee.std_logic_1164.all;
entity dffa is
port( dina: in std_logic_vector(3 downto 0);
clr, clk, load: in std_logic;
q: out std_logic_vector(3 downto 0));
end dffa;
architecture beh of dffa is
begin
process(clk,clr)
begin
if(clr = '1') then
q <= ( others => '0');
elsif (rising_edge(clk)) then
if(load = '1') then
q <= dina;
end if;
end if;
end process;
end beh;
D-Flip-Flop for Multiplier
library ieee;
use ieee.std_logic_1164.all;
entity dffb is
port( dinb: in std_logic_vector(3 downto 0);
clr, clk, load, sb: in std_logic;
qb0: out std_logic);
end dffb;
architecture beh of dffb is
signal q: std_logic_vector(3 downto 0);
begin
qb0 <= q(0);
process(clk,clr, load, sb)
begin
if(clr = '1') then
q <= ( others => '0');
elsif (rising_edge(clk)) then
if(load = '1') then
q <= dinb;
elsif (sb = '1') then
q <= '0' & q ( 3 downto 1);
end if;
end if;
end process;
end beh;
MUX
library ieee;
use ieee.std_logic_1164.all;
entity mux is
port( d0,d1: in std_logic_vector(3 downto 0);
s: in std_logic;
y: out std_logic_vector(3 downto 0));
end mux;
architecture beh of mux is
begin
y <= d0 when s = '1' else d1;
end beh;
Adder
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.std_logic_arith.all;
entity adder is
port( a,b: in std_logic_vector(3 downto 0);
cry: out std_logic;
r: out std_logic_vector(3 downto 0));
end adder;
architecture beh of adder is
signal temp : std_logic_vector(4 downto 0);
begin
temp <= ('0' & a) + ('0' & b);
r <= temp(3 downto 0);
cry <= temp(4);
end beh;
D-Flip-Flop for Product
library ieee;
use ieee.std_logic_1164.all;
entity dffp is
port( dinp: in std_logic_vector(3 downto 0);
carry: in std_logic;
clr, clk, loadP, sb: in std_logic;
PHout: out std_logic_vector (3 downto 0);
P: out std_logic_vector(7 downto 0));
end dffp;
architecture beh of dffp is
signal q: std_logic_vector(7 downto 0);
begin
--qp0 <= q(0);
process(clk,clr, loadP, sb)
begin
if(clr = '1') then
q <= ( others => '0');
elsif (rising_edge(clk)) then
if(loadP = '1') then
--q <= "00000000";
q(7 downto 4) <= dinp;
elsif (sb = '1') then
q <= carry & q ( 7 downto 1);
--else
--q(7 downto 4) <= dinp;
end if;
end if;
end process;
PHout <= q(7 downto 4);
P <= q;
end beh;
TEST-BENCH Code
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
--USE ieee.numeric_std.ALL;
ENTITY toplvds_tb IS
END toplvds_tb;
ARCHITECTURE behavior OF toplvds_tb IS
-- Component Declaration for the Unit Under Test (UUT)
COMPONENT toplvds
PORT(
A : IN std_logic_vector(3 downto 0);
B : IN std_logic_vector(3 downto 0);
Zero : IN std_logic_vector(3 downto 0);
clk : IN std_logic;
clr : IN std_logic;
load : IN std_logic;
loadP : IN std_logic;
sb : IN std_logic;
Po : OUT std_logic_vector(7 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 Zero : std_logic_vector(3 downto 0) := (others => '0');
signal clk : std_logic := '0';
signal clr : std_logic := '0';
signal load : std_logic := '0';
signal loadP : std_logic := '0';
signal sb : std_logic := '0';
--Outputs
signal Po : std_logic_vector(7 downto 0);
-- Clock period definitions
constant clk_period : time := 10 ns;
BEGIN
-- Instantiate the Unit Under Test (UUT)
uut: toplvds PORT MAP (
A => A,
B => B,
Zero => Zero,
clk => clk,
clr => clr,
load => load,
loadP => loadP,
sb => sb,
Po => Po
);
-- Clock process definitions
clk_process :process
begin
clk <= '0';
wait for clk_period/2;
clk <= '1';
wait for clk_period/2;
end process;
-- Stimulus process
stim_proc: process
begin
A <= "1011";
B <= "1101";
Zero <="0000";
load <= '0';
sb <= '0';
clr <= '1';
wait for 12 ns;
clr <= '0'; load <= '1';
wait for 12 ns;
load <= '0'; sb <= '1';
wait for 12 ns;
sb <= '0'; loadP <= '1';
wait for 12 ns;
loadP <= '0'; sb <= '1';
wait for 12 ns;
sb <= '0'; loadP <= '1';
wait for 12 ns;
loadP <= '0'; sb <= '1';
wait for 12 ns;
sb <= '0'; loadP <= '1';
wait for 12 ns;
loadP <= '0'; sb <= '1';
wait for 12 ns;
sb <= '0'; loadP <= '1';
wait for 12 ns;
loadP <= '0'; sb <= '1';
wait for 20 ns;
loadP <= '0'; sb <= '0';
wait;
end process;
END;
Sorry that I have not commented the code for better understanding. I know this will be hard to follow but I hope someone will. I will also attach an image of the figure of the sequential multiplier I am following, the circuit design.
4 by 4 binary sequential multiplier circuit
4 by 4 binary sequential multiplier circuit - more
Well it was indeed something in the testbench that was giving issues. I worked it out in the lab with fellow classmates. Thank You for your help anyways it is much appreciated.
p.s. All I did was changed some timing values in the testbench at the very bottom to when the load and shift bit would happen and I got it to work.

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.

test bench of a 32x8 register file VHDL

I wrote the assembly code for this circuit in vhdl already. I want to simulate it with a test bench.
RegWrite: 1 bit input (clock)
Write Register Number: 3-bit input(write addresses)
Write Data: 32-bit input (data in) Read
Register Number A: 3-bit input (read addresses)
Read Register Number B: 3-bit input (read adddresses)
Port A: 32-bit output (data out)
Port B: 32-bit output (data out)
I think my problem is that I don't understand what this circuit does. I chose random values to assign to the inputs, but it didn't output anything. What are good inputs to choose for this circuit?
here is my test bench file for reference:
library ieee;
use ieee.std_logic_1164.all;
entity Reg_TB is -- entity declaration
end Reg_TB;
architecture TB of Reg_TB is
component RegisterFile_32x8
port ( RegWrite: in std_logic;
WriteRegNum: in std_logic_vector(2 downto 0);
WriteData: in std_logic_vector(31 downto 0);
ReadRegNumA: in std_logic_vector(2 downto 0);
ReadRegNumB: in std_logic_vector(2 downto 0);
PortA: out std_logic_vector(31 downto 0);
PortB: out std_logic_vector(31 downto 0)
);
end component;
signal T_RegWrite : std_logic;
signal T_WriteRegNum: std_logic_vector(2 downto 0);
signal T_WriteData: std_logic_vector(31 downto 0);
signal T_ReadRegNumA: std_logic_vector(2 downto 0);
signal T_ReadRegNumB: std_logic_vector(2 downto 0);
signal T_PortA : std_logic_vector(31 downto 0);
signal T_PortB : std_logic_vector(31 downto 0);
begin
T_WriteRegNum <= "011";
T_WriteData <= "00000000000000000000000000000001";
T_ReadRegNumA <= "001";
T_ReadRegNumB <= "100";
U_RegFile: RegisterFile_32x8 port map
(T_RegWrite, T_WriteRegNum, T_WriteData,T_ReadRegNumA, T_ReadRegNumB, T_PortA, T_PortB);
-- concurrent process to offer clock signal
process
begin
T_RegWrite <= '0';
wait for 5 ns;
T_RegWrite <= '1';
wait for 5 ns;
end process;
process
begin
wait for 12 ns;
-- case 2
wait for 28 ns;
-- case 3
wait for 2 ns;
-- case 4
wait for 10 ns;
-- case 5
wait for 20 ns;
wait;
end process;
end TB;
as you can see I chose
WriteRegNum = "011"
WriteData = "00000000000000000000000000000001"
ReadRegNumA = "001"
ReadRegNumB = "100"
I think that I chose bad inputs. The simulation does this:
In general reading an address before it is written doesn't produce any useful results.
Your block diagram shows a 32 bit wide 8 word deep register file with two read ports and one write port with RegWrite used as a clock gated by the decode of the write address. A stable WriteRegNum value and a rising edge on RegWrite effects a write to the address specified by WriteRegNum.
The two read ports appear completely independent. Specifying an address on the respective ReadRegNumA or ReadRegNumB should output the contents of that register to the respective output port.
To get something useful out, you have to write to that location first, otherwise it will be the default value ((others => 'U'),) suspiciously like your waveform.
Trying writing to a location before expecting valid read data from it. Use values that are distinguishable by register location. Theoretically you should be preserving set up and hold time on WriteRegNum with respect to the rising edge of RegWrite.
Example stimulus producing output:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity registerfile_32x8 is
port (
RegWrite: in std_logic;
WriteRegNum: in std_logic_vector (2 downto 0);
WriteData: in std_logic_vector (31 downto 0);
ReadRegNumA: in std_logic_vector (2 downto 0);
ReadRegNumB: in std_logic_vector (2 downto 0);
PortA: out std_logic_vector (31 downto 0);
PortB: out std_logic_vector (31 downto 0)
);
end entity;
architecture fum of registerfile_32x8 is
type reg_array is array (0 to 7) of std_logic_vector(31 downto 0);
signal reg_file: reg_array;
begin
process(RegWrite)
begin
if rising_edge(RegWrite) then
reg_file(to_integer(unsigned(WriteRegNum))) <= WriteData;
end if;
end process;
PortA <= reg_file(to_integer(unsigned(ReadRegNumA)));
PortB <= reg_file(to_integer(unsigned(ReadRegNumB)));
end architecture;
library ieee;
use ieee.std_logic_1164.all;
entity reg_tb is
end entity;
architecture fum of reg_tb is
component registerfile_32x8
port (
RegWrite: in std_logic;
WriteRegNum: in std_logic_vector (2 downto 0);
WriteData: in std_logic_vector (31 downto 0);
ReadRegNumA: in std_logic_vector (2 downto 0);
ReadRegNumB: in std_logic_vector (2 downto 0);
PortA: out std_logic_vector (31 downto 0);
PortB: out std_logic_vector (31 downto 0)
);
end component;
signal RegWrite: std_logic := '1';
signal WriteRegNum: std_logic_vector (2 downto 0) := "000";
signal WriteData: std_logic_vector (31 downto 0) := (others => '0');
signal ReadRegNumA: std_logic_vector (2 downto 0) := "000";
signal ReadRegNumB: std_logic_vector (2 downto 0) := "000";
signal PortA: std_logic_vector (31 downto 0);
signal PortB: std_logic_vector (31 downto 0);
begin
DUT:
registerfile_32x8
port map (
RegWrite => RegWrite,
WriteRegNum => WriteRegNum,
WriteData => WriteData,
ReadRegNumA => ReadRegNumA,
ReadRegNumB => ReadRegNumB,
PortA => PortA,
PortB => PortB
);
STIMULUS:
process
begin
wait for 20 ns;
RegWrite <= '0';
wait for 20 ns;
RegWrite <= '1';
wait for 20 ns;
WriteData <= x"feedface";
WriteRegnum <= "001";
RegWrite <= '0';
wait for 20 ns;
RegWrite <= '1';
ReadRegNumA <= "001";
wait for 20 ns;
WriteData <= x"deadbeef";
WriteRegNum <= "010";
ReadRegNumB <= "010";
RegWrite <= '0';
wait for 20 ns;
RegWrite <= '1';
wait for 20 ns;
wait for 20 ns;
wait;
end process;
end architecture;
david_koontz#Macbook: ghdl -a regfile_32x8.vhdl
david_koontz#Macbook: ghdl -e reg_tb
david_koontz#Macbook: ghdl -r reg_tb --wave=reg_tb.ghw
david_koontz#Macbook: open reg_tb.gtkw
Essentially, the point is to have non 'U' values in a register file that's being read. If you notice the last write to WriteRegNum = "010", PortB shows undefined output until the write occurs.

Resources