Prevent compiler from optimizing logic away

2019-08-12 04:47发布

问题:

I'd like to generate a reset signal (active high) that will last for a short period of time. I achieved it by following code:

always @(posedge clk or negedge rst_n or posedge data) begin
  if(~rst_n | data)
    data <= 1'b0;
  else if(ena)
    data <= 1'b1;
  else
    data <= data;
end 

Which is synthesized to D flip-flop:

My generated signal will be 1 only for time equal to propagation time through OR gate. Now I want to remove rst_n signal. But if I do that, I receive the following D flip-flop:

In that case, my signal will never be high. The easiest way to solve that I came up with is to add 2 NOT gates between Q and CLR. Unfortunately, my software (Quartus II) will synthesize those two gates away.

tl;dr - how to remove rst_n so reset signal will be generated correctly?

回答1:

Did you try using the "synthesis keep" tag for Quartus to insert buffers?

http://quartushelp.altera.com/13.1/mergedProjects/hdl/vlog/vlog_file_dir_keep.htm

try this:

module test(clk,ena,data);
input clk, ena;
wire data_n /*synthesis keep*/;
wire data_nn /*synthesis keep*/;
output reg data;

assign data_n = ~data; 
assign data_nn = ~data_n; 

always @(posedge clk or posedge data_nn) begin
  if(data_nn)
    data <= 1'b0;
  else if(ena)
    data <= 1'b1;
  else
    data <= data;
end

endmodule


回答2:

Can you make the D-flop synchronously reset, and not asynchronously?

If you feedback the output into asynchronous reset you will get a very unstable runt pulse, which may or may not even be able to fully propogate through the design. In that case you might only actually be resetting half the flops in your design, and you may get different behavior each time you power on the device.

If you want to drive reset until the first posedge, then just initialize the flop to 1, and put 0 on the D pin. Then your flop will drive 1 until the first clock cycle. This probably will not be stable, depending on when the clock starts running versus when the device is fully powered.

Ideally you would want a longer reset pulse, to give the device more time to powerup and stably propogate the reset through the design, and make sure that any other synchronously reset flops are initialized before the reset is released. In that case you can initialize a counter of a few bits to some value, and have it start counting down on power-up, and then deassert the reset when the counter reaches 0.

Also, this only applies to an FPGA design where you may set an initial value for a flop. If you were discussing a silicon design then an external reset signal would certainly be required.