How to "sample" a value in VHDL? - case

So I have a modulo counter going from 1->15, then looping back around constantly in a seperate entity. I would like to, in a case statement depending on some outputs, sample this value on the rising_edge of a clock, but only do it once, otherwise the value will be constantly changing. Is there a way to do this? Assign the signal and have it stay static?
I've posted some code that I hope will demonstrate what I am trying to say a bit better.
process(all)
begin --sensitivity list?
if(reset) then
playerCards <= "0000000000000000";
dealerCards <= "0000000000000000";
elsif rising_edge(clock) then
case? deal & dealTo & dealToCardSlot is
when "1100" =>
playerCards(3 downto 0) <= singleCard;
playerCards(15 downto 4) <= (others => '0');
when "1101" =>
playerCards(7 downto 4) <= singleCard;
playerCards(15 downto 8) <= (others => '0');
when "1110" =>
playerCards(11 downto 8) <= singleCard;
playerCards(15 downto 12) <= (others => '0');
when "1111" =>
playerCards(15 downto 12) <= singleCard;
when "1000" =>
dealerCards(3 downto 0) <= singleCard; --dcard1
dealerCards( 15 downto 4) <= (others => '0');
when "1001" =>
dealerCards(7 downto 4) <= singleCard; --dcard2
dealerCards( 15 downto 8) <= (others => '0');
when "1010" =>
dealerCards(11 downto 8) <= singleCard; --dcard3
dealerCards( 15 downto 12) <= (others => '0');
when "1011" =>
dealerCards(15 downto 12) <= singleCard; --dcard4
when "0--0" => null; --do nothing when in win/end
when others => --this covers the start case --sets cards to 0
playerCards <= "0000000000000000";
dealerCards <= "0000000000000000";
end case?;
end if;
end process;
Here I have singleCard being linked to the output of my counter, which increments every clock edge. So basically I would like my case statement to only happen update the value of playerCards once, and then stop.
Thanks for any help.

Your requirement can be stated as : the process can be in two states - sampling, or not sampling, and to transition to not sampling when you sample.
So you can do this with a state variable, which in this case can be a boolean - this turns your process into a state machine. As the other answer says, you can use a signal here instead of a variable, but that breaks encapsulation, making the processes internal workings visible.
Some people would insist you separate out the state machine into another two (or even 3) processes, but I think the single process form is a lot smaller and easier to understand.
process(reset,clock) -- original sens list is incorrect for a clocked process
variable sampling : boolean;
begin
if(reset) then
sampling <= true;
-- other reset actions
elsif rising_edge(clock) then
if sampling then -- add conditions here, or it'll sample on the first clock.
sampling := false;
case ... -- sampling process and program logic
end case;
else
-- if you need to turn sampling back on, set "sampling" here
end if;
end if;
end process;

Yes, you need an additional internal signal that will control your operation mode: updating and non-updating.
It would be actually a kind of feedback signal. You generate it depending on the input conditions, and then you also use it on input to modify the behaviour.

Related

How do I rewrite this VHDL code to prevent latches?

architecture Behavioral of REGISTERS is
type REG_FILE_TYPE is array(0 to 15) of STD_LOGIC_VECTOR(15 downto 0);
signal REG_ARRAY : REG_FILE_TYPE:= (others => X"0000");
begin
process(WRITE_ENABLE,REG_CLOCK) is
begin
case (WRITE_ENABLE) is
when '1' => REG_ARRAY(to_integer(unsigned(WRITE_ADDRESS))) <= REG_INPUT;
when '0' => NULL;
when others => NULL;
end case;
end process;
You forgot to add the clock to the process. If there's no clock, and the synthesizer infers that you have a need some memory for the implementation, then it has no other option than to add latches. This is almost always a mistake.
Besides that, I don't like your case structure here, where a simple if-then would do. This is how I'd implement it:
process(REG_CLOCK) is
begin
if rising_edge(REG_CLOCK) then
if WRITE_ENABLE = '0' then
REG_ARRAY(to_integer(unsigned(WRITE_ADDRESS))) <= REG_INPUT;
end if;
end if:
end process;

How to correctly increment the rate at which segments of a display illuminate via button press

