Reputation: 11
Trying this on a Terasic DE10-Lite, programmed with Quartus Prime Lite Edition.
SW[0] is a switch. LEDR[0] is an LED. KEY[0] is a push button. The push button is active low. I want to model a flip flop that stores SW[0] in register r0 and displays it in LEDR[0] when KEY[0] delivers a rising edge.
The following works as expected:
module flipfloptest (
input [9:0] SW,
input [1:0] KEY,
output [9:0] LEDR);
reg r0;
assign LEDR[0] = r0;
always @(posedge(~KEY[0]))
r0 <= SW[0];
endmodule
I now add another push button, KEY[1], to the sensitivity list with the intention that pushing either down will set the flip flop.
module flipfloptest (
input [9:0] SW,
input [1:0] KEY,
output [9:0] LEDR);
reg r0;
assign LEDR[0] = r0;
always @(posedge(~KEY[0]) or posedge(~KEY[1]))
r0 <= SW[0];
endmodule
This behaves like a latch (i.e. no longer edge triggered). LEDR[0] immediately reflects the state of SW[0] without the need to press either KEY[0] or KEY[1]. Pressing one or both does not affect behavior in any way.
Clearly, I don't understand the meaning of this sensitivity list. What is the correct interpretation?
More context: I can get the desired behavior using a clock and state machine as shown below. My question is why the sensitivity list isn't behaving intuitively.
module flipfloptest (
input MAX10_CLK1_50,
input [9:0] SW,
input [1:0] KEY,
output [9:0] LEDR);
reg [1:0] tic0, tic1;
reg r0;
assign LEDR[0] = r0;
always @(posedge MAX10_CLK1_50) begin
case (tic0)
0: tic0 = (~KEY[0])?1:0;
1: tic0 = (~KEY[0])?2:0;
2: tic0 = (~KEY[0])?2:0;
endcase
case (tic1)
0: tic1 = (~KEY[1])?1:0;
1: tic1 = (~KEY[1])?2:0;
2: tic1 = (~KEY[1])?2:0;
endcase
if (tic0==1 | tic1==1)
r0 <= SW[0];
end
endmodule
Upvotes: 1
Views: 85
Reputation: 62236
Synthesis tools only recognize certain Verilog coding patterns. Refer to synthesizable constructs. The documentation for your Quartus tool set should describe what coding styles are supported.
Your 1st and 3rd code examples adhere to the synthesizable coding style, whereas your 2nd example does not. You should look at the log files that your synthesis tools created: there should be messages in there warning you about unintended latches.
The code in your 2nd example is unusual. Perhaps your synthesis tool did not know what to do with it, and it just decided to give you a latch. Unfortunately for you, that is not how your code simulates.
This code:
always @(posedge(~KEY[0]) or posedge(~KEY[1]))
r0 <= SW[0];
can be simplified as:
always @(negedge KEY[0] or negedge KEY[1])
r0 <= SW[0];
r0
will be updated with SW[0]
every time you get a negedge of either KEY[0]
or KEY[1]
. That does not behave like a latch. But, as I said, this code does not adhere to typical synthesis coding style.
Upvotes: 0