I am wondering how it is possible to build a sequential verilog circuit with a reset trigger. The problem I am having is that I need an always block specifically for when the reset is triggered. I have created this example of a counter to demonstrate what I mean:
`timescale 1ns / 1ps
module Counter(input CLK, reset, output reg[2:0] val);
always@(posedge CLK)
val = val+1;
always@(negedge reset)
val = 0;
endmodule
The bug I get when synthesizing this is
"ERROR:Xst:528 - Multi-source in Unit <Counter> on signal <Mcount_val_cy<0>>; this signal is connected to multiple drivers.
Drivers are:
Output signal of FD instance <val_0>
Signal <val<0>> in Unit <Counter> is assigned to GND"
This is because val is updated in 2 always statements.
How can I work around this and have a sequential circuit with a reset trigger?
-
\$\begingroup\$ Keep in mind that Verilog is a hardware description language. What kind of hardware do you imagine could do what you're trying to do here? \$\endgroup\$Dave Tweed– Dave Tweed2018年04月18日 01:06:39 +00:00Commented Apr 18, 2018 at 1:06
-
1\$\begingroup\$ I doubt whether edge triggering clock and edge triggered reset together be implemented correctly in FPGAs \$\endgroup\$Meenie Leis– Meenie Leis2018年04月18日 03:06:46 +00:00Commented Apr 18, 2018 at 3:06
2 Answers 2
One way to do this is to combine the always blocks, like this:
module Counter(input CLK, reset, output reg[2:0] val);
always@(posedge CLK or negedge reset) begin
if (!reset) begin
val <= 0;
end else begin
val <= val+1;
end
end
endmodule
This will reset the counter whenever reset is low.
However, this may or may not be the functionality you're looking for. Generally, asynchronous resets in FPGAs are not a super great idea. An alternative is to use an edge detector, like this:
module Counter(input CLK, reset, output reg[2:0] val);
reg reset_reg = 0;
reg last_reset_reg = 0;
always@(posedge CLK) begin
reset_reg <= reset;
last_reset <= reset_reg;
if (!reset_reg && last_reset_reg) begin
val <= 0;
end else begin
val <= val+1;
end
end
endmodule
-
\$\begingroup\$ That would work if I wanted the val to be 0 whenever reset is low, but I want it to set val = 0 only on the negative edge of reset. This means that even if reset is at 0 it can keep counting. \$\endgroup\$user146255– user1462552018年04月18日 00:59:47 +00:00Commented Apr 18, 2018 at 0:59
-
\$\begingroup\$ This absolutely has to be asynchronous? \$\endgroup\$alex.forencich– alex.forencich2018年04月18日 01:05:54 +00:00Commented Apr 18, 2018 at 1:05
The most straightforward way to do this would be to synchronize the reset
signal into the counter's clock domain and then do the edge detection on it. Here's an actual snippet from a project I'm currently working on. I'm using a fixed local clock to measure the period of an incoming data signal.
/* This logic is in the "fast local clock" domain.
* The local clock is assumed to be faster than the RF signal itself, by
* a factor of at least two. We resynchronize bit_pulse to the FLC domain
* and count the number of cycles between the rising edges of those pulses.
*
* The bit_period is stable by the time the logic in the rf_in domain
* looks at it based on a delayed version of the original bit_pulse.
*/
always @(posedge clock) begin
flc_pulse_a <= bit_pulse;
flc_pulse_b <= flc_pulse_a;
flc_pulse_c <= flc_pulse_b;
if (sim_reset || (flc_pulse_b && !flc_pulse_c)) begin
bit_period <= bit_count;
bit_count <= 0;
end else begin
bit_count <= bit_count + 1;
end
end
Note that it IS possible to do what you want with a complex asynchronous state machine, but FPGAs do not generally have the resources to implement such things efficiently, and the tools are not set up to support such designs.
Plus, you need to think about boundary cases: If the two events (posedge clock
and negedge reset_l
) are truly asynchronous, that means they can occur arbitrarily close together. What behavior do you expect when that happens?