Trying to use a buffer in VHDL - not working

一个人想着一个人 提交于 2019-12-26 14:37:03

问题


My code produces the following error when compiling:

ERROR:HDLCompiler:439 - "E:/ELECTRONIC ENGINEERING 2/DIGITAL/Resit_Year/Assignment_7_seg/4_Bit_Counter/Bit_Counter/counter_tb.vhd" Line 47: Formal port count_out of mode buffer cannot be associated with actual port count_out of mode out ERROR:Simulator:777 - Static elaboration of top level VHDL design unit counter_tb in library work failed

don't know how to fix this.

full code:

-----------------------------------------------------------------------------------
    entity Four_Bit_Counter is

    Port ( clock : in  STD_LOGIC;
           reset : in  STD_LOGIC;
           pause : in  STD_LOGIC;
           count_out : buffer  STD_LOGIC_VECTOR (3 downto 0);
              student_id : buffer STD_LOGIC_VECTOR (3 downto 0)  ); 
      end Four_Bit_Counter;

----------------------------------------------------------------------------------
     architecture Behavioral of Four_Bit_Counter is

    signal temp_count : std_logic_vector(3 downto 0) := "0000" ;
    signal slow_clock : std_logic ;
    signal clock_divider : std_logic_vector(1 downto 0) := "00";
     variable cout_out : std_logic_vector(3 downto 0):= "0000";


    begin

---------------------------------------------------------------------------------

    clock_division : process (clock, clock_divider)

    begin

    if 
        clock'event and clock = '1' then
       clock_divider <= clock_divider + 1;

    end if;

    slow_clock <= clock_divider(1);

     end process;

--------------------------------------------------------------------------------
      counting : process(reset, pause, slow_clock, temp_count)

     begin

     if     reset = '1' then
            temp_count <= "0000";

        elsif pause = '1' then
            temp_count <= temp_count;
    else
    if slow_clock'event and slow_clock= '1' then
    if temp_count < 15 then
    temp_count <= temp_count + 1;
        else
            temp_count <= "0000";
            end if;
        end if;
    end if;

    count_out <= temp_count;

    end process;

----------------------------------------------------------------------------------
student : process (reset, pause, slow_clock, temp_count)

begin


            IF (cout_out = "0010")  THEN
            student_id <= "0010";
            ELSIF (cout_out = "0011")  THEN
            student_id <= "0001";
            ELSIF (cout_out = "0100")  THEN
            student_id <= "0000";
            ELSIF (cout_out = "0101")  THEN
            student_id <= "0000";
            ELSIF (cout_out = "0110")  THEN
            student_id <= "1001";
            ELSIF (cout_out = "0111")  THEN
            student_id <= "0011";
            ELSIF (cout_out = "1000")  THEN
            student_id <= "0010";
            ELSIF (cout_out = "1001")  THEN
            student_id <= "0110";
            ELSE student_id <= "1000";

            END IF;

end process student;

    --student_id <=  "0010" when count_out >= "0001" else
                        --"0001" when count_out >= "0011" else
                        --"0000" when count_out >= "0101" else
                        --"0000" when count_out >= "0111" else
                        --"1001" when count_out >= "1000" else
                        --"0011" when count_out >= "1001" else
                        --"0000" when count_out >= "1011" else
                        --"0110" when count_out >= "1100" else
                        --"1000";



end Behavioral;

回答1:


Old style VHDL : Buffer ports must be connected to Buffer ports (not Out ports) all the way up the hierarchy. The reason behind this made sense in the early days of VHDL but ASIC and FPGA technology has moved on, so has synthesis technology.

