How to solve latch warning? - vhdl

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;

Related

verilog bit select of concatenation

module mac #(
parameter integer A_BITWIDTH = 8,
parameter integer B_BITWIDTH = A_BITWIDTH,
parameter integer OUT_BITWIDTH = 20,
parameter integer C_BITWIDTH = OUT_BITWIDTH - 1
)
(
input clk,
input rstn,
input en,
input add,
input [A_BITWIDTH-1:0] data_a,
input [B_BITWIDTH-1:0] data_b,
input [C_BITWIDTH-1:0] data_c,
output reg done,
output [OUT_BITWIDTH-1:0] out
);
localparam
STATE_IDLE = 2'b00,
STATE_MULT = 2'b01,
STATE_ACCM = 2'b10;
reg [1:0] state;
reg signed [OUT_BITWIDTH-1:0] out_temp;
reg signed [A_BITWIDTH-1:0] data_a_bf;
reg signed [B_BITWIDTH-1:0] data_b_bf;
reg signed [C_BITWIDTH-1:0] data_c_bf;
assign out = out_temp;
always # (posedge clk or negedge rstn) begin
if(!rstn) begin
state <= STATE_IDLE;
data_a_bf <= {A_BITWIDTH{1'b0}};
data_b_bf <= {B_BITWIDTH{1'b0}};
data_c_bf <= {C_BITWIDTH{1'b0}};
done <= 1'b0;
out_temp <={OUT_BITWIDTH{1'b0}};
end
else begin
case(state)
STATE_IDLE: begin
// TO DO
// Done flag reset!
data_a_bf <= {A_BITWIDTH{1'b0}};
data_b_bf <= {B_BITWIDTH{1'b0}};
data_c_bf <= {C_BITWIDTH{1'b0}};
out_temp <={OUT_BITWIDTH{1'b0}};
done <= 1'b0;
if(en && !done) begin
// If en == 1 and done != 1, then running state.
// And capture data_a, data_b, data_c to buffer
data_a_bf <= data_a;
data_b_bf <= data_b;
data_c_bf <= data_c;
state <= STATE_MULT;
end
else begin
// If not, just waiting for condition.
end
end
STATE_MULT: begin
// TO DO;
if (!add) begin
// If add signal is low, do muliply with data_a_bf and data_b_bf.
//out_temp <= data_a_bf * data_b_bf;
out_temp <= {{{A_BITWIDTH{data_a_bf[7]}}, data_a_bf}*{{B_BITWIDTH{data_b_bf[7]}}, data_b_bf}}[15:0]; // >> this invokes a error, which is syntax error near "["
end
else begin
// If add signal is high, shift data_a_bf to match bit representation.
//out_temp <= {data_a_bf, 8'b0};
out_temp <= {data_a_bf, 8'b0};
end
state <= STATE_ACCM;
end
STATE_ACCM: begin
// TO DO
// Do add and make output 'done' flag high.( done = 1)
out_temp <= out_temp + data_c_bf;
done <= 1'b1;
state <= STATE_IDLE;
end
default:;
endcase
end
end
endmodule
I want to do 'bit select' concatenation of data_a_bf signed extension * data_b_bf signed extension and assign it to out_temp, but it occurs a syntax error. How can I do this?
I don't know how to do bit select of it.
I think you just need to see error line.
I just upload all code.
Selecting a bit of a concatenation is a feature of SystemVerilog, not Verilog. Make sure your file has a .sv file extension. The tool that you are using might also have a switch to turn on support for SystemVerilog.
A Verilog friendly solution would be to create a bit mask.
For example, change:
out_temp <= {{{A_BITWIDTH{data_a_bf[7]}}, data_a_bf}*{{B_BITWIDTH{data_b_bf[7]}}, data_b_bf}}[15:0]; // >> this invokes a error, which is syntax error near "["
To:
out_temp <= {{{A_BITWIDTH{data_a_bf[7]}}, data_a_bf}*{{B_BITWIDTH{data_b_bf[7]}}, data_b_bf}} & 'h0FFFF;

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.

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

Can't infer register for ... at ... because it does not hold its value outside the clock edge

This must be the most common problem among people new to VHDL, but I don't see what I'm doing wrong here! This seems to conform to all of the idioms that I've seen on proper state machine design. I'm compiling in Altera Quartus 9.2, for what it's worth. The actual error is:
"Can't infer register for "spiclk_out" at [file] [line] because it does not hold its value outside the clock edge"
ENTITY spi_state_machine IS
PORT(
spiclk_internal : IN STD_LOGIC;
reset : IN STD_LOGIC;
spiclk_out : BUFFER STD_LOGIC
);
END spi_state_machine;
PROCESS(spiclk_internal, reset)
BEGIN
IF reset = '1' THEN
spiclk_out <= '0';
END IF;
IF spiclk_internal = '1' AND spiclk_internal'EVENT THEN --error here
spiclk_out <= NOT spiclk_out;
END IF;
END PROCESS;
Thanks for your time.
As written, the process would cause spiclk_out to toggle on spiclk_internal edges even when reset is active, which is not how flip-flops with asynchronous resets should behave.
What you probably want is
SPICLK: process(spiclk_internal, reset)
if reset = '1' then
spiclk_out <= '0';
elsif spiclk_internal'event and spiclk_internal='1' then
spiclk_out <= not spiclk_out;
end if;
end process SPICLK;

Resources