2
\$\begingroup\$

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.

\$\endgroup\$
  • \$\begingroup\$ When you write 'it tied data_out to data_in' do you mean that you are looking at the synthesised code? \$\endgroup\$ – copper.hat Sep 17 '14 at 6:45
  • \$\begingroup\$ I run a compilation and then use ModelSim to look at the signals. \$\endgroup\$ – Snagglewhen Sep 18 '14 at 16:45
  • \$\begingroup\$ Is the compiled circuit just a buffer? \$\endgroup\$ – copper.hat Sep 18 '14 at 16:50
  • \$\begingroup\$ Not even a buffer, just a wire from data_in to data_out \$\endgroup\$ – Snagglewhen Sep 18 '14 at 17:00
  • \$\begingroup\$ 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? \$\endgroup\$ – copper.hat Sep 18 '14 at 17:07
3
\$\begingroup\$

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
\$\endgroup\$
  • \$\begingroup\$ 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. \$\endgroup\$ – Snagglewhen Sep 18 '14 at 16:35
  • \$\begingroup\$ @Andrew See if the update answer might help. \$\endgroup\$ – pre_randomize Sep 18 '14 at 17:38
  • \$\begingroup\$ I had to change "logic" to "reg". I have never seen a signal declared as logic before. \$\endgroup\$ – Snagglewhen Sep 18 '14 at 18:06
  • \$\begingroup\$ @Andrew, sorry that is system verilog, effectively switches between reg and wire, depending on how signal is driven. \$\endgroup\$ – pre_randomize Sep 18 '14 at 20:51
2
\$\begingroup\$

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.

\$\endgroup\$
  • \$\begingroup\$ always_ff is not a reserved word, and throws errors when compiling. \$\endgroup\$ – Snagglewhen Sep 18 '14 at 16:36
  • \$\begingroup\$ 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) \$\endgroup\$ – Greg Sep 18 '14 at 18:04
0
\$\begingroup\$

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'.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.