VHDL State machie is skipping state - vhdl

I have written FSM on a FPGA, when I run simulation using iSim everything looks good, problem starts when I run my program on board(I'm using Spartan SP605 Eval Kit), and after looking up on signals using chipscope, I discovered that it skips state when the ADV signal should be low (see code below) and it just follows thru that state to the next one on witch it is stuck.
I've check and I do not violate any of my timing requirement.
A little bit of my project:
I'm using Cypres board to receive and sent data to/from PC,hardware there works as it should be. This board is connected to FPGA via FMC interconnection board (also from Cypress). This board contains two buffers (FIFO; one for transfer to FPGA and one to transfer from FPGA), FPGA sees flags that indicates state of those buffers (flag A - full, B - partial full, C - empty, D - partial empty). FPGA is configured as loopback, it first reads all data from board, then transfer those data to it.
flags are active low.
I tried to force it to run without those if's (every clock cycle is new state), and it worked as expected (I got error from board that says it tries to read from empty buffer)
here is fragment of my State machie code, the state it skips is named ADDRRead.
If you are intrested in full code I posted it on pastebin https://pastebin.pl/view/ae9b57ce
process(currentFPGAMode, writeEnable, chipEnable, outputEnable, rdy, flagA, flagb, flagD, flagC, readEmptyDelayCnt, writeFullDelayCnt)
begin
case currentFPGAMode is
when Idle =>
if (flagc = '1') --check if buffer is avaible
then
nextFPGAMode <= waitFlagD;
else
nextFPGAMode <= Idle;
end if;
when waitFlagD =>
--wait for data to appear in buffer (from PC)
if (flagD = '1')
then
nextFPGAMode <= ADDRRead;
else
nextFPGAMode <= waitFlagD;
end if;
when ADDRRead =>
--setting up address bus to point on endpoint for read transfer
nextFPGAMode <= OeDelay;
when OeDelay =>
--waiting for valid data
if (rdy = '1')
then
nextFPGAMode <= FPGARead;
else
nextFPGAMode <= OeDelay;
end if;
when FPGARead =>
--valid data data are avaible here
if (flagD = '1') --check if there are data to be read
then
nextFPGAMode <= FPGARead;
else
nextFPGAMode <= ReadEndDelay;
end if;
when ReadEndDelay =>
if (readEmptyDelayCnt = 0)
then
nextFPGAMode <= FPGAReadEnd;
else
nextFPGAMode <= ReadEndDelay;
end if;
when FPGAReadEnd =>
--end read sequence
nextFPGAMode <= waitFlagA;
when waitFlagA =>
--checking if DMA Buffer is empty
if (flagA = '1')
then
nextFPGAMode <= ADDRWrite;
else
nextFPGAMode <= waitFlaga;
end if;
when ADDRWrite =>
--seting address bus to point at endpoint for writetransfer (address line = 3)
nextFPGAMode <= WeDelay;
when WeDelay =>
--waiting for valid data to apear
if (rdy = '1')
then
nextFPGAMode <= FPGAWrite;
else
nextFPGAMode <= WeDelay;
end if;
when FPGAWrite =>
--data are avaible to apear
if ( flagb = '0')
then
nextFPGAMode <= WriteEndDelay;
else
nextFPGAMode <= FPGAWrite;
end if;
when WriteEndDelay =>
if (writeFullDelayCnt = 0)
then
nextFPGAMode <= RDYDelay;
else
nextFPGAMode <= WriteEndDelay;
end if;
when RDYDelay =>
--Delay for rdy signal to deassert after finishing transfer
if (rdy = '0')
then
nextFPGAMode <= Idle;
else
nextFPGAMode <= RDYDelay;
end if;
when others =>
nextFPGAMode <= Idle;
end case;
end process;

Related

How to solve latch warning?

I have a question about VHDL. The following code is for a player turn selector in a game. It simulates well, but when I generate a bit stream it has a warning that says:
"[Synthesizer 8-327] infer latch for variable 'teToca_reg' [" C: /...../ Eleccion.vhd ": 137]"
The main problem is generated by an assignment made in a process, which I need in order for the "cambio" signal to receive the first value of the turn in that game, and to be able to change after each time B1 is pressed. The problem appears because the assignment is done later combinationally in the opposite direction so that the output "teToca" takes the changed value.
The signal "FinPartida" is set to 1 when a game ends and "win" gives a value, so "teToca" receives a new value.
proceso_switch: process(clk,reset)
begin
if reset = '1' then
cambia <= '0';
elsif clk'event and clk='1' then
if FinPartida='1' then
cambia <= tetoca; --LATCH
elsif state = S_JUEGO and flanco='1' and B1='1' and posicion/=9 and pos1(posicion)='0' and pos2(posicion)='0' then
cambia <= NOT cambia; --OK
end if;
end if;
end process;
teToca <= empieza when state = S_ESPERA and reset = '0' else
'0' when state = S_ESPERA and reset = '1' else
--PLATCH--
cambia when state = S_JUEGO AND (flanco='1' and B1='1' and posicion/=9 and pos1(posicion)='0' and pos2(posicion)='0') else
--LATCH--
'0' when state = S_JUEGO AND win="001" else
'1' when state = S_JUEGO AND win="100";
turno <= teToca;

VHDL: having multiple clock enables in one process

Hello I am new to VHDL and I want to ask if it is ok to have a process like this
where I have multiple clocks in one process
C256Hz and C4Hz are clock enables driven from the 50MHz clock
process (Reset, C50Mhz, Go, start_flag, C256Hz, C4Hz)
begin
if reset = '1' then
start_flag <= '0';
elsif rising_edge (C50Mhz) then
if C4Hz = '1' then
if count4 = "11" and single_run_flag = '0' then
start_flag <= '0';
end if;
end if;
if C256Hz = '1' then
if Go = '1' and start_flag = '0' then
start_flag <= '1';
end if;
end if;
end if;
end process; `
It is okay, but whether synthesis will generate a good result depends on the fabric.
The sensitivity list should have just reset and C50MHz, because these are the only events that actually change signals. When C4Hz toggles, then rising_edge(C50MHz) is false, because these are not synchronized, and nothing would happen if the process were to run then.
The separate enable can be assumed to be available everywhere -- clock fanout is so high that everyone implements separate clock distribution networks, and the enable on the registers is required then. So this is safe to use.
The asynchronous reset might not be available on all fabrics, but usually is. Some devices will support asynchronous load (i.e. you can decide the value to be taken on reset), others only reset (i.e. you can set the register to zero only, and initializing to one would generate an inverted table, a register with reset-to-zero, and an inverter in the next LE.
So in general, this is fairly safe, this can be synthesized as
-- intermediates
do_clear_start_flag := C4Hz = '1' and count4 = "11" and single_run_flag = '0';
do_set_start_flag := C256Hz = '1' and Go = '1' and start_flag = '0';
-- to register
enable_start_flag := do_clear_start_flag or do_set_start_flag;
new_start_flag := do_set_start_flag;
The check for the old value of start_flag in do_set_start_flag cannot be optimized out even if setting start_flag has no effect if it has been set before, because it might just be reset in the current clock cycle.
If the block beginning with if C256Hz = '1' were an elsif instead, the second intermediate would read
do_set_start_flag := C256Hz = '1' and Go = '1' and do_clear_start_flag = '0'

VHDL - making the logic synthesizable

I'm designing a relatively simple memory arbiter, with two states.
State 1: Port 1 is connected to the memory (default state)
State 2: Port 2 is connected to the memory (only if there are requests)
The simulation in ModelSim works just fine and proves that my arbiter operates as required. However I was told that code I've written is not synthesizable. I've included the relevant process' code below.
The enable signal goes high upon request, and setting the enable signal low acknowledges that port has been served. Requirement is that if there are two simultaneous requests, port 2 should be connected. However if port 1 is already connected due to previous request, the port 2 should wait until port 1 has been served.
My questions are:
What are problems with the code that I've written (and why)?
What would be your approach for making this code synthesizable (not aksing for final solution, but hopefully for useful hints)
Because of the problem with formatting the code part of this post I've included code as image as well.
transition: process (clk)
begin
if rising_edge(clk) then
if reset = '1' then
state <= port1;
else
if (state = port1) and (req_p2.enable='1') and
(req_p1.enable='0' or rising_edge(req_p1.enable)) then
state <= port2;
elsif(state = port2) and (req_p2.enable='0') then
state <= port1;
end if;
end if;
end if;
end process;
This line of your code is not synthesisable:
rising_edge(req_p1.enable)
To make it synthesisable you need to replace the rising_edge function with some actual logic that detects a rising edge - a synchronous rising edge detector. Something along the lines of this should work (I don't know your requirements):
sync_rising_edge: process (clk)
begin
if rising_edge(clk) then
if reset = '1' then
req_p1_enable_d <= '0';
else
req_p1_enable_d <= req_p1.enable;
end if;
end if;
end process;
transition: process (clk)
begin
if rising_edge(clk) then
if reset = '1' then
state <= port1;
else
if (state = port1) and (req_p2.enable='1') and
(req_p1.enable='0' or (req_p1_enable_d = '0' and req_p1.enable = '1')) then
state <= port2;
elsif(state = port2) and (req_p2.enable='0') then
state <= port1;
end if;
end if;
end if;
end process;
The rising_edge function is synthesisable if there it is used in the conventional way inside a clocked process. See my answer here.

How to make startup process in VHDL

How to make a process that executes only once on powering up?
It is easy to make a process that executes when reset button is pressed, but how to make it run when you plug in the power supply without touching the reset button?
In my example I want to initialize the LCD on startup and I need to send some commands to it in the beginning, but I don't need it in the process that is dependent on some signal like reset(just let's suppose there is no reset button at all).
The state (first run) is stored in a single FF, which is initialized with '1':
signal IsStartup : STD_LOGIC := '1';
FF process without reset:
process(clk)
begin
if rising_edge(clk) then
IsStartup <= '0';
end if;
end process;
Usage example (FSM):
process(clk)
begin
if rising_edge(clk) then
if (Reset = '1') then
State <= ST_RESET;
else
State <= NextState;
end if;
end if;
end process;
process(State, IsStartup)
begin
NextState <= State;
case State is
when ST_RESET =>
if (IsStartup = '1') then
NextState <= ST_STARTUP;
else
NextState <= ST_IDLE;
end if;
-- ...
end case;
end process;
Just use a wait statement with no sensativity list.
process
begin
assignment <= "101";
wait;
end process;
That being said, I'd recommend that you instead build this as a state machine.

VHDL Pullup Resisters

I am fairly new to vhdl, I am working to understand if I can use it for a project.
I created a project to see how to implement pullup resisters and see how they work. I must have done something wrong.
My constraints entry for the wire is
net "rx_i" PULLUP;
net "rx_i" loc="p88";
the process for the project is
Process (clk_i)
type state_type is (qInit, qZero, qZero1, qZero2, qZero3, qZero4);
variable state: state_type:= qInit;
Begin
if (rising_edge(clk_i)) then
case state is
when qInit =>
if (rx_i = '0') then
led_o(0) <= '1';
state := qZero;
end if;
when qZero =>
if (rx_i = '0') then
led_o(1) <= '1';
state := qZero1;
end if;
when qZero1 =>
if (rx_i = '0') then
led_o(2) <= '1';
state := qZero2;
end if;
when qZero2 =>
if (rx_i = '0') then
led_o(3) <= '1';
state := qZero3;
end if;
when qZero3 =>
if (rx_i = '0') then
led_o(4) <= '1';
state := qZero4;
end if;
when qZero4 =>
if (rx_i = '0') then
led_o(5) <= '1';
state := qInit;
end if;
end case;
end if;
End Process;
All of the led's 0 thru 5 light up. If the wire is pulled up high I would expect maybe a few spurious 0's but not 6 in a row. Any help would be appreciated.
First: you never set the value of your leds back to '0'. Once you have set all values to '1' in this state machine, you keep driving '1'. You could add a line like led_o <= (others => '0'); before your case statement.
Even then, you will be running through the states at the speed of your clock. Your leds will be blinking so fast that your eyes just sees them as "on", but slightly less bright. perhaps you can add a counter in each state, or check for another condition like a button pushed.
Finally, the code you have posted shows nothing of a pull-up. I'm just assuming you are using that in another part of your code. The problems I can see have nothing to do with pull-ups.
Your constraints file is only used when the code gets synthesized and turned into a bitstream to be loaded onto the FPGA. It has nothing to do with simulation. In simulation you can create a pullup by driving 'H' (high) onto a signal.
If you want led_o to be the signal pulled up you could do:
led_o <= 'H';
led_o <= LED_DRIVE;
So when LED_DRIVE is high impedance (Z) then the pullup will take over and pull the signal high. This is how you would implement a bidirectional interface such as I2C. But I think now that I've gone over your head. The tutorial here shows how you could create a simple LED blinker: http://www.nandland.com/vhdl/tutorials/tutorial-your-first-vhdl-program-part1.html

Resources