So I'm a newbie to Verilog. I decided to purchase a nice board (a Terasic DE0-CV) and teach myself some Verilog. And I'm seeing some strange behavior that I can't explain.
I lifted some code out of an example that drives the 7-seg LEDs. And I have them tied to a register. Whatever the register holds, the LEDs display.
reg [23:0] mSEG7_DIG;
SEG7_LUT_6 u0 ( .oSEG0(HEX0),
.oSEG1(HEX1),
.oSEG2(HEX2),
.oSEG3(HEX3),
.oSEG4(HEX4),
.oSEG5(HEX5),
.iDIG(mSEG7_DIG) );
I made a simple counter to drive the register, like this:
always @(negedge KEY[3]) begin
mSEG7_DIG <= mSEG7_DIG + 1;
end
And that works just fine. Click Key[3] on the board, the counter counts up from zero with each key click. Works like a charm. Sees the edge, increments the register, displays on the LEDs. So next, I wanted to make a way to clear the register to start back from zero. This is the idea I was thinking of.
always @(negedge KEY[3]) begin
mSEG7_DIG <= mSEG7_DIG + 1;
end
always @(negedge KEY[2]) begin
mSEG7_DIG <= 0;
end
This turns out to not be legal, since I have two always blocks trying to drive the same register. But you get where I'm going with this.
So I figure "Ok, I'll make them into one always block, then check the switch levels to see what we're trying to do, increment or clear."
So I did this to start.
always @(negedge KEY[3], negedge KEY[2]) begin
mSEG7_DIG <= mSEG7_DIG + 1;
end
For whatever reason when I do this, the counter counts so fast you can't see it. I've tested it for hardware problems by doing this:
always @(negedge KEY[2]) begin
mSEG7_DIG <= mSEG7_DIG + 1;
end
And that works fine too.
So what am I missing? Why does having two edge dependent signals in my always block's dependency list make it seem to be always true?
Edit: The hint from IanJ - "the synthesis tool doesn't want to make something sensitive to two different edges", and being able to see what synthesis is doing with my code in RTL viewer - this allowed me to solve the problem.
The problem - imagine a CLK line going into a D type flip flop. And you want two signals to control it. But I didn't specify HOW. The synthesis tool would have to be a mind reader to understand my intention. You have to explicitly say how you're triggering. This solves the problem. Full points to IanJ for the tip - that led to this solution.
wire change;
assign change = ~KEY[2] | ~KEY[3];
always @(posedge change) begin
if(~KEY[2]) begin
mSEG7_DIG <= mSEG7_DIG + 1;
end
else begin
mSEG7_DIG <= 0;
end
end