Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Can I create an active-low (asynchronous) reset? #363

Open
hofstee opened this issue Apr 22, 2020 · 13 comments
Open

Can I create an active-low (asynchronous) reset? #363

hofstee opened this issue Apr 22, 2020 · 13 comments

Comments

@hofstee
Copy link
Contributor

hofstee commented Apr 22, 2020

Refiling here instead of other repo. Sorry if it's a duplicate.

Specifically, I'm looking to mimic the following SystemVerilog code:

always_ff @(posedge clk, negedge rst_n)
  if (~rst_n) q <= 0;
  else q <= d;

async_reset=True gets halfway there, but it's still an active-high reset. Any way of making it active-low or somehow creating one manually with this behavior where I can also control the port name?

@whitequark
Copy link
Member

Currently there's no way to do so; it is something on my radar for a while, but also not trivial to add in a backward compatible way. Please see the discussion here: #185 (comment).

@whitequark
Copy link
Member

whitequark commented Apr 22, 2020

Regarding the port name, you can create a clock domain and then rename the signal using cd.rst.name = "foobar", for example. (nMigen guarantees that it will never mangle names of signals you use for ports, unless two of them clash.)

@hofstee
Copy link
Contributor Author

hofstee commented Apr 22, 2020

I'm not sure if I should put this here on in the other thread, but one case where an async active-low reset would be useful (even in FPGAs) is when you want to connect or adhere to something like an AHB/AXI interface. Currently, it wouldn't be possible to do this solely in nmigen unless you wrote a wrapper module around the generated code inverting the reset.

@whitequark
Copy link
Member

You'd have to write a wrapper module anyway to instantiate a clock domain, wouldn't you?

@hofstee
Copy link
Contributor Author

hofstee commented Apr 22, 2020

If the AXI clock is the same as your system/reference clock then I don't see why you would?

@whitequark
Copy link
Member

whitequark commented Apr 22, 2020

The reset is synchronous unless you explicitly configure it async. Maybe I'm missing some part of your plan here; could you illustrate what you mean with some code?

@hofstee
Copy link
Contributor Author

hofstee commented Apr 22, 2020

For example, a Zynq exposes AXI ports as one of the main means of communicating between the processing system and the programmable logic. Those might actually be synchronous resets but I don't recall. In either case, they're active-low.

So if you're taking the clock from the processing system to use as your clock in the programmable logic, then you're on the same clock domain as the AXI port you would be communicating on, so everything there is just on a single clock domain.

@whitequark
Copy link
Member

Yeah, I understand that. My question is on a much more practical level. If you make a single-clock AXI component in nMigen that creates its own clock domain, then it would be, in general, not reusable in nMigen code (at least nMigen code that follows the conventions) since such components shouldn't have their own clock domains but refer, through late binding, to existing sync domain in the design. On the other hand, if you want to get Verilog for that component with the domain configured for asynchronous reset, you do need to create a clock domain for it explicitly. Another relevant aspect is that nMigen's definitions of buses do not, in general, follow Verilog conventions for the signal names, so you'd have to rename the signals there as well.

This, as far as I can tell, implies that a wrapper is necessary anyway. (Such a wrapper doesn't have to be verbose or laborous--it could be a simple invocation of a Python function provided by the same library that contains the AXI bus definitions.) And if you have a wrapper, you might as well invert the reset polarity there.

@akukulanski
Copy link

@hofstee Not really about nMigen, but in the Zynq you have a reset synchronizer that provides both high and low resets in it's outputs. From there, you can have cores with both low and high synchronic resets. Also if you are thinking about using the "Automation" provided by Vivado, you'll have to explicitly configure the reset port of the nmigen-generated core as "active high" beforehand (in the block design) and it'll do everything for you correctly (for some reason it assumes a low reset).

@github-4o
Copy link

github-4o commented Jan 27, 2021

where do i start if i were to implement active-low reset?

@github-4o
Copy link

github-4o commented Jan 27, 2021

https://github.com/nmigen/nmigen/blob/818c8bc46485ada0f31ad8ec23182ad01a6c7da1/nmigen/back/rtlil.py#L994
looks promissing. fixing this for negedge produces

sync negedge \rst
      update \v \v$next

in rtlil (look ok so far, is it a valid active-low reset in rtlil?). and verilog:

always @(posedge clk, posedge \$auto$proc_dff.cc:153:gen_dffsr$3 [0], posedge \$auto$proc_dff.cc:154:gen_dffsr$4 [0])
    if (\$auto$proc_dff.cc:154:gen_dffsr$4 [0]) v[0] <= 1'b0;
    else if (\$auto$proc_dff.cc:153:gen_dffsr$3 [0]) v[0] <= 1'b1;
    else v[0] <= \v$next [0];

for every bit of the signal being reset, which is not really an active low reset. i tested it with https://github.com/nmigen/nmigen/blob/master/examples/basic/arst.py example

so is it actually yosys who is unable to generate active low reset from valid rtl, or rtlil should look different?

@github-4o
Copy link

github-4o commented Jan 27, 2021

can't find explicit confirmation that rtlil supports negedge SyncRules, but yosys source annotation says negedge is a valid type for SyncRule:
http://eddiehung.github.io/yosys/d3/dc3/namespaceRTLIL.html#a79713e13c00e4e216c60fb297be1900f
update: quick tests show that sync negedge \rst is a valid rtlil SyncRule

@whitequark
Copy link
Member

It's not clear what the design for active-low resets should be, so you should write an RFC we can discuss before any code changes will be considered at all.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

No branches or pull requests

4 participants