1
\$\begingroup\$

I am trying to write verilog code or or thinking about a circuit to do the function below. In the clock period n, if there is a falling edge on S1 then OUT is high for the next clock cycle (n+1), if no falling edge is detected then OUT is low for the next clock cycle (n+1).

Is this possible? Can anyone show me how to do this?

enter image description here

\$\endgroup\$
  • 2
    \$\begingroup\$ What have you tried so far? This is pretty similar to your earlier question about using two negative clock edges so you should have some ideas of what you can do. \$\endgroup\$ – Elliot Alderson Apr 18 at 19:35
  • \$\begingroup\$ @ElliotAlderson I don't know how to process with next clock period. It has been a long time since I was doing verilog school day. I don't know if there is even possible with verilog. For the previous problem, everything is done in a clock cycle which seems easier. \$\endgroup\$ – anhnha Apr 18 at 19:39
1
\$\begingroup\$

You don't want to have two different always blocks controlling one signal.

Here's my version to avoid that

always @(negedge s1 or posedge clk) begin
    if(clk)
        saw_a_falling_edge <= 1'b0;
    else
        saw_a_falling_edge <= 1'b1;
    end

always @(posedge clk) begin
    out <= saw_a_falling_edge;
end

This is inferring a DFF with asynchronous clear to drive saw_a_falling_edge. The clk signal is connected to the CLEAR input and the s1 signal is connected to the clock. The D input is tied high.

If you did it the other way around then if the clock edge happened while s1 was still low, the output wouldn't go high (violating the requested behavior per your timing diagram).

Be aware the above solution won't handle the case that s1 goes low while clk remains high. It's not clear to me from your problem statement whether you need to handle that or not.

\$\endgroup\$
  • \$\begingroup\$ In the first always block, at rising edge of clk saw_a_falling_edge is always 0. So will the second always block, out is always 0? \$\endgroup\$ – anhnha Apr 18 at 20:21
  • \$\begingroup\$ @anhnha, saw_a_falling_edge physically can't change until a few (maybe 100) picoseconds after the clock edge. The out flip-flop will already have decided what it is going to change to before that. It will actually change based on what the input was a few (10-100?) picoseconds before the clock edge. This is called "negative hold time". \$\endgroup\$ – The Photon Apr 18 at 20:34
  • \$\begingroup\$ To do FPGA design, you need to get used to flip-flops responding to the "old" values on their inputs, not waiting for the changes on the inputs due to other flip-flops changing on the same edge. \$\endgroup\$ – The Photon Apr 18 at 20:36
  • \$\begingroup\$ I missed that concept which made it difficult. I tried to test in Modelsim and it works well. However, when I tried with DFF in PSIM circuit simulator, sometimes it works, sometimes not. The problem is maybe ideal DFF. Also, in my case falling edge of S1 is very close to rising edge of clk. \$\endgroup\$ – anhnha Apr 18 at 20:45
  • \$\begingroup\$ @anhnha, Falling edge of S1 very close to rising edge of CLK will make this problem fundamentally difficult, regardless of what technology you use. Maybe re-evaluate whether this is the right way to solve your bigger problem. \$\endgroup\$ – The Photon Apr 18 at 20:57
2
\$\begingroup\$

Use the solution given in verilog code with two falling edges, followed by another DFF. Adjust the edge directions as needed.

Putting it all together, you get:

module saw_falling_edge (
  input s1,
  input clock,
  output reg out
);
  reg set_ff;
  reg reset_ff;
  wire q = set_ff ^ reset_ff;

  always @(negedge s1) if (!q) set_ff <= !set_ff;
  always @(posedge clock) begin
    if (q) reset_ff <= !reset_ff;
    out <= q;
  end

endmodule
\$\endgroup\$
0
\$\begingroup\$

In principle, you'd do something along the lines of:

input clk;
input s1;
output reg out;

reg saw_a_falling_edge;

always @(negedge s1)
    saw_a_falling_edge <= 1;

always @(posedge clk) begin
    out <= saw_a_falling_edge;
    saw_a_falling_edge <= 0;
end

In practice, this will probably fail timing analysis unless you can constrain s1 appropriately against clk.

\$\endgroup\$
  • \$\begingroup\$ can you explain what "constrain s1 appropriately against clk" mean? \$\endgroup\$ – anhnha Apr 18 at 19:56
  • \$\begingroup\$ Essentially, you have to promise to the synthesis tools that s1 won't change too close to a clock edge. Exactly how you do this will depend on what toolchain you're working with, and is a bit outside the scope of this question. \$\endgroup\$ – duskwuff Apr 18 at 19:57
  • \$\begingroup\$ This problem is only in synthesis tool? Ideally in my project, falling edge will approach the rising edge of clk. \$\endgroup\$ – anhnha Apr 18 at 20:01
  • 1
    \$\begingroup\$ I think it's ambiguous what this will synthesize. Is saw_a_falling_edge produced by a DFF with asynchronous set (clocked by clk) or with asynchronous reset (clocked by s1). Better to use a single always block to define saw_falling_edge as one or the other (and to specify in a synthesizable way what happens if the clk edge happens when s1 is still low or s1 edge happens when clk is still high) \$\endgroup\$ – The Photon Apr 18 at 20:03
  • \$\begingroup\$ I don't think the exact behavior decribed by the Verilog is synthesizable in an FPGA. \$\endgroup\$ – The Photon Apr 18 at 20:04

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.