Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
470 views
in Technique[技术] by (71.8m points)

asynchronous - Verilog/VHDL - How to avoid resetting data registers within a single always block?

I like to avoid resetting data registers that don't need to be reset. For example, when streaming data through pipeline stages, if each stage has a valid bit, there is no need to reset the data registers. (I believe this eases routing and timing on the data registers.)

This can easily be accomplished by using separate always blocks (or processes in vhdl), but I find this verbose, and doing the following is problematic because the data register is essentially being enabled by the reset.

always @(posedge clk)
if (rst)
  out_valid <= 0;
  // NOTE: out_data is not reset
else begin
  out_valid <= in_valid;
  if (in_valid)
    out_data <= in_data + 1;
end

Instead, I've been putting the reset clause at the end of the always block and taking advantage of the "last assignment wins" rule.

always @(posedge clk)
begin
  out_valid <= in_valid;
  if (in_valid)
    out_data <= in_data + 1;

  if (rst)
    out_valid <= 0
end

I haven't seen a lot of people using this style. Are there any drawbacks or issues that I'm missing? Is there a better way of doing this?

Bonus Question: What if the reset is asynchronous? As in:

always @(posedge clk, posedge rst)
begin
  out_valid <= in_valid;
  if (in_valid)
    out_data <= in_data + 1;

  if (rst)
    out_valid <= 0
end

In this case I think the synthesizer will connect the reset signal to the data register, which defeats the purpose. Is there an elegant way of decoupling the data register from the reset signal without resorting to separate always block?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Synchronous Resets

I've been using the "last assignment wins" for resets for >5 years. Personally I find it easier to read and it saves having to needlessly indent the entire process one level. I've never seen any problems using this coding style with the FPGA synthesis tools I use (ISE, Quartus, Synplify).

Asynchronous Resets

To answer your bonus question regarding asynchronous resets - this is a little trickier. Consider the following:

typedef struct packed {
    logic               a;
    logic               b;
} state_t;

state_t                 state;

always_ff @(posedge clk or negedge areset_n) begin
    if (~areset_n) begin
        state.a         <= 1'b0;
    end else begin
        state.a         <= data_a;
        state.b         <= data_b;
    end
end

We have a bit of a problem. We don't want state.b to have a reset, but it's part of the same structure as state.a which is reset. Being good engineers we use always_ff processes but this actually means we can't split the code into separate processes. Besides, it would become very messy and error prone keeping track of which members are assigned in which process for a large state structure.

The above code actually synthesises to the following:

example of gated input

We can see that the areset_n signal acts as an enable to the state.b register. Typically this isn't what we want, and since most FPGAs don't support this architecture natively the synthesis tool is forced to insert additional logic to emulate the enable:

enter image description here

This extra logic reduces timing margin and uses up precious resource. Thankfully, there is a workaround:

always_ff @(posedge clk or negedge areset_n) begin
    if (~areset_n) begin
        state.a         <= 1'b0;
        state.b         <= 1'bx;
    end else begin
        state.a         <= data_a;
        state.b         <= data_b;
    end
end

Note that we have assigned x to state.b during the reset. As we can see, Quartus now synthesises our intended circuit:

enter image description here

Bonus Rant

As an aside, I'm not a big fan of being constrained to "standard practice" because the possibility that tools might get is wrong. "Conventional wisdom" is often incorrect or outdated.

Be adventurous and push the tools to their limits. If you hit a bug in the tool or a limitation then raise a bug with the vendor and adjust your style to compensate. Sure sometimes you'll spend time looking into a strange bug that turns out to be the fault of the toolchain but you should be looking at the output of your tools anyway. The time spent will be more than saved by the improved levels of abstraction and re-use made available with some of the newer language features.

If more of us pushed to get new features supported or participated in improving the languages then vendors wouldn't be able to get away with fobbing us all off with tools that are already 5-years out of date! The level of conservatism in RTL development hampers innovation - we love complaining about the tools but we don't participate enough in making them better.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...