# Verilog always block w/o posedge or negedge

I have a basic Verilog block that I wrote to trigger on any change in the signal.

always @ (trigger)
begin
data_out <= data_in;
end


I expected this to trigger on the rising or falling edge of the trigger. Instead, it tied data_out to data_in. Even when the trigger was in steady state, the output was changing with the input. What am I missing here?

EDIT: I can only use the three signals listed: data_in, data_out, and trigger. The output must initiate on the bit flip of trigger.

• When you write 'it tied data_out to data_in' do you mean that you are looking at the synthesised code? Sep 17, 2014 at 6:45
• I run a compilation and then use ModelSim to look at the signals. Sep 18, 2014 at 16:45
• Is the compiled circuit just a buffer? Sep 18, 2014 at 16:50
• Not even a buffer, just a wire from data_in to data_out Sep 18, 2014 at 17:00
• Its been a few years since I dealt with this stuff, are you using any directives that would affect this? Any warnings during synthesis? Are you using a cycle-level model perhaps? Sep 18, 2014 at 17:07

Not sure why it would trigger on data_in when written like that unless your synthesising it and simulating at gate level.

always @(posedge clk) in RTL maps to a flip-flop.

always @* in RTL maps to combinatorial logic.

The @* is an auto completed sensitivity list based on any signal which can effect an output (left hand side of =).

Your use of manually specifying a sensitivity list which is not used, to create an output value is not valid for synthesis. As it does not map to hardware.

NB: you should only use <= inside always @posedge blocks (when implying flip-flops) other wise use =.

May be create an edge detection circuit which can be used as an enable for a clocked system.

//Capture Previous trigger values
reg [1:0] trigger_d;
always @(posedge clk) begin
trigger_d = {trigger_d[0], trigger};
end

reg trigger_toggle;
always @* begin
//Bitwise XOR reduction operator creates pos & neg edge detect.
trigger_toggle = ^trigger_d;
end

always @(posedge clk) begin
if (trigger_toggle) begin
data_out <= data_in;
end
end


Follow up to question posted in comment for system without dedicated clock:

 logic pos_enable =1'b0;
logic neg_enable =1'b0;
always @(posedge trigger) begin
data_1     <= data_in;
pos_enable <= ~pos_enable;
end

always @(negedge trigger) begin
data_2     <= data_in;
neg_enable <= ~neg_enable:
end

wire sel = pos_enable ^ neg_enable;
always @* begin
if (sel) begin
data_out = data_1;
end
else begin
data_out = data_2;
end
end

• One of the issues here is that there is no clock, so the output has to trigger on the bit flip of the trigger. I am fairly limited in what I can do with this system. I have the input data, output line, and trigger. Those are all of the signals that I can work with. Sep 18, 2014 at 16:35
• @Andrew See if the update answer might help. Sep 18, 2014 at 17:38
• I had to change "logic" to "reg". I have never seen a signal declared as logic before. Sep 18, 2014 at 18:06
• @Andrew, sorry that is system verilog, effectively switches between reg and wire, depending on how signal is driven. Sep 18, 2014 at 20:51

There shouldn't be an issue with simulation. There will be an issue when synthesizing, which will generate pass through behavior instead of being clocked via double edge. Most synthesizers do not support double edge clocking and those that do often require special setup and restriction. Refer to the manual and other documentation from the synthesizer/FPGA.

In general, always @ (trigger) will not synthesize to a double edge flip flop. If your synthesizer supports double edge flops, then try: always @ (posedge trigger or negedge trigger). This makes it more explicate for edge events. Additional requirements may be required for by the synthesize tool such as declaring the trigger as a dual data rate clock. If you don't follow the synthesizers requirements for identifying a double edge flops then it could infer one of the edges as asynchronous set/reset level trigger.

SystemVerilog did simplify the clocking for double edge events. However, even if SystemVerilog is supported, some vendors haven't implemented support for this feature. If supported on your system then try: always_ff @(edge trigger). It is more compare and explicit than declaring both edges in the sensibility list and should generate the same logic.

• always_ff is not a reserved word, and throws errors when compiling. Sep 18, 2014 at 16:36
• always_ff is reserved word for SystemVerilog. Modern simulations/FGPAs support both Verilog & SystemVerilog. Change the file extinction from .v to .sv to enable SystemVerilog parsing on the file (recommenced) or check your tools options to globally enable (commonly -sv or -sverilog)
– Greg
Sep 18, 2014 at 18:04

As other have pointed out already in their answers, the non-edge elements of the sensitivity list are ignored in synthesis. It is not just in general done this way by synthesis tools, it is actually part of the IEEE Verilog RTL synthesis standard (IEEE 1364.1, not IEEE 1364, note that there is no synthesis standard for System Verilog aka IEEE 1800).

Greg mentioned support for double edge flops in some tools. Dual edge flops are not supported by the standard and thus this are non-standard features. You can not expect a synthesis tool to support that.

However, if you really, really need a double edge flop and do not want to rely on non-standard features, and do not want to directly instantiate a cell primitive, then you can always use the following contraption:

module dual_edge_ff(trig, din, dout);
input trig;
input din;
output dout;

reg qpos = 0, qneg = 0;

always @(posedge trig)
if (dout != din)
qpos <= ~qpos;

always @(negedge trig)
if (dout != din)
qneg <= ~qneg;

assign dout = qpos ^ qneg;
endmodule


The initializations (qpos=0, qneg=0) are only there for simulation so that the module does not output constant 'x'.