问题
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