Yosys: Multiple edge sensitivities for asynchronous reset - verilog

I am teaching myself verilog, bare with me. :)
I have a clock line called enable coming from a clock divider I created.
I also have a rst button on my devboard.
I would like to modify the following code to react to rst button presses by turning off my leds:
always # (posedge enable) begin
if (leds == 8'b11111111) begin
leds <= 8'b00000000;
end else begin
leds <= 8'b11111111;
end
end
I added my rst button as an additional edge sensitivity and caught it in an if statement:
always # (posedge enable or negedge rst) begin
if (leds == 8'b11111111 || ~rst) begin
leds <= 8'b00000000;
end else begin
leds <= 8'b11111111;
end
end
When I synthesize this for ice40 using yosys, I get the following error: ERROR: Multiple edge sensitive events found for this signal
If it helps, the previous line of yosys output suggests that this always block is translated to a dff cell during synthesis.
I have seen several examples of people including asynchronous resets in their always blocks, so I am curious if somebody can teach me what I am violating in my case, as a novice to verilog/digital-logic.
Thank you so much!

A lot of synthesizers expect the code to follow certain coding styles. If your synthesizer supports async-reset then try making the reset logic exclusive.
always # (posedge enable or negedge rst) begin
if (~rst) begin
leds <= 8'b00000000;
end else if (leds == 8'b11111111) begin
leds <= 8'b00000000;
end else begin
leds <= 8'b11111111;
end
end
Your leds == 8'b11111111 || ~rst is logically equivalent. I haven't used a synthesizer smart enough to recognize it as logically equivalent.

Related

multi-driven net, or reg not being driven

I'm working on an assignment where I need to create a jackpot game. But I'm having trouble driving the register that controls the win condition and I can't figure out why. As far as I know, the always#(posedge zero) block should be able to run whenever I flip my switch to the up position. Then, so long as the right hot register value happens in the same instant, it should be able to set the win register. However, this is not the case. Nothing seems to happen, and I'm not sure why. I've tried running the always block from different sensitivities but nothing seems to effect it. Maybe I'm just mis-understanding how always blocks work or how the switch works, any help is appreciated.
module jackpot(
input [3:0] SWITCHES,
output [3:0] LEDS,
input CLOCK,
input reset
);
reg [3:0] hot = 4'd1;
reg win;
wire clk, zero, one, two, three;
Clock_Div CDD (CLOCK, clk);
assign LEDS[2:0] = hot[2:0];
assign zero = SWITCHES[0];
assign one = SWITCHES[1];
assign two = SWITCHES[2];
assign three = SWITCHES[3];
assign LEDS[3] = zero;
initial begin
win <= 1'b0;
end
always #(posedge zero) begin
if(hot[0] && zero)
win <= 1'd1;
end
always #(posedge clk) begin
if (reset == 1'b1) begin
hot <= 4'd1;
win <= 1'd0;
end
else if(win == 1'b1) begin
hot <= 4'b1111;
end
else begin
if(hot == 4'b1000) begin
hot <= 4'b0001;
end
else begin
hot <= hot << 1;
end
end
end
endmodule
Thanks to Serge's comment I've realized the issue. Like his comment says, driving a register from multiple always blocks throws a critical warning, and Vivado picks one of the blocks to use over the other. Once I made sure to isolate a reg to an always block the behavior started to look like I expected. This must just be something that got glossed over during class, or maybe I wasn't paying attention enough.

How do I drive a signal from 2 sources in system verilog

I'm trying to write a RTL model in which I monitor independent clock sources. These clock sources can have variable frequency (range 5 to 50MHz)
Let us say clk1 and clk2. I'm trying to drive a signal 'toggle' which is set '1' at every posedge of clk1 and is set to '0' at every negedge of clk2. I'm having trouble realizing this model.
I tried using 1 flop triggered at the positive edge of clk1 with inputs of this flop tied to 'high' and another flip flop triggered at the negative edge of clk2 with input tied to 'low'. I sent these outputs to a mux, but I have trouble figuring out how to drive the select signal of this mux
Here is my code snippet :
always_ff #(posedge clk1 or rstb) begin
if(!rstb) begin
flop1_out <= 0;
end else begin
flop1_out <= 1;
end
end
always_ff #(negedge clk2) begin
flop2_out <= 0;
end
assign toggle = sel ? flop1 : flop2;
So, as of now nothing is driving sel and trying to figure this out is where I'm having trouble
If I try to drive the same signal (toggle) from 2 different clock sources, I get an error saying that multiple drivers found for signal toggle, which makes sense.
Please let me know if you have any suggestions
EDIT: fixed a typo and removed rstb from the sensitivity list for flop2
assign rstn = clk2;
always # (posedge clk1 or negedge rstn)
if (~rstn)
toggle = 1'b0;
else
toggle <= 1'b1;
note: depending on the clock frequency and insertion delay relationships this circuit may become metastable. if you can tolerate delay, add a synchronizer on the output. better yet, if you can tolerate distortion, add a reset synchronizer on clk2 to clk1mx, where clk1mx is synchronous to clock1 but x times faster.

Verilog code, same structure, same style. How come one works but the other doesnt? Where did I go wrong?

I will get straight to the point. I have a simple counter that is trying to
mimic how a clock works pretty much. I have a module called counter60sec and another one called counter12hr
counter12hr
module counter12hr(reset, hourInc, overflowOut, hrCounter);
input reset;
input hourInc;
output overflowOut;
output [3:0] hrCounter;
reg overflowOut;
reg [3:0] hrCounter; //0'b1101 == 13 hours
//Initialize counter
initial begin
overflowOut = 1'b0;
hrCounter = 4'b0; //once hour reaches 12:59:59, it is supposed to go back to zero
end
//Everytime hrInc is one, increment hrCounter
always#(negedge reset or posedge hourInc) begin
overflowOut = 1'b0;
if(reset == 1'b0) begin
overflowOut = 1'b0;
hrCounter = 4'b0;
end
else begin
if (hourInc == 1'b1) begin
hrCounter = hrCounter + 1'b1;
end
end
end
always#(negedge hrCounter) begin
if (hrCounter == 4'b1100) begin
overflowOut = 1'b1;
hrCounter = 4'b0;
end
end
endmodule
counter60sec
module counter60sec(reset, secInc, minOut, secCounter);
input reset;
input secInc;
output minOut;
output [5:0] secCounter;
reg [5:0] secCounter; //0'b111100 == 60 seconds.
reg minOut;
//Initialize counter
initial begin
minOut = 1'b0;
secCounter = 6'b0;
end
//Everytime secInc is one, increment secCounter
always#(posedge secInc or negedge reset) begin
minOut = 1'b0;
if(reset == 1'b0) begin
minOut = 1'b0;
secCounter = 6'b0;
end
else begin
if (secInc == 1'b1) begin
secCounter = secCounter + 1'b1;
end
end
end
//output minOut to 1 to signal minute increase when secCounter hits 111100 in binary
always#(negedge secCounter) begin
if(secCounter == 6'b111100) begin
minOut = 1'b1;
secCounter = 6'b0;
end
end
endmodule
I have test bench set up for both. The counter60sec one works fine (Where when secCounter is at value of 60, the minOut becomes 1). The counter12hr follows the same concept, but the value of overflowOut never becomes 1.
For my hrCounter conditional statement in counter12hr.v, I have tried both 4'b1101 and 4'b1100 and neither of them worked. (Trying to get the overflowOut to become one when the hrCounter hits 13)
I've spent hours on this, taking break to relax my eyes etc. I still can't see where I am going wrong. Any help would be appreciated
you have a few issues. The main one is that you have a multiple-driven register in both cases:
always#(negedge reset or posedge hourInc) begin
overflowOut = 1'b0;
...
always#(negedge hrCounter) begin
if (hrCounter == 4'b1100) begin
overflowOut = 1'b1;
the overflowOut is driven from 2 different alsways blocks. Same as minOut in the second counter. The order in which those statements are executed is undefined and the resulting value would depend on the order.
You need to restructure your program in such a way that the registers are assigned in a single always block only.
Secondly, i think, that you have a logic bug, assigning your overflow to '0' in the first statement of the first block (same as in the second one).
Thirdly, you should have uset non-blocking assighments '<=' in finlal assignments to the registers.
something like the following should work.
always#(negedge reset or posedge hourInc) begin
if(reset == 1'b0) begin
hrCounter <= 4'b0;
overflowOut <= 1'b0;
end
else begin
if (hrCounter == 4'b1100) begin
overflowOut <= 1'b1;
hrCounter <= 4'b0;
end
else
hrCounter <= hrCounter + 1'b1;
overflowOut <= 1'b0;
end
end
end
Your code is wrong in so many ways...
Most likely it does not work because of:
#(negedge hrCounter)
You are using a vector but #... works with bits. So it will look at the LS bit only.
As to your code:first and most start using a clock. Do not use posedge and negedge of your signals to drive the other signals.
You use:
always#(posedge secInc ...
...
if (secInc == 1'b1)
Remove the 'if'. you have that condition already in your always statement. (But the signal should not be the 'always' anyway, it should be your clock)
Remove the 'initial' sections You have a reset which defines the start condition.
If you have an active low reset reflect that in the name. Call it reset_n or n_reset anything but 'reset' which is per convention a positive reset signal.
If your drive ANYTHING from an edge, be it from a clock or from other signals, use non-blocking assignments "<="
Do not use your generated signal edges to generate other signals. As mentioned use a clock for everything an in the clocking section use an if. Also do not drive signals from different 'always'. You can never know in which order they are executed and then you have a race condition. Thus the clear and the increment are all in one always block:
if (secCounter == 6'b111100) begin
minOut <= 1'b1;
secCounter <= 6'b0;
end
else
secCounter <= secCounter + 6'b000001;
Because of the timing aspect you now have to go to 59 not 60. Which is as you should expect as digital clocks and watches run from 00 to 59, not 00 to 60. You are allowed to use decimal numbers which will, again, make the code more readable: 6'd59, 4'd11

System verilog: if loop inside always block not executing

I wrote a piece of code to assert a signal (val_changed) synchronously when another 64-bit signal (val) changes value by more than a threshold. Later this signal need to be de-asserted based on a third signal's (adj_in_prog) negedge.
Here clk and val are inputs to the block.
logic [63:0] val_reg;
always #(posedge clk) begin
val_reg <= val;
end
always #(posedge clk) begin
if ((val - val_reg) > 64'hFFFFF) //Threshold = 64'hFFFFF
val_changed <= 1'b1;
#(negedge adj_in_prog);
val_changed <= 1'b0;
end
I understand that the above method is not the cleanest of ways to do it, but since this is test-bench code and so I don't need to synthesis this, thought of experimenting. But this code is not working as val_changed is not going 1. I would like to know why the if loop won't execute. As per me, val_changed should have gone high at the clock edge where marker is positioned in the waveform attached. Can someone please help? (waveform values are in hex)
in your case at the very first posedge of clk the second always block starts executing and processes the 'if' statement. Then it sticks at the #(negedge adj_in_prog) statement, waiting for the event. On the next clock edge it will continue waiting and will not re-enter and evaluate the 'if' statement, and so on. So, this explains why it is not progressing.
so, assuming that the adj_in_prog is turned on at val_changed changing to one, the following should work for you.
always #(posedge clk) begin
if ((val - val_reg) > 64'hFFFFF) //Threshold = 64'hFFFFF
val_changed <= 1'b1;
else if (!adj_in_prog);
val_changed <= 1'b0;
end

compiling Verilog code in Quartus

I'm new to verilog HDL and my first project is to implement a simple stopwatch counter using a set of registers. I'm using Altera Quartus.
When I tried compiling the code below, I keep getting an error for each and everyone of the registers. one of the error messages looks like this:
Error (10028): Can't resolve multiple constant drivers for net "sec0[3]" at test_interface.v(127)
Anyone can help? The code simulates fine in Modelsim.
Here's the fragment of code that's causing problems:
always # (posedge clk)
if (qsoutput == 1)
sec0 = sec0 + 1;
else if (sec0 == 4'b1010) begin
sec1 = sec1 + 1;
sec0 = 4'b0000;
end else if (sec1 == 4'b0110) begin
min0 = min0 + 1;
sec1 = 4'b0000;
end else if (min0 == 4'b1010) begin
min1 = min1 + 1;
min0 = 4'b0000;
end else if (min1 == 4'b0110) begin
sec0 = 4'b0000;
sec1 = 4'b0000;
min0 = 4'b0000;
min1 = 4'b0000;
end
Based on your code in Dropbox, you are assigning registers in multiple always blocks. This is illegal for synthesis and cosponsors to the Altera Quartus error message is referring to. A reg type should only be assigned with in one always block.
As an example, sec0 is defined in always #(posedge reset_reg) and the code provided in your question. The code in Dropbox is even worse because you split the counter logic into 4 separate always blocks that assign sec0.
I suggest you put all sec* and min* resisters one clock synchronous always block with an asynchronous:
always(#posedge clk or posedge reset_reg)
begin
if(reset_reg)
begin
// ... asynchronous reset code ...
end
else
begin
// ... synchronous counter code ...
end
end
This paper goes into detail about good verilog coding practices for synthesis:
http://www.sunburst-design.com/papers/CummingsSNUG2000SJ_NBA.pdf
Other issues you will have:
Use non-blocking (<=) when assigning registers. This is discussed in Cliff's paper mentioned earlier.
Get rid of the initial block. I understand some FPGA synthesizers allow it and some ignore it. It is a better practice to have an asynchronous to put everything into a known and predictable value.
The block starting with always # (clk or start_reg or lap_reg or reset_reg) has a bizarre sensitivity list and will likely give you problems. you wither want #(*) if you want combination logic or #(posedge clk or posedge reset_reg) for synchronous flops.
Very rarely dual edge flops are used. The line always # (posedge clk or negedge clk) should be always # (posedge clk) for synchronous or always #(*) for combination logic.

Resources