Old style solution : So make the out port in entity (you haven't posted enough code so I can't name it, but it's the next level up in the hierarchy) a buffer port too.

Workaround : If you're not allowed to change the port type in the higher level, you can connect the Buffer port to a signal, and assign that signal to the out port.

Newer VHDL : in VHDL-2002 this restriction was eliminated, so this should work if you select --std=vhdl2002 or equivalent option when compiling.

Newest VHDL : Because Buffer has been so poorly taught it's created so much confusion, that if you select --std=vhdl2008, out ports now allow reading the driving value just like buffer ports, so you can simply replace your buffer ports with out ports.




回答2:


Getting the design working first

There are multiple things wrong with the design specification, so it seems easier to get it working properly before showing usage as mode buffer.

"Full code:" is missing the context clause:

-- missing context clause:
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;

(Synopsys package std_logic_unsigned provides "+" operator [std_logic_vector, integer return std_logic_vector], may require -fexplicit or equivalent command line flag for some VHDL analyzers. There are two possible interpretations for the equality operator "=" with the same signature.)

Neither count_out nor student_id are evaluated in architecture behavioral, they can be declared as mode out. Unless you intended eliminating temp_count (wherein count_out could remain mode buffer, we'll do that later).

entity four_bit_counter is
    port ( 
        clock:      in      std_logic;
        reset:      in      std_logic;
        pause:      in      std_logic;
        count_out:  out     std_logic_vector (3 downto 0);
        student_id: out     std_logic_vector (3 downto 0) 
    ); 
end entity four_bit_counter;

As Brian notes the next level up in the hierarchy should have a directly connected port mode buffer for a four_bit_counter port of mode buffer. It isn't clear why you have ports on a test bench (the "_tb" in "E:/ELECTRONIC ENGINEERING 2/DIGITAL/Resit_Year/Assignment_7_seg/4_Bit_Counter/Bit_Counter/counter_tb.vhd"), it's not in evidence.

cout_out should be a signal not a variable. It's not used and can be eliminated:

    -- variable cout_out:      std_logic_vector(3 downto 0):= "0000";
    -- signal cout_out:        std_logic_vector(3 downto 0):= "0000"; 

cout_out is evaluated in process student but it appears it should be renamed wires connected to temp_count in process counting, so we can substitute temp_count for cout_out. The sensitivity list for process student should also only contain temp_count:

student: 
    process (temp_count) -- (reset, pause, slow_clock, temp_count)
    begin
        if temp_count = "0010"  then
            student_id <= "0010";
        elsif temp_count = "0011"  then
            student_id <= "0001";
        elsif temp_count = "0100"  then
            student_id <= "0000";
        elsif temp_count = "0101"  then
            student_id <= "0000";
        elsif temp_count = "0110"  then
            student_id <= "1001";
        elsif temp_count = "0111"  then
            student_id <= "0011";
        elsif temp_count = "1000"  then
            student_id <= "0010";
        elsif temp_count = "1001"  then
            student_id <= "0110";
        else 
            student_id <= "1000";
        end if;
    end process student;

There's also a design issue with pause:

counting: 
    process(reset, pause, slow_clock, temp_count)
    begin
        if reset = '1' then
            temp_count <= "0000";
        elsif pause = '1' then
            temp_count <= temp_count;
        else

It looks like pause should be synchronous. The reset is asynchronous and will use the clear inputs of the flip flops comprising the temp_count counter. The D inputs to those flip flops are an incrementor (the + 1). Adding an asynchronous control to a multiplexer selecting between the incrementor and the current value is essentially an enable, and should be expressed synchronously:

counting: 
    process (reset, slow_clock, temp_count) -- (reset, pause, slow_clock, temp_count)
    begin
        if reset = '1' then
            temp_count <= "0000";
        -- elsif pause = '1' then
        --     temp_count <= temp_count;
        -- else
            -- if slow_clock'event and slow_clock = '1' then
        elsif slow_clock'event and slow_clock = '1' and pause = '0' then
            if temp_count < 15 then
                temp_count <= temp_count + 1;
            else
                temp_count <= "0000";
            end if;
        end if;
        -- end if;
        count_out <= temp_count;
    end process;

(I also collapsed an if statement level, using elsif instead of else if).

So with those changes the design analyzes and elaborates successfully. (Counting on the default value of "00" to enable the increment clock_divider <= clock_divider + 1; to work correctly).

By adding a test bench:

library ieee;
use ieee.std_logic_1164.all;

entity four_bit_counter_tb is
end entity;

architecture foo of four_bit_counter_tb is
    signal clock:      std_logic := '0';
    signal reset:      std_logic;
    signal pause:      std_logic;
    signal count_out:  std_logic_vector (3 downto 0);
    signal student_id: std_logic_vector (3 downto 0);
begin
DUT:
    entity work.four_bit_counter
    port map ( 
        clock => clock,
        reset => reset,
        pause => pause,
        count_out => count_out,
        student_id => student_id
    ); 
CLK:
    process
    begin
        wait for 10 ns;
        clock <= not clock;
        if Now > 1.53 us then
            wait;
        end if;
    end process;
STIMULIS:
    process
    begin
        wait for 20 ns;
        pause <= '0';
        reset <= '1';
        wait for 20 ns;
        reset <= '0';
        wait for 140 ns;
        pause <= '1';
        wait for 40 ns;
        pause <= '0';
        wait;
        wait;
    end process;
end architecture;

We can simulate:

(image is clickable)

You can see that an invocation of pause stretched the temp_count cycle for temp_count = "0001".

You might also notice that count_out was always defined, there's a default value for temp_count.

Re-converting count_out to mode buffer

So, you could make count_out mode buffer, eliminate the declaration for temp_count and replace temp_count with count_out everywhere else in entity four_bit_counter and it would work. Notice the provided test bench doesn't care what the mode is for count_out because it's not connected to any port signals.

So I did that, renaming count_out to simply count:

library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;

entity four_bit_counter is
    port ( 
        clock:      in      std_logic;
        reset:      in      std_logic;
        pause:      in      std_logic;
        count:      buffer  std_logic_vector (3 downto 0) := "0000";
        student_id: out     std_logic_vector (3 downto 0) 
    ); 
end entity four_bit_counter;

architecture behavioral of four_bit_counter is

    signal slow_clock:      std_logic;
    signal clock_divider:   std_logic_vector(1 downto 0) := "00";
begin

clock_division: 
    process (clock, clock_divider)
    begin
        if clock'event and clock = '1' then
           clock_divider <= clock_divider + 1;
        end if;
        slow_clock <= clock_divider(1);
    end process;

counting: 
    process (reset, slow_clock)
    begin
        if reset = '1' then
            count <= "0000";
        elsif slow_clock'event and slow_clock = '1' and pause = '0' then
            if count < 15 then
                count <= count + 1;
            else
                count <= "0000";
            end if;
        end if;
    end process;

student: 
    process (count)
    begin
        if count = "0010"  then
            student_id <= "0010";
        elsif count = "0011"  then
            student_id <= "0001";
        elsif count = "0100"  then
            student_id <= "0000";
        elsif count = "0101"  then
            student_id <= "0000";
        elsif count = "0110"  then
            student_id <= "1001";
        elsif count = "0111"  then
            student_id <= "0011";
        elsif count = "1000"  then
            student_id <= "0010";
        elsif count = "1001"  then
            student_id <= "0110";
        else 
            student_id <= "1000";
        end if;
    end process;
end architecture behavioral;

And the results are the same. The test bench not having any ports is unaffected. For what ever reason and vendor allowing should your test bench have ports and count was connected, it would have to be mode buffer.

Note that a default value for the renamed count has been added. This is mostly for convenience. The test bench generates a reset after the next falling edge of clock, and the Synopsys package std_logic_unsigned calls std_logic_arith."=" during intial execution of process student.



来源:https://stackoverflow.com/questions/27129747/trying-to-use-a-buffer-in-vhdl-not-working

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!