I am programming a xilinx basys 3 board in behavioral VHDL. I am illuminating the individual segments of the 4x seven segment display to make it looks as though the display has two rotating "wheels". My overall project consists of many components such as a decoder, mux, debouncer, counter, clock divider for display refresh rate, etc. All of which have been cleared by my prof.
I am currently working on the component that takes in a 250 Hz clk and an up and down button. The up and down buttons will allow for the incrementation of a counter that is mapped to 11 different prescalar values. These values will then vary a clock divider max step accordingly.
Currently my reset button works. However the up and down buttons just pause the rotation of the segments instead of increasing the rate at which they rotate. I believe this component is the issue but I cannot find out where, within the three processes.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.std_logic_unsigned.all;
entity wheelClkDiv is
Port ( btnUp, btnDown, clk, reset : in STD_LOGIC;
--up/down/rst buttons and 250Hz clk initialized as inputs
clkout : out STD_LOGIC
-- newly divided clock initialized as output
);
end wheelClkDiv;
architecture Behavioral of wheelClkDiv is
signal count : STD_LOGIC_VECTOR(19 downto 0) := x"00000"; --20 bit count value for clk divider
signal temp : STD_LOGIC := '0'; --temp store value for clk divider
signal countDiv : STD_LOGIC_VECTOR(19 downto 0) := x"00000"; --value given to choose prescalar
signal btn_counter : STD_LOGIC_VECTOR(3 downto 0) := "0110"; --button press counter
begin
buttonChoose : process(btnUp, btnDown, reset)
begin
if(btnUp = '1') then
btn_counter <= btn_counter + 1; --add one to count if up button pushed
elsif(btnDown = '1') then
btn_counter <= btn_counter - 1; --subtract one from count if down button pushed
elsif(reset = '1') then
btn_counter <="0110"; --set back to middle speed if reset is pushed
end if;
end process;
setDivideCase : process(btn_counter)
begin
case btn_counter is --case statement to choose prescalar based on btn_counter value
when "0000" =>
countDiv <= b"00000000000110010000"; --3.2s cycle
when "0001" =>
countDiv <= b"00000000000100101100"; --2.4s cycle
when "0010" =>
countDiv <= b"00000000000011001000"; --1.6s cycle
when "0011" =>
countDiv <= b"00000000000010010110"; --1.2s cycle
when "0100" =>
countDiv <= b"00000000000001100100"; --0.8s cycle
when "0101" =>
countDiv <= b"00000000000001001011"; --0.6s cycle
when "0110" =>
countDiv <= b"00000000000000110010"; --0.4s cycle
when "0111" =>
countDiv <= b"00000000000000100110"; --0.3s cycle
when "1000" =>
countDiv <= b"00000000000000011001"; --0.2s cycle
when "1001" =>
countDiv <= b"00000000000000010011"; --0.15s cycle
when "1010" =>
countDiv <= b"00000000000000001101"; --0.1s cycle
when others =>
countDiv <= b"00000000000000001101";--not correct
end case;
end process;
wheelDivider : process(clk, reset)
begin
if(reset = '1') then --reset clock count if reset pushed
count <= x"00000";
temp <= '0';
elsif(rising_edge(clk)) then
if(count = countDiv) then --set clk counter value to prescalar
count <= x"00000";
temp <= not temp;
else
count <= count + 1; --keep incrementing clk count until it matches PS
temp <= temp;
end if;
end if;
end process;
clkout <= temp; --give temp value to output clk
end Behavioral;
First thing I see is that you ignore the fact the count signal is constantly counting.
When you hit reset, your count is back at `x"00000", this is the only reason it works.
But when you hit up/down button, you change the countDiv value from e.g.
countDiv <= b"00000000000000110010"; --0.4s cycle
to
countDiv <= b"00000000000000011001"; --0.2s cycle
but what if, in the moment of button click, the count is b"00000000000000100000" ?
The count = countDiv condition did not caught before, and not it will never catch. The count will start to count infinitely, and any further changes of countDiv won't change that fact (maybe will if you hit other button fast enough and expect of reset button of course). The clkout will stop at current value and display will freeze, until of course count overflows.
Of course the easiest resolution would be changing count = countDiv to count >= countDiv, but such comparison is resources consuming, so it is not good way to design fpgas. You should reset count value to zero every time you chage countDiv, or even better, count down to zero, starting at countDiv. Then temporary overflowing current countDiv should not be a problem. You have plenty of possibilities.
For example:
wheelDivider : process(clk, reset)
begin
if(reset = '1') then --reset clock count if reset pushed
count <= b"00000000000001001011";
temp <= '0';
elsif(rising_edge(clk)) then
if(count = x"00000") then --set clk counter value to zero
count <= countDiv;
temp <= not temp;
else
count <= count - 1; --keep decrementing count until zero
temp <= temp;
end if;
end if;
end process;
I am not sure if this is the only problem for now. Hope it is.

VHDL clock generator with different speeds using button

I am new to VHDL and currently working on a clock generator that generates two different clock speeds.
Everything is working, except the switch between the slow and fast speed_status.
There seems to be a problem with the "speed button" because sometimes I have to press it more than once to change the current set speed. The "reset button" is always working as expected. Is there something wrong with my VHDL Code or do I need to add some sort of software debouncing? If so, why is the reset button working?
And could you give me some advice which parts of my clock generator I could improve (code/logic)?
entity clk_gen is
Port ( clk_in : in STD_LOGIC;
clk_btn_in : in STD_LOGIC_VECTOR (3 DOWNTO 0);
clk_out : out STD_LOGIC);
end clk_gen;
architecture Behavioral of clk_gen is
signal temp : STD_LOGIC := '0';
begin
clock: process(clk_in,clk_btn_in)
variable counter : integer range 0 to 49999999 := 0;
constant freq_cnt_slow : integer := 49999999;
constant freq_cnt_fast : integer := 4999999;
type speed is (slow, fast);
variable speed_status : speed := slow;
begin
if rising_edge(clk_in) then
-- RESET BUTTON PRESSED
if (clk_btn_in = "1000") then
temp <= '0';
counter := 0;
speed_status := slow;
-- SPEED BUTTON
elsif (clk_btn_in = "0100") then
if (speed_status = fast) then
speed_status:= slow;
elsif (speed_status = slow) then
speed_status := fast;
end if;
end if;
if ((counter = freq_cnt_fast) and (speed_status = fast)) then
temp <= NOT(temp);
counter := 0;
elsif ((counter = freq_cnt_slow) and (speed_status = slow)) then
temp <= NOT(temp);
counter := 0;
else
counter := counter + 1;
end if;
end if;
end process clock;
clk_out <= temp;
end Behavioral;
I use Xilinx ISE 13.4 and the XC5VLX110T based on Xilinx Virtex 5.
It looks like your speed mode will toggle any time the button is in the 'pressed' state. Unless you can guarantee that your button is only 'pressed' for one clock period, the state is likely to toggle many times, making the state after you pressed the button essentially random (depending on the exact timing of the button press).
Firstly, you need a debouncing circuit on the button. This can be implemented externally, or within the FPGA. I will not go into switch debouncing in detail here, but you can easily find information on this elsewhere. Secondly, you need to convert the button into a synchronous signal, that is, one that has a fixed relationship to your clock. An example synchroniser for your example would be:
signal button_reg1 : std_logic_vector(3 downto 0) := (others => '0');
signal button_reg2 : std_logic_vector(3 downto 0) := (others => '0');
...
process (clk_in)
begin
if (rising_edge(clk_in)) then
button_reg2 <= button_reg1;
button_reg1 <= clk_btn_in;
end if;
end process;
button_reg2 will then have a fixed relationship to the clock.
Without this, you could violate the setup/hold constraints on the speed_status register. Lastly, you need to convert the pressing of the button into a pulse that is one clock period in length. Example:
signal speed_button_reg : std_logic := '0';
signal speed_button_pressed : std_logic := '0';
...
process (clk_in)
begin
if (rising_edge(clk_in)) then
speed_button_reg <= button_reg2(2);
if (speed_button_reg = '0' and button_reg2(2) = '1') then
-- The button has just been pressed (gone from low to high)
-- Do things here, or set another signal e.g.
speed_button_pressed <= '1';
else
speed_button_pressed <= '0';
end if;
end if;
end process;

VHDL RS-232 Receiver

I have been trying to design an RS-232 receiver taking an FSM approach. I will admit that I do not have a very well-rounded understanding of VHDL, so I have been working on the code on the fly and learning as I go. However, I believe I've hit a brick wall at this point.
My issue is that I have two processes in my code, one to trigger the next state and the other to perform the combinational logic. My code is as follows:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity ASyncReceiverV4 is
Port ( DataIn : in STD_LOGIC;
Enable : in STD_LOGIC;
CLK : in STD_LOGIC;
BadData : out STD_LOGIC;
DataOut : out STD_LOGIC_VECTOR (7 downto 0));
end ASyncReceiverV4;
architecture Behavioral of ASyncReceiverV4 is
type states is (StartBitCheck, ReadData, StopBitCheck);
signal currentState, nextState : states;
begin
process(CLK)
begin
if rising_edge(CLK) then
currentState <= nextState;
end if;
end process;
process(CLK)
variable counter : integer := 0;
variable dataIndex : integer := 0;
begin
case currentState is
when StartBitCheck =>
if Enable = '1' then
if (DataIn = '0' and counter < 8) then
counter := counter + 1;
elsif (DataIn = '0' and counter = 8) then
BadData <= '0';
nextState <= ReadData;
counter := 0;
else
nextState <= StartBitCheck;
end if;
end if;
when ReadData =>
if Enable = '1' then
if counter < 16 then
counter := counter + 1;
elsif (counter = 16 and dataIndex < 8) then
DataOut(dataIndex) <= DataIn;
counter := 0;
dataIndex := dataIndex + 1;
elsif dataIndex = 8 then
dataIndex := 0;
nextState <= StopBitCheck;
else
nextState <= ReadData;
end if;
end if;
when StopBitCheck =>
if Enable = '1' then
if DataIn = '1' then
if counter < 16 then
counter := counter + 1;
nextState <= StopBitCheck;
elsif counter = 16 then
counter := 0;
nextState <= StartBitCheck;
end if;
else
DataOut <= "11111111";
BadData <= '1';
nextState <= StartBitCheck;
end if;
end if;
end case;
end process;
end Behavioral;
For whatever reason, based on my simulations, it seems that my processes are out of sync. Although things are only supposed to occur at the rising edge of the clock, I have transitions occurring at the falling edge. Furthermore, it seems like things are not changing according to the value of counter.
The Enable input is high in all of my simulations. However, this is just to keep it simple for now, it will eventually be fed the output of a 153,600 Baud generator (the Baud generator will be connected to the Enable input). Hence, I only want things to change when my Baud generator is high. Otherwise, do nothing. Am I taking the right approach for that with my code?
I can supply a screenshot of my simulation if that would be helpful. I am also not sure if I am including the correct variables in my process sensitivity list. Also, am I taking the right approach with my counter and dataIndex variables? What if I made them signals as part of my architecture before any of my processes?
Any help on this would be very much so appreciated!
The easiest way to fix this, while also producing the easiest to read code, would be to move to a 1-process state machine like so (warning: not complied may contain syntax errors):
entity ASyncReceiverV4 is
Port ( DataIn : in STD_LOGIC;
Enable : in STD_LOGIC;
CLK : in STD_LOGIC;
BadData : out STD_LOGIC;
DataOut : out STD_LOGIC_VECTOR (7 downto 0));
end ASyncReceiverV4;
architecture Behavioral of ASyncReceiverV4 is
type states is (StartBitCheck, ReadData, StopBitCheck);
signal state : states := StartBitCheck;
signal counter : integer := 0;
signal dataIndex : integer := 0;
begin
process(CLK)
begin
if rising_edge(CLK) then
case state is
when StartBitCheck =>
if Enable = '1' then
if (DataIn = '0' and counter < 8) then
counter <= counter + 1;
elsif (DataIn = '0' and counter = 8) then
BadData <= '0';
state <= ReadData;
counter <= 0;
end if;
end if;
when ReadData =>
if Enable = '1' then
if counter < 16 then
counter <= counter + 1;
elsif (counter = 16 and dataIndex < 8) then
DataOut(dataIndex) <= DataIn;
counter <= 0;
dataIndex <= dataIndex + 1;
elsif dataIndex = 8 then
dataIndex <= 0;
state <= StopBitCheck;
end if;
end if;
when StopBitCheck =>
if Enable = '1' then
if DataIn = '1' then
if counter < 16 then
counter <= counter + 1;
elsif counter = 16 then
counter <= 0;
state <= StartBitCheck;
end if;
else
DataOut <= "11111111";
BadData <= '1';
state <= StartBitCheck;
end if;
end if;
end case;
end if;
end process;
end Behavioral;
Note that while this no longer contains language issues, there are still odd things in the logic.
You cannot enter the state StopBitCheck until counter is 16 because the state transition is in an elsif of counter < 16. Therefore, the if counter < 16 in StopBitCheck is unreachable.
Also note that the state transition to StopBitCheck happens on the same cycle that you would normally sample data, so the sampling of DataIn within StopBitCheck will be a cycle late. Worse, were you ever to get bad data (DataIn/='1' in StopBitCheck), counter would still be at 16, StartBitCheck would always go to the else clause, and the state machine would lock up.
Some more explanation on what was wrong before:
Your simulation has things changing on the negative clock edge because your combinatorial process only has the clock on the sensitivity list. The correct sensitivity list for the combinatorial process would include only DataIn, Enable, currentState, and your two variables, counter and dataIndex. Variables can't be a part of your sensitivity list because they are out of scope for the sensitivity list (also you do not want to trigger your process off of itself, more on that in a moment).
The sensitivity list is, however, mostly just a crutch for simulators. When translated to real hardware, processes are implemented in LUTs and Flip Flops. Your current implementation will never synthesize because you incorporate feedback (signals or variables that get assigned a new value as a function of their old value) in unclocked logic, producing a combinatorial loop.
counter and dataIndex are part of your state data. The state machine is simpler to understand because they are split off from the explicit state, but they are still part of the state data. When you make a two process state machine (again, I recommend 1 process state machines, not 2) you must split all state data into Flip Flops used to store it (such as currentState) and the output of the LUT that generates the next value (such as nextState). This means that for your two process machine, the variables counter and dataIndex must instead become currentCounter, nextCounter, currentDataIndex, and nextDataIndex and treated like your state assignment. Note that if you choose to implement changes to keep a 2-process state machine, the logic errors mentioned above the line will still apply.
EDIT:
Yes, resetting the counter back to 0 before moving into StopBitCheck might be a good idea, but you also need to consider that you are waiting the full 16 counts after sampling the last data bit before you even transition into StopBitCheck. It is only because counter is not reset that the sample is only off by one clock instead of 16. You may want to modify your ReadData action to transition to StopBitCheck as you sample the last bit when dataIndex=7 (as well as reset counter to 0) like so:
elsif (counter = 16) then
DataOut(dataIndex) <= DataIn;
counter <= 0;
if (dataIndex < 7) then
dataIndex <= dataIndex + 1;
else
dataIndex <= 0;
state <= StopBitCheck;
end if;
end if;
A pure state machine only stores a state. It generates its output purely from the state, or from a combination of the state and the inputs. Because counter and dataIndex are stored, they are part of the state. If you wanted to enumerate every single state you would have something like:
type states is (StartBitCheck_Counter0, StartBitCheck_counter1...
and you would end up with 8*16*3 = 384 states (actually somewhat less because only ReadData uses dataIndex, so some of the 384 are wholly redundant states). As you can no doubt see, it is much simpler to just declare 3 separate signals since the different parts of the state data are used differently. In a two process state machine, people often forget that the signal actually named state isn't the only state data that needs to be stored in the clocked process.
In a 1-process machine, of course, this isn't an issue because everything that is assigned is by necessity stored in flip flops (the intermediary combinational logic isn't enumerated in signals). Also, do note that 1-process state machines and 2-process state machines will synthesize to the same thing (assuming they were both implemented correctly), although I'm of the opinion that is comparatively easier to read and more difficult to mess up a 1-process machine.
I also removed the else clauses that maintained the current state assignment in the 1-process example I provided; they are important when assigning a combinational nextState, but the clocked signal state will keep its old value whenever it isn't given a new assignment without inferring a latch.
First Process runs just on CLK rising edge, while the second one runs on both CLK edge (because runs on every CLK change).
You use 2 process, “memory-state” and “next-state builder”, the first must be synchronous (as you done) and the second, normally, is combinatorial to be able to produce next-state in time for next CLK active edge.
But in your case the second process needs also to run on every CLK pulse (because of variable counter and index), so the solution can be to run the first on rising-edge and the second on falling-edge (if your hardware support this).
Here is your code a little bit revisited, I hope can be useful.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity ASyncReceiverV4 is
Port ( DataIn : in STD_LOGIC;
Enable : in STD_LOGIC;
CLK : in STD_LOGIC;
BadData : out STD_LOGIC := '0';
DataOut : out STD_LOGIC_VECTOR (7 downto 0) := "00000000");
end ASyncReceiverV4;
architecture Behavioral of ASyncReceiverV4 is
type states is (StartBitCheck, ReadData, StopBitCheck);
signal currentState : states := StartBitCheck;
signal nextState : states := StartBitCheck;
begin
process(CLK)
begin
if rising_edge(CLK) then
currentState <= nextState;
end if;
end process;
process(CLK)
variable counter : integer := 0;
variable dataIndex : integer := 0;
begin
if falling_edge(CLK) then
case currentState is
when StartBitCheck =>
if Enable = '1' then
if (DataIn = '0' and counter < 8) then
counter := counter + 1;
elsif (DataIn = '0' and counter = 8) then
BadData <= '0';
nextState <= ReadData;
counter := 0;
else
nextState <= StartBitCheck;
end if;
end if;
when ReadData =>
if Enable = '1' then
if counter < 15 then
counter := counter + 1;
elsif (counter = 15 and dataIndex < 8) then
DataOut(dataIndex) <= DataIn;
counter := 0;
dataIndex := dataIndex + 1;
elsif dataIndex = 8 then
dataIndex := 0;
nextState <= StopBitCheck;
else
nextState <= ReadData;
end if;
end if;
when StopBitCheck =>
if Enable = '1' then
if DataIn = '1' then
if counter < 15 then
counter := counter + 1;
nextState <= StopBitCheck;
elsif counter = 15 then
counter := 0;
nextState <= StartBitCheck;
end if;
else
DataOut <= "11111111";
BadData <= '1';
nextState <= StartBitCheck;
end if;
end if;
end case;
end if;
end process;
end Behavioral;
This is a 0x55 with wrong stop bit receive data simulation

VHDL Value in case statement randomly gets stuck at a certain value

I've recently been working on some code trying to make a vending machine in vhdl. Started getting some strange errors and managed to narrow it down to my display value being updated.
The code is basically suppose to be able to toggle between display formats for a 7-segment display. I'd say it works as it should mostly but seemed to freeze randomly
I altered to code,found below, a little for debugging and noticed that the values within the case statement get stuck at a certain value. The rest of the code continuous to run perfectly so I can reset and it will work again. Below is the code with the problem
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity display_switch is
Port ( clk : in STD_LOGIC;
reset: in STD_LOGIC;
number : in STD_LOGIC_VECTOR (13 downto 0);-- unsigned binary number
hexid : in std_logic_vector(15 downto 0); -- hex representation
sel : in std_logic;
an : out std_logic_vector(3 downto 0);
seg : out STD_LOGIC_VECTOR (6 downto 0); -- 7 segment display
dp,Led,Led1,Led2 : out std_logic);
end display_switch;
architecture bhv of display_switch is
type button_state is(dec,hex,deb); -- states for display formats
signal current_display,next_display : button_state;
process(clk, reset)
begin
if reset = '1' then -- asynchronous reset
current_display <= dec;
next_display <= hex;
decp <= '1'; -- decimal point
elsif rising_edge(clk) then
segm_display <= hexid;
case current_display is
when dec => Led2 <= '1';
Led1 <= '0';
Led <= '0';
decp <= '0';
next_display <= hex;
if sel = '1' then
current_display <= deb;
end if;
when hex => Led2 <= '0';
Led1 <= '1';
Led <= '0';
decp <= '1';
next_display <= dec;
if sel = '1' then
current_display <= deb;
end if;
when deb => Led2 <= '0';
Led1 <= '0';
Led <= '1';
if sel /= '1' then
current_display <= next_display;
end if;
when others => current_display <= dec;
end case;
end if;
end process;
end bhv;
Basically what happens is that the output values in the case statements either all get stuck at '1' or all get stuck at '0'.
Thanks
Your computation for the next states is dubious. If you are using a synchronous process (as you are indeed doing), you do not need a next_display signal. Just assign the next state value to current_display instead.
I found the problem. It was a timing issue with the "sel" input variabel.
added a signal to store the value on rising clock edge.
temp <= sel;
then used that temp variable instead.

Resources