Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

VHDL: CPU Register file help

Status
Not open for further replies.

NYFinest

Newbie level 3
Newbie level 3
Joined
Nov 29, 2013
Messages
3
Helped
0
Reputation
0
Reaction score
0
Trophy points
1
Visit site
Activity points
85
Hello,

I am currently working on designing a CPU using VHDL. I am currently working on the register file portion and running into difficulties.
The design is output the contents of the registers on the input. The values are read out on a positive clock edge, values are written on negative clock edge. There is also forwarding if write register and a read register is the same, in that case the new value is sent out first then written.

Now, in my test bench if i write values first then read them after it works as expected. In reality I want to read the values first, since I am going to preload the registers with random values. In the code you'll see reg(0) - reg(3) loaded with the value. In the test want to read register 0 but I get all outputs as "U". If I comment out my write process then I get the values I want. I cant figure out whats wrong with my code.

My questions are:
Is there a way to load the register array inside my module in the testbench?
Am I doing something wrong in my module and how can I fix it.

Thank you for your time.

Module


Code VHDL - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
 
entity register_file is
    port(   
        clk : in std_logic;      
        write : in std_logic;
        regA : in std_logic_vector(3 downto 0);
        regB : in std_logic_vector(3 downto 0);
        regW : in std_logic_vector(3 downto 0);
        dataA : out std_logic_vector(63 downto 0);           
        dataB : out std_logic_vector(63 downto 0);
        dataW : in std_logic_vector(63 downto 0)
    );
end register_file;
 
architecture behavioral of register_file is              
 
type reg_array is array(15 downto 0) of std_logic_vector(63 downto 0);
signal reg : reg_array;               
signal data_write : std_logic_vector(63 downto 0);
 
begin       
    reg(0) <= X"FFFFEEEEAAAABBBB"; 
    reg(1) <= X"FFFFEEEEAAAABBBB"; 
    reg(2) <= X"FFFFEEEEAAAABBBB"; 
    
    read_prc: process(clk)
    begin   
        if rising_edge(clk) then
            dataA <= reg(to_integer(unsigned(regA)));
            dataB <= reg(to_integer(unsigned(regB)));     
        end if;
    end process read_prc;
    
    write_prc: process(clk, write)
    begin
        if (write = '1' AND falling_edge(clk)) then                  
                data_write <= dataW;
                reg (to_integer(unsigned(regW))) <= data_write;
            end if;
    end process write_prc;   
    
    bypass_prc: process(clk)
    begin
        if (regA = regW) then
            if write = '1' then
                if rising_edge(clk) then
                    dataA <= dataW;
                end if;
            end if;
        end if;    
        
        if (regB = regW) then
            if write = '1' then
                if rising_edge(clk) then
                    dataB <= dataW;
                end if;
            end if;
        end if;
        
    end process bypass_prc;
end behavioral;




TestBench


Code VHDL - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE ieee.std_logic_unsigned.all;
 
-- entity declaration for your testbench.Dont declare any ports here
ENTITY test_tb IS 
END test_tb;
 
ARCHITECTURE behavior OF test_tb IS
   -- Component Declaration for the Unit Under Test (UUT)
    COMPONENT register_file  --'test' is the name of the module needed to be tested.
--just copy and paste the input and output ports of your module as such. 
    PORT( 
        clk : in std_logic;      
        write : in std_logic;
        regA : in std_logic_vector(3 downto 0);
        regB : in std_logic_vector(3 downto 0);
        regW : in std_logic_vector(3 downto 0);
        dataA : out std_logic_vector(63 downto 0);           
        dataB : out std_logic_vector(63 downto 0);
        dataW : in std_logic_vector(63 downto 0)
        );
    END COMPONENT;
   --declare inputs and initialize them
   signal clk : std_logic := '0';
   signal write : std_logic := '0';  
   signal regA : std_logic_vector(3 downto 0) := "0000";     
   signal regB : std_logic_vector(3 downto 0) := "0000";
   signal regW : std_logic_vector(3 downto 0) := "0001";      
   signal dataW : std_logic_vector(63 downto 0) := X"0000000000000FFF";
   --declare outputs and initialize them
   signal dataA : std_logic_vector(63 downto 0);   
   signal dataB : std_logic_vector(63 downto 0);
   
   -- Clock period definitions
   constant clk_period : time := 50 ns;  
   
   
BEGIN
    -- Instantiate the Unit Under Test (UUT)
   uut: register_file PORT MAP (
         clk => clk,
          write => write,
          regA => regA,    
          regB => regB,
          regW => regW,  
          dataA => dataA, 
          dataB => dataB,
          dataW => dataW    
        );       
 
   -- Clock process definitions( clock with 50% duty cycle is generated here.
   clk_process :process
   begin
        clk <= '0';
        wait for clk_period/2;  --for 0.5 ns signal is '0'.
        clk <= '1';
        wait for clk_period/2;  --for next 0.5 ns signal is '1'.
   end process;
   -- Stimulus process
  stim_proc: process
   begin         
        wait for 10 ns;
--      regW <= "0001"; 
--      dataW <= X"0000000000000FFF";
--      wait for 5 ns;
--      write <= '1';
--      wait for 5 ns;
--      write <= '0';
--      wait for 10 ns;
--      regW <= "0010";  
--      dataW <= X"FFF000000000000A";
--      wait for 5 ns;
--      write <= '1';
--      wait for 5 ns;
--      write <= '0';
--      wait for 10 ns;
--      regA <= "0001";
--      regB <= "0010";
--      wait for 5 ns;
--      regW <= "0010"; 
--      dataW <= X"000000000000EEEE";
--      wait for 5 ns;
--      write <= '1';
--      wait for 5 ns;
--      write <= '0';
--      wait for 10 ns;
write <= '0';
regA <= "0000";
regB <= "0000";
regW <= "0011"; 
  end process;
 
END;

 
Last edited by a moderator:

Are you sure it is 'U' and not 'X'?
In VHDL, you are only allowed to assign a signal in a single process. An assignment outside a process is essentially a self contained process. So the conflict with the assignment inside and outside the write process is whats causing the problem.

I would initialise all the values to the fixed value, remove the constant assignments outside the write process then you should read the correct values.
 
Hello,

Yes they are coming out as 'U'. So I took your suggestion and changed the code around. Now It works. My bypass_prc is doing the same thing. I forgot to mention before that I was testing my write prc while having my bypass_prc commented out. In this process if i comment out dataA <= dataW I get the values I want, but if don't I get the output as 'U'. So I think that the read_prc and bypass_prc are conflicting with each other.

Thank you for your time.

Updated Code


Code VHDL - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
 
entity register_file is
    port(   
        clk : in std_logic;      
        write : in std_logic;
        regA : in std_logic_vector(3 downto 0);
        regB : in std_logic_vector(3 downto 0);
        regW : in std_logic_vector(3 downto 0);
        dataA : out std_logic_vector(63 downto 0);           
        dataB : out std_logic_vector(63 downto 0);
        dataW : in std_logic_vector(63 downto 0)
    );
end register_file;
 
architecture behavioral of register_file is              
 
type reg_array is array(15 downto 0) of std_logic_vector(63 downto 0);
signal reg : reg_array := (X"FFFFEEEEAAAABBBB", X"FFFFEEEEAAAABBBB", X"FFFFEEEEAAAABBBB", X"FFFFEEEEAAAABBBB",
X"FFFFEEEEAAAABBBB", X"FFFFEEEEAAAABBBB", X"FFFFEEEEAAAABBBB", X"FFFFEEEEAAAABBBB",
X"FFFFEEEEAAAABBBB", X"FFFFEEEEAAAABBBB", X"FFFFEEEEAAAABBBB", X"FFFFEEEEAAAABBBB",
X"FFFFEEEEAAAABBBB", X"FFFFEEEEAAAABBBB", X"FFFFEEEEAAAABBBB", X"FFFFEEEEAAAABBBB");
 
begin       
    
    read_prc: process(clk)
    begin   
        if rising_edge(clk) then
            dataA <= reg(to_integer(unsigned(regA)));
            dataB <= reg(to_integer(unsigned(regB)));     
        end if;
    end process read_prc;
    
    write_prc: process(clk, write)
    begin
        if (write = '1' AND falling_edge(clk)) then                  
                reg (to_integer(unsigned(regW))) <= dataW;
            end if;
    end process write_prc;   
    
    bypass_prc: process(clk, write)
    begin
        if (regA = regW AND write = '1' AND rising_edge(clk)) then
            dataA <= dataW;
        end if;    
--      
--      if (regB = regW) then
--          if write = '1' then
--              if rising_edge(clk) then
--                  dataB <= dataW;
--              end if;
--          end if;
--      end if;
        
    end process bypass_prc;
end behavioral;

 

Thank you for your reply. I actually fixed it few minutes after I posted.

I have 1 more question. When I simulate the inputs are U's. So on falling edge on a U input it provides me the contents of register 0.
Is their a way to prevent this from happening? i was thinking of hardcoding if = U then output U but I haven't been able to implement this.


Thank you for your time.


waveform.png


Code VHDL - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
 
entity register_file is
    port(   
        clk : in std_logic;      
        write : in std_logic;
        regA : in std_logic_vector(3 downto 0);
        regB : in std_logic_vector(3 downto 0);
        regW : in std_logic_vector(3 downto 0);
        dataA : out std_logic_vector(63 downto 0);           
        dataB : out std_logic_vector(63 downto 0);
        dataW : in std_logic_vector(63 downto 0)
    );
end register_file;
 
architecture behavioral of register_file is              
 
type reg_array is array(15 downto 0) of std_logic_vector(63 downto 0);
signal reg : reg_array := (X"1111111111111111", X"2222222222222222", X"FFFFEEEEAAAABBBB", X"FFFFEEEEAAAABBBB",
X"FFFFEEEEAAAABBBB", X"FFFFEEEEAAAABBBB", X"FFFFEEEEAAAABBBB", X"FFFFEEEEAAAABBBB",
X"FFFFEEEEAAAABBBB", X"FFFFEEEEAAAABBBB", X"FFFFEEEEAAAABBBB", X"FFFFEEEEAAAABBBB",
X"FFFFEEEEAAAABBBB", X"FFFFEEEEAAAABBBB", X"AAAAAAAAAAAAAAAA", X"EEEEEEEEEEEEEEEE");
 
begin       
    
    read_prc: process(clk)
    begin   
        if falling_edge(clk) then
            --dataA <= reg(to_integer(unsigned(regA)));
            --dataB <= reg(to_integer(unsigned(regB))); 
        
            if (regA = regW AND write = '1') then
                dataA <= dataW;            
            --end if;
            elsif (regB = regW AND write = '1') then
                dataB <= dataW;
            --end if;
            else
            dataA <= reg(to_integer(unsigned(regA)));
            dataB <= reg(to_integer(unsigned(regB)));
            end if;  
        end if;
        
    
    end process read_prc;
    
    write_prc: process(clk, write)
    begin
        if (write = '1' AND falling_edge(clk)) then                  
                reg (to_integer(unsigned(regW))) <= dataW;
            end if;
    end process write_prc;   
    
end behavioral;

 

These U values are because the reg signals are not initialised. In real hardware they will start off as either '1' or '0', so checking for 'U' would only serve a purpose in simulation.
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top