2

I am trying to create a phase accumulator using VHDL that has the following characteristics.

Inputs:

  • D (Input signal)
  • RESET
  • CE
  • CLK

Outputs:

  • Q (output signal - feedback)

Source code:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity Phase_accu is
port (
    D       : in std_logic_vector(3 downto 0);
    CE      : in std_logic;
    CLK     : in std_logic;
    RESET   : in std_logic;
    Q       : out std_logic_vector(15 downto 0)
);
end Phase_accu;

architecture Behavioral of Phase_accu is
begin

process(D, CE, CLK, RESET)
    begin
        if RESET = '1' then
            Q <= "0000000000000000";
        elsif rising_edge(CLK) then
            if CE = '1' then
                Q <= ("000000000000" & D) + Q;
            end if;
        end if;
end process;

end Behavioral;

I get an error with the line trying to merge together the 2 signals for feedback...

Q <= ("000000000000" & D) + Q;

Cannot read output "Q".

mucka
  • 1,286
  • 3
  • 20
  • 36
Paul James
  • 121
  • 2
  • 7
  • Removing the superfluous `use` before `library` on the first line of your code and using VHDL revision -2008 your code analyzes and elaborates (evaluating a port of mode out is possible in -2008). Please provide a [mcve] including complete error message and identifying the operation your tool was performing, the problem isn't guaranteed reproducible from your question as is. –  Feb 05 '19 at 20:05

2 Answers2

6

You can't read the value of an out in VHDL revisions prior to VHDL-2008. The usual way to get around this is to have an internal copy of your output, and use that internal copy when you need to get its value:

[...]
Q : out std_logic_vector(15 downto 0);
[...]
signal Q_reg : std_logic_vector(15 downto 0);

process(D, CE, CLK, RES)
    begin

        if RES = '1' then
            Q_reg <= "0000000000000000";
        elsif rising_edge(CLK) then
            if CE = '1' then
                Q_reg <= ("000000000000" & D) + Q_reg;
            end if;
        end if;
end process;

Q <= Q_reg;
Kevin Kruse
  • 268
  • 2
  • 13
1

I suggest to use numeric_std library instead of STD_LOGIC_ARITH and STD_LOGIC_UNSIGNED. I also suggest to make some minor optimizations regarding the vector size specification.

Also the sensitivity list has two many entries. You have to remove D and CE to describe a valid clocked process with asynchronous reset. See your Synthesis tool manual for details.

This makes the code above to

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity Phase_accu is
port (
    D       : in std_logic_vector(3 downto 0);
    CE      : in std_logic;
    CLK     : in std_logic;
    RESET   : in std_logic;
    Q       : out std_logic_vector(15 downto 0)
);
end Phase_accu;

architecture Behavioral of Phase_accu is
    signal Q_reg : unsigned(Q'range);
begin

process(CLK, RES)
begin

        if RES = '1' then
            Q_reg <= (others => '0');
        elsif rising_edge(CLK) then
            if CE = '1' then
                Q_reg <= resize(unsigned(D), Q_reg'length) + Q_reg;
            end if;
        end if;

end process;

Q <= std_logic_vector(Q_reg);

end Behavioral;
ttobsen
  • 66
  • 1
  • 7