Kim
Kim

Reputation: 43

VHDL - coding error of value outside the clock edge

library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.std_logic_arith.all;
entity RAM_controler is 
port(
      clk_50 : in std_logic;
      clk_baud : in std_logic;
      main_reset : in std_logic;
      enable: in std_logic; --active high write enable
      in_data : in std_logic_vector(7 downto 0);
      W_order : out std_logic; 
      R_order : out std_logic;
      Data_OUT : out std_logic_vector(7 downto 0);
      Write_Address_OUT: out std_logic_vector(7 downto 0);  
      Read_Address_OUT: out std_logic_vector(7 downto 0)          
      );
end entity RAM_controler;
architecture Behavioral of RAM_controler is
type state is (reset,operation);
signal state_reg,next_state_reg : state;
signal write_address : std_logic_vector(W-1 downto 0):="00000000"; 
signal next_write_address : std_logic_vector(W-1 downto 0):="00000000";         
begin   
state_change : process(clk_50, main_reset)
begin
    if (main_reset = '1') then
        state_reg <= reset;     
    elsif (rising_edge(clk_50)) then
        state_reg <= operation;
        read_counter <= next_read_counter;
        write_address<= next_write_address;
        read_address <= next_read_address;
    end if;     
end process;

writecounter : process(clk_baud, main_reset,enable) 
begin
    if (main_reset='1') then
        next_write_address <= "00000000";
        Data_OUT <= "ZZZZZZZZ";
        W_order <='0';
        Write_Address_OUT <="ZZZZZZZZ";
    elsif (rising_edge(clk_baud) and enable='1' ) then
        W_order <='1';
        Data_OUT <= in_data;            
        Write_Address_OUT <= write_address;
        if (write_address = "11111111") then
            next_write_address <= "00000000";
        else
            next_write_address <= write_address+1;
        end if;
    else 
        W_order <='0';
        Write_Address_OUT <= "ZZZZZZZZ";
        next_write_address <= write_address+1;
    end if;
end process;        
end Behavioral;

Above code is describing RAM controller.

The part of making problem is "elsif (rising_edge(clk_baud) and enable='1' ) then".

Error : Can`t inter register for "Write_Address_OUT" at RAM_controler.vhd because it does not hold its value outside the clock edge

I don`t know why that point is error.

Is there anyone who advice to me?

Thank you!

Upvotes: 0

Views: 643

Answers (2)

Matthew
Matthew

Reputation: 14007

If you're coding sequential logic, it is wise to stick to a template. Here is one such template for sequential logic with an asynchronous reset, which all synthesis tools should understand:

process(clock, async_reset)  -- nothing else should go in the sensitivity list
begin
    -- never put anything here
    if async_reset ='1' then  -- or '0' for an active low reset
        -- set/reset the flip-flops here
        -- ie drive the signals to their initial values
    elsif rising_edge(clock) then  -- or falling_edge(clock)
        -- put the synchronous stuff here
        -- ie the stuff that happens on the rising or falling edge of the clock
    end if;
     -- never put anything here
end process;        

So enable should not be in the senstivity list and it should not be tested in the same if statement as the asynchronous reset and the clock is tested.

The reason why your are getting this error:

Error : Can`t inter register for "Write_Address_OUT" at RAM_controler.vhd because it does not hold its value outside the clock edge

is because the last three assignments in your code:

            W_order <='0';
            Write_Address_OUT <= "ZZZZZZZZ";
            next_write_address <= write_address+1;

can occur on the falling edge of the clock or (because you also had enable in your sensitivity list) independently of any clock at all. A logic synthesiser can't synthesise logic that behaves like that. If you stick to the template, you won't run into this kind of problem (and it makes you think a bit more carefully about what logic you are expecting the synthesiser to synthesise).

So, I would have coded your writecounter process more like this:

writecounter : process(clk_baud, main_reset) 
begin
    if (main_reset='1') then
        next_write_address <= "00000000";
        Data_OUT <= "ZZZZZZZZ";
        W_order <='0';
        Write_Address_OUT <="ZZZZZZZZ";
    elsif rising_edge(clk_baud) then
        if enable='1' then
            W_order <='1';
            Data_OUT <= in_data;            
            Write_Address_OUT <= write_address;
            if (write_address = "11111111") then
                next_write_address <= "00000000";
            else
                next_write_address <= write_address+1;
            end if;
        else 
            W_order <='0';
            Write_Address_OUT <= "ZZZZZZZZ";
            next_write_address <= write_address+1;
        end if;
    end if;
end process;        

Though, I should emphasise that my code does not behave exactly like yours. I don't know your design intent, so I can only guess what you intended. If you intended some other behaviour, then you will have to implement that instead. My advice about sticking to a template is nevertheless important, whatever your design intent.

Upvotes: 2

Bill Lynch
Bill Lynch

Reputation: 82026

The final else in your code should actually be:

elsif (rising_edge(clk_baud) and enable='0' ) then

Upvotes: 0

Related Questions