if(rising_edge(clk)) then
count := count + 1;
if count = 3 then
enable <= 1;
elsif count = 6 then
enable <= 0;
count := 0;
end if;
end if;
if enable = 0 then
a0i <= a_0;
boi <= b_0;
end if;
if enable = 1 then
a0i <= a_1;
boi <= b_1;
end if;
All are signals except the count. Value of a0i and boi should response as soon as enable becomes either 0 or 1. I tried using the variable. but it can not allow me to use out side the process.
I am getting the o/p as this. How ever I want to change the input as soon as enable signal change.
Put the last two if conditions in another process
Process(enable, a_0, b_0, a_1, b_1)
begin
If(enable = '0')THEN
a0i <= ...
....
ELSE
.....
END IF;
END PROCESS;
This process is sensitive to the enable signal so anytime there is a change in enable, independent of the clock, the statements will take effect immediately (asynchronously)
Solution 1: use 2 processes as blueprint mentioned.
Solution 2: use an internal variable.
process(clk)
variable count : natural range of 0 to 6 := 0;
variable enable_i : std_logic := '0';
begin
if(rising_edge(clk)) then
count := count + 1;
if count = 3 then
enable_i := '1';
elsif count = 6 then
enable_i := '0';
count := 0;
end if;
end if;
if enable = '0' then
a0i <= a_0;
boi <= b_0;
else
a0i <= a_1;
boi <= b_1;
end if;
enable <= enable_i;
end process;
Some hints:
Maybee, the type boolean is more suitable for your signal/variable enable_i
If enable_i is only used inside the process, then you can remove the conversion to enable
including the data path and multiplexers in a state machine (I assume this is a part of it) is not a good design choice.
You could also take these two equation below out from your process.
process(...)
[...]
if enable = 0 then
a0i <= a_0;
boi <= b_0;
end if;
if enable = 1 then
a0i <= a_1;
boi <= b_1;
end if;
end process
Then you cannot use the IF statement anymore, but you can use the WHEN statement :
a0i <= a_0 when enable = '0' else a_1;
boi <= b_0 when enable = '0' else b_1;
Note that in this case, the multiplexer will be after the latch. This could be important if you have timing issues on these signals.
From your simulation waveform, it looks to me like you failed to include enable, a_0, b_0, a_1, and b_1 in your sensitivity list, but I can't be sure because you didn't post the complete example. Because you test the values of the 5 mentioned signals outside of the if rising_edge(clk), they need to be included. The values are only updated on the falling edge of clk because, presuming that clk is the only thing in your sensitivity list, that is the next time the process is evaluated.
It should be otherwise functional as written, although you could use an else instead of a separate test for enable = 0 for a slight readability improvement. Synthesis usually ignores the sensitivity list (it just makes simulation more efficient) so it should already work if you were to synthesize.
Related
I am making a MultiLevel Car Parking system module with consist of common entry and exit, The idea is that, when I get input stimulus from signal car entry or car exit, It will check the car's Type and then the output should display the level reserved for the particular type where, the car should go, If the slots reserves for particular type is full then the display should output as such. The code gets stimulated through the output gets displayed only after the next clock cycle after the input stimulus is given.
I have tried using a different if-else block for counting operations and also with different process using a flag, and tried to change it to different if-else blocks, but it's still the same. I am beginner to vhdl the execution of statements is quite confusing, and online search is of little help, please help me where did I go wrong?
library ieee;
use ieee.std_logic_1164.all;
use ieee.Numeric_std.all;
use work.Parking_Package.all;
entity CarPark is
port( clk :in std_logic;
rst : in std_logic;
car_in : in std_logic;
Car_out : in std_logic;
Ent_car_type : car_type;
Ext_car_type : car_type;
Status : out level
);
end CarPark;
architecture behave of CarPark is
signal count : counter;
begin
SLOT_CHECKING: process(rst,clk)
begin
if(rst= '1')then
count <= (others => 0);
Status <= FULL;
elsif(rising_edge(clk))then
if(car_in )then
case(Ent_car_type)is
when Admin =>
if(count(Admin) < 5) then
Status <= L1;
count(Admin) <= count(Admin) +1;
else
Status <= FULL;
end if;
when Staff =>
if(count(Staff) < 5) then
Status <= L2;
count(Staff) <= count(Staff) + 1;
else
Status <= FULL;
end case;
end if;
elsif(car_out)then
case(Ext_car_type)is
when Admin =>
if(count(Admin) >0) then
Status <= L1a;
count(Admin) <= count(Admin) - 1;
else
count(Admin)<= 0;
end if;
when Staff =>
if(count(Staff) >0) then
Status <= L2a;
count(Staff) <= count(Staff) - 1;
else
count(Staff) <= 0;
end if;
end process;
end behave;
The user defined packages is given below
library ieee;
use ieee.std_logic_1164.all;
use ieee.Numeric_std.all;
package Parking_Package is
type car_type is (Admin, Staff);
type level is (L1, L2a, FULL);
type counter is array (Staff downto Admin) of integer range 0 to 22;
end Parking_Package;
package body Parking_Package is
end Parking_Package;
After initializing using reset, I give input of car_in as 1 and
car_type as Admin, The output gets displayed as L1 in the Next Clock
and if I force the value of car_type as staff, The corresponding output is simulated in the next clock cycle.
![ScreenShot Simulation] https://imgur.com/a/B6cqADn
Firstly, some comments :
Your application (MultiLevel Car Parking) is not very adapted to VHDL language. It's too high level. Your coding style is a bit object oriented (type and variable names).
There are syntax errors in your code (I assume you already know it because You achieve to have a simulation screen).
The behavior that you expect on the first clock cycle implies that your output will be the product of combinational logic. It's better to have outputs directly from flip flops.
Then the code that you can use to have the expected behavior with 2 process (One purely sequential, the other purely combinational) :
signal current_count : counter;
signal next_count : counter;
signal current_status : level;
signal next_status : level;
begin
SEQ : process(rst_tb, clk_tb)
begin
if (rst_tb = '1') then
current_count <= (others => 0);
current_status <= FULL;
elsif (rising_edge(clk_tb)) then
current_count <= next_count;
current_status <= next_status;
end if;
end process;
SLOT_CHECKING : process(current_count, current_status, car_in, car_out, Ent_car_type, Ext_car_type)
begin
next_count <= current_count;
next_status <= current_status;
if (car_in = '1') then
case (Ent_car_type) is
when Admin =>
if (current_count(Admin) < 5) then
next_status <= L1;
next_count(Admin) <= current_count(Admin) + 1;
else
next_status <= FULL;
end if;
when Staff =>
if (current_count(Staff) < 5) then
next_status <= L2;
next_count(Staff) <= current_count(Staff) + 1;
else
next_status <= FULL;
end if;
end case;
elsif (car_out = '1') then
case (Ext_car_type) is
when Admin =>
if (current_count(Admin) > 0) thenremarques
next_status <= L1a;
next_count(Admin) <= current_count(Admin) - 1;
else
next_count(Admin) <= 0;
end if;
when Staff =>
if (current_count(Staff) > 0) then
next_status <= L2a;
next_count(Staff) <= current_count(Staff) - 1;
else
next_count(Staff) <= 0;
end if;
end case;
end if;
end process;
count <= next_count ;
Status <= next_status ;
Warning, with this code the outputs are directly from combinational logic : It's not recommended but it is the only way to get the behavior you expect.
If this application is only a practise, I advice you too to take another example more adapted to VHDL : filter, SPI communication, processing unit, ...
I am trying to interface the output of my FPGA onto a DAC. I am using the PmodDA2 DAC. The trouble I am having is working out how to output the data from a 16bit register into 1 bit per clock cycle.
I have studied the timing diagram and understand that CS needs to send a pulse before data transmission begins.
I have tried using the necessary resets and other features as applicable within my design as a whole.
I tried implementing a count to cycle between 0 to 16/17 and when it was at the beginning it would set CS to high and begin transmission. However I did not believe this would be at all the correct way to do it.
architecture Behavioral of DAC is
signal count : integer range 0 to 15;
signal selected : std_logic;
signal data_storage : std_logic_vector(15 downto 0);
begin
process(D_DAC, CE_DAC, RES_DAC, RES_DAC, data_storage)
begin
if RES_DAC = '1' then
data_storage <= "0000000000000000";
end if;
if rising_edge(CLK_DAC) then
if CE_DAC = '1' then
data_storage <= D_DAC;
end if;
end if;
end if;
end process ;
CS_DAC <= CE_DAC;
SCLK_DAC <= CLK_DAC;
DATA1_DAC <= data_storage;
end Behavioral;
I'm getting myself very confused over this.
I'd appreciate any help.
************************EDIT************************
I have had another go at implementing the counter...
process(D_DAC, CE_DAC, CLK_DAC, RES_DAC, data_storage)
begin
if RES_DAC = '1' then
data_storage <= "0000000000000000";
cound <= 0;
selected <= '0';
elsif rising_edge(CLK_DAC) then
if CE_DAC = '1' then
if count = 0 then
selected <= '1';
end if;
if selected = 1 then
if count = 15 then
count <= 0;
selected <= '0';
else
count <= count + 1;
data_storage <= D_DAC;
end if;
end if;
end if;
end if;
end process ;
CS_DAC <= CE_DAC;
SCLK_DAC <= CLK_DAC;
DATA1_DAC <= data_storage;
end Behavioral;
I am writing a specified UART component in VHDL.
send: process(send_start)
variable bit_index : integer range 0 to 2 := 0;
begin
if (falling_edge(send_start)) then
if (start = '0' and transceiver_start = '1') then
bit_index := 0;
end if;
transceiver_start <= '1';
if (bit_index = 0) then
temp_data <= data.RE;
bit_index := 1;
transceiver_start <= '0';
delay_counter <= 0;
elsif (bit_index = 1) then
temp_data <= data.IM;
bit_index := 2;
transceiver_start <= '0';
end if;
end if;
end process;
The falling edge of the transceiver_start signal triggers the sub-component to run. I wanted to trigger it twice, but I do not know how to generate a second falling edge.
I thought about using a concurrent process, which would basically reset the transceiver_start signal to it's hi-state after delay_counter reaches some limit. Therefore I could bring it down inside the send process again to generate a falling edge. However, this makes me have two driving processes for the delay_counter signal, and I read that having resolution functions is not a good practice for synthesis (this code needs to be synthesizable.)
Is there any way for me to generate that falling edge when bit_index = 1?
FPGA devices and related synthesis tools are optimized for synchronous logic,
thus VHDL where a clock triggers process execution. Using a specific signal to
trigger process execution, as in the question code, is thus not in line with
the indented FPGA and VHDL design methodology.
Instead, use an internal clock to trigger process execution, usually the rising
edge of the clock. Actual update inside the process can then be conditional on
detection of change to a control signal, which can be send_start.
process (clock) is
begin
if rising_edge(clock) then
send_start_prev <= send_start; -- Previous for edge detection
if ((send_start = '0') and (send_start_prev = '1')) then -- Falling edge of send_start
... -- More code
end if;
end if;
end process;
For rerunning of conditional process code, for example based on bit_index = 1, the process contents can be updated like:
send_start_prev <= send_start; -- Previous for edge detection
rerun_request <= '0'; -- Default no rerun
if ((send_start = '0') and (send_start_prev = '1')) or -- Falling edge of send_start
(rerun_request = '1') then -- Rerun request
if bit_index = 1 then
rerun_request <= '1';
end if;
... -- More code
end if;
I am aware that inferred latches occur when not every possible path is defined, but I have made considerations to avoid this in my process:
The signal is:
signal BothButtons : std_logic_vector (1 downto 0) ;
The process is:
Signaling : process(button0, button1)
begin
if (button0= '0') AND (button1 = '0') then
BothButtons <= "00";
elsif (button0= '0') AND (button1 = '1') then
BothButtons <= "01";
elsif (button0= '1') AND (button1 = '0') then
BothButtons <= "10";
elsif (button0= '1') AND (button1 = '1') then
BothButtons <= "11";
end if;
end process;
This is driving me crazy, any help is appreciated, maybe I lack an understanding of something really simple!
The error is:
Warning (10631): VHDL Process Statement warning at swDisplay.vhd(28): inferring latch(es) for signal or variable "BothButtons", which holds its previous value in one or more paths through the process
As far as I am aware I am not assigning to the signal two values at the same time, rather it is in receiving values in different situations?
this time I am using that previous signal to drive the output of another process but another latch is appearing within it, this time I did take into account any other value and place an "else" statement to take care of that but no luck:
Counting : process(BothButtons)
variable count0 : integer range 0 to 9; -- to hold the counter value
begin
if BothButtons = "00" then
count0 := 0;
elsif BothButtons = "01" then
count0 := count0 + 1;
elsif BothButtons = "10" then
count0 := count0;
elsif BothButtons = "11" then
count0 := count0;
else
count0 := 0;
end if;
For those of you who are wondering, yes this is part of an academic exercise!
What happens if button0 is neither '0' nor '1'? There's your latch. (ditto button1) Even 'H' and 'L' will confuse it, even though these have a clear meaning to you or me...
Now what do you need that BothButtons <= button0 & button1; doesn't do? (I may have misunderstood the problem you are having)
You have latches because you have a process with memory without a clock.
In the first example you give you just need an else in the end of the if-case. Otherwise it is forced to use a previous value, which requires that it has some memory of this previous value. Memory requires latches or flip-flops - and without a clock it is forced to use latches.
In the second example the lines count0 := count0 + 1; and count0 := count0; uses the value from a previous iteration of the process. This requires memory. And memory without a clock gives you latches.
I am trying to send multiple bytes on the SPI bus during the transmit window. Initially I am acquiring data from the flash ADC when the input pulse is high, then calculating its average and transmitting each average value sequentially on the SPI bus. I got the SPI vhdl module working, it was able to send data when I tried sending a single byte, but when I try to send more than 1 byte it just does not work. There is logic 0 on the MOSI line and the SS line is constantly high. This is the part where I try to send multiple bytes.
process(SPITrig, Clock, TX_Done, data_count, average2A_s, average2B_s)
begin
case data_count is
when 1 =>
TX_Data <= average2A_s;
when 2 =>
TX_Data <= average2B_s;
when others => TX_Data <= "0101010101010101";
end case;
end process;
process(SPIBusy, SPITrig, SPI_Clock_base, data_count, TX_Start)
begin
if falling_edge(SPITrig) then
SPIBusy <= '1';
TX_Start <= '0';
data_count <= 0;
delay_counter <= 0;
end if;
if rising_edge(SPI_Clock_base) and SPIBusy = '1' then
if data_count < 3 then
if delay_counter = 128 then
TX_Start <= not TX_Start;
delay_counter <= 0;
elsif delay_counter < 128 then
delay_counter <= delay_counter + 1;
end if;
elsif data_count >= 3 then
TX_Start <= '0';
delay_counter <= 0;
SPIBusy <= '0';
end if;
end if;
if rising_edge(TX_Start) then
data_count <= data_count + 1;
end if;
end process;
It works perfectly well in simulation, but theres no output on the hardware. Need your help in finding out whats wrong.
PS: This is my first FPGA project, so my code may not be so efficient.
I have also attached the ISIM screenshot.
clickable
tx = TX Done pin
trig = TX Start ping
c1 = data count
Note: SPI transmission sequence starts when average outputs are available and it is triggered using an internal signal"SPITRig".
Take a look at the synthesis and timing (STA) warnings, since these will indicate if the synthesis tool could not implement the design to match the RTL VHDL code.
The edge condition by rising_edge(...) or falling_edge(...) should only be used on a single common clock signal, unless there is a good reason for use of multiple clock signals; and usually only rising_edge(...) is used.
In your design you have three different signal SPITrig, SPI_Clock_base, and TX_Start that work like clocks, and this is likely to give a timing violation.
As example, in the first if of the large process, the TX_Start and data_count are both updated on the falling_edge(SPITrig), and in the last if the rising_edge(TX_Start) is used to update data_count again based on current data_count value. This may work fine in simulation, but in HW you have signal propagation delay, which depends on routing and other factors that may wary for different signals, so a design construction like that is likely to give problems in implementation.
If you have a full Static Timing Analysis (STA) setup for your design, which you probably don't have for a first time FPGA project, then the STA tool will report if the timing can be meet, and a construction like the above is likely to not meet timing.
So instead, rewrite your design to use only a single clock edge, for example rising_edge(SPI_Clock_base). It is also much easier to make a correct STA timing setup for such a design, and the sensitivity list of the processes should then only contain the clock and any asynchronous reset signals, if used, like:
process (SPI_Clock_base) is
begin
if rising_edge(SPI_Clock_base) then
...
end if;
end process;
Finally, the sensitivity list of the initial process should be reduced to only contain the signals that are read in the process, since the process need only to be sensitive to the these signals. The design won't fail if more signals are included, it makes the reader wonder what is wrong; the sensitivity list or the code.
As suggested by Morten Zilmer, I made the necessary changes to synchronize everything with the Clock. following is the code and it is working. Might post a screenshot from an oscilloscope later.
process(SPITrig, data_count, average2A_s, average2B_s)
begin
case data_count is
when 1 =>
TX_Data <= average2A_s;
when 2 =>
TX_Data <= average2B_s;
when others => TX_Data <= x"0000";
end case;
end process;
SPICycler : process(delay_counter, data_count, SPITrig, SPI_Clock_base, SPIBusy)
begin
if rising_edge(SPI_Clock_base) and SPIBusy = '1' then
if delay_counter < 511 then
delay_counter <= delay_counter + 1;
TX_Start <= '0';
else
delay_counter <= 0;
TX_Start <= '1';
data_count <= data_count + 1;
end if;
end if;
if rising_edge(SPI_Clock_base) then
if SPITrig = '1' then
SPIBusy <= '1';
data_count <= 0;
end if;
if data_count = 3 then
SPIBusy <= '0';
end if;
end if;
end process;