A simple VHDL circuit won't display initial value

送分小仙女□ 提交于 2021-01-28 06:07:58

问题


Here is my code and it's pretty simple. I'm to cycle through the first 8 letters of the alphabet on a Altera Cyclone II board.

entity lettercycle is
    port(
        SW  : in  std_logic; -- toggle switch
        HEX0 : out std_logic_vector(6 downto 0) -- 7-segment display
        );
end lettercycle;

architecture behavioural of lettercycle is
    signal counter : integer range 0 to 7 := 0;
begin
    process
        type SEGMENT_ARRAY is array (0 to 7) of std_logic_vector(6 downto 0);
        variable SEVENSEG : SEGMENT_ARRAY := ("0001000","0000011","1000110","0100001","0000110","0001110","0010000","0001001");
        begin
        HEX0 <= SEVENSEG(counter);
        wait until SW = '0';
        counter <= counter + 1;
        end process;
end behavioural;

This works great, it cycles but initially it doesn't display "A" on my seven segment display. It displays "8" (so nothing essentially). Once I push SW which is a logic 0 switch it changes to 'A' and cycles to 'B', 'C', etc properly. It also loops correctly. What it isn't doing is initially setting to 'A'. If I force

    HEX0 <= SEVENSEG(0);

Then it will display 'A' initially so I'm out ideas. Could this be related to bouncing?


回答1:


The synthesis tool implements the process with falling edge flip-flops, as a result of the wait until SW = '0';, so both the counter and HEX0 inside the process are updated at falling edge of SW (thus HEX0 is not a latch).

The synthesis tool does however not propagate the initial 0 value of counter to initial value on HEX0 based on mapping through SEVENSEG, so you won't see an initial 'A' on the output.

The synthesis output is shown on the figure below, whereby the flip-flops on the output can also be seen.

enter image description here

The intended operation is possible with update of process and HEX0 assign to:

process (SW) is
begin
  if falling_edge(SW) then
    counter <= counter + 1;
  end if;
end process;
HEX0    <= SEVENSEG(counter);

This will also remove the unnecessary flip-flops on the output for HEX0.

Note the SEVENSEG is moved to architectural level declaration as constant.




回答2:


Morten is right about the falling edge treatment of HEX0.

The alternative is to declare SEVENSEG as a constant in the architecture declarative region and move the assignment from counter (which is a signal) to HEX0 outside of the process:

library ieee;
use ieee.std_logic_1164.all;

entity lettercycle is
    port(
        SW  : in  std_logic; -- toggle switch
        HEX0 : out std_logic_vector(6 downto 0) -- 7-segment display
        );
end lettercycle;

architecture behavioural of lettercycle is
    signal counter : integer range 0 to 7 := 0;
    type SEGMENT_ARRAY is array (0 to 7) of std_logic_vector(6 downto 0);
    constant SEVENSEG : SEGMENT_ARRAY := 
              ("0001000","0000011","1000110","0100001",
               "0000110","0001110","0010000","0001001");
begin
    process
        -- type SEGMENT_ARRAY is array (0 to 7) of std_logic_vector(6 downto 0);
        -- variable SEVENSEG : SEGMENT_ARRAY := 
        --           ("0001000","0000011","1000110","0100001",
        --            "0000110","0001110","0010000","0001001");
        begin
        -- HEX0 <= SEVENSEG(counter);
        wait until SW = '0';
        if counter = 7 then
            counter <= 0;
        else
            counter <= counter + 1;
        end if;
    end process;

    HEX0 <= SEVENSEG(counter);

end behavioural;

library ieee;
use ieee.std_logic_1164.all;

entity lettercycle_tb is
end entity;

architecture foo of lettercycle_tb is
    signal SW:      std_logic := '1';
    signal HEX0:    std_logic_vector(6 downto 0);
begin
DUT:
    entity work.lettercycle
        port map (
            SW => SW,
            HEX0 => HEX0
        );
STIMULUS:
    process 
    begin
        wait for 60 ms;
        SW <= '0';
        wait for 60 ms;
        SW <= '1';
        wait for 60 ms;
        SW <= '0';
        wait for 60 ms;
        SW <= '1';
        wait for 60 ms;
        SW <= '0';
        wait for 60 ms;
        SW <= '1';
        wait for 60 ms;
        SW <= '0';
        wait for 60 ms;
        SW <= '1';
        wait for 60 ms;
        SW <= '0';
        wait for 60 ms;
        SW <= '1';
        wait for 60 ms;
        SW <= '0';
        wait for 60 ms;
        SW <= '1';
        wait for 60 ms;
        SW <= '0';
        wait for 60 ms;
        SW <= '1';
        wait for 60 ms;
        SW <= '0';
        wait for 60 ms;
        SW <= '1';
        wait for 60 ms;
        SW <= '0';
        wait for 60 ms;
        SW <= '1';
        wait for 60 ms;
        wait;
    end process;

end architecture;

And the bit about if counter = 7 then... is because integer "+" has it's mathematical meaning, the output of the add can be out of range and give you a nasty run time message:

ghdl -r lettercycle_tb --wave=lettercycle_tb.ghw
./lettercycle_tb:error: bound check failure at lettercycle.vhdl:29
./lettercycle_tb:error: simulation failed ghdl: compilation error

This says simulation can fail and should encourage the use of std_ulogic based array values for counters and other values undergoing arithmetic operations, which would have counter rollover. A range of 0 to 7 happens to fit exactly within 3 bits and in the synthesized product you'd expect counter to roll over.

There's a description of the verification methodology in the now withdrawn IEEE Std 1076.6 (Register Transfer Level Synthesis):

The process of verifying synthesis results using simulation consists of applying equivalent inputs to both the original model and synthesized model and then comparing their outputs to ensure that they are equivalent. Equivalent in this context means that a synthesis tool shall produce a circuit that is equivalent at the input, output, and bidirectional ports of the model. As synthesis in general does not recognize the same delays as simulators, the outputs cannot be compared at every simulation time. Rather, they can only be compared at specific simulation times when all transient delays have settled and all active timeout clauses have been exceeded. If the outputs do not match at all comparable times, the synthesis tool shall not be compliant. There shall be no matching requirement placed on any internal nodes.

Essentially, the synthesized result is supposed to match what VHDL simulation does other than ignoring meta-value transactions. So you're synthesized result did as much as possible.




回答3:


This isn't a switch bounce issue (although your design is susceptible). In your design HEX0 is a latch. You never set it to an initial value which is why it starts up in a tool assigned initial state of "0000000". Note that this is not an inherent property of VHDL which would start up with "UUUUUUU" (all uninitialized) in simulation but synthesis tools take some liberties when implementing 9-value logic in real hardware.

There is no need for SEVENSEG to be a variable so you can turn it into an architecture level constant and turn the assignment to HEX0 into a continuous assignment outside the process as a simple way to make it start up as desired.



来源:https://stackoverflow.com/questions/23797127/a-simple-vhdl-circuit-wont-display-initial-value

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