asynchronous reset mechanism of D flip-flop in yosys - Page 1
Forum section: electronics / general

author: promach
author_rank: Frequent Contributor
timestamp: July 04, 2019, 02:05:45 am
content: Forthis D flip-flop with asynchronous reset, why is line 28 executed when it should not had ?Note: Please the comments at lines 5,6,7 as wellNote: I am usingformal verification tool, all the testbench stimuli are generated automatically by the tool.

author: ataradov
author_rank: Super Contributor
timestamp: July 04, 2019, 02:17:36 am
content: You mean the transition from step 4 to 5? Why would not it execute? It is a positive edge transition on the clock and enable is "1". Or am I missing something?

author: promach
author_rank: Frequent Contributor
timestamp: July 04, 2019, 02:43:48 am
content: QuoteNo, during posedge clk , enable is '0'

author: ataradov
author_rank: Super Contributor
timestamp: July 04, 2019, 02:46:37 am
content: There are many posedges shown here. Which one do you mean? Your cursor highlights negedge. And the next posedge has enable = "1".

author: promach
author_rank: Frequent Contributor
timestamp: July 04, 2019, 03:14:53 am
content: See the following instead.

author: ataradov
author_rank: Super Contributor
timestamp: July 04, 2019, 03:18:51 am
content: That's a visualization error. It is not clear how enable signal is created, but typically it is created by the process clocked from the same clk signal. It can't change "just before the edge". All changes in the real systems happen after the causing signal. Ans in this case it was "1" all previous cycle, so it would be "1" at the time of the positive edge, and it will go to "0" as the result of the edge.

author: hamster_nz
author_rank: Super Contributor
timestamp: July 04, 2019, 03:40:05 am
content: This little code is weird."Enable" is siad to be an async signal w.r.t. clk, so there is meta-stability errors.Having two clocks on the main block (the posedge on clk and reset_sync) is just weirdThe synchronizer seems to be being used in a funky way, to reset (maybe sync? or async?) to an initial stat of '1' and then feeding in zeros. So that might mean reset_sync is actually an async signal.It is like all the right ideas are there, but somehow viewed from an unusual perspective.

author: Bassman59
author_rank: Super Contributor
timestamp: July 04, 2019, 05:13:27 am
content: You need to show how the signalsenableanddare driven. Looks to me like they are synchronous to both edges of the clock, that is, they change a delta time after it.Why areenableanddchanging on both edges ofclk? They need to change only on one edge, likely the rising. You do want to model real hardware, right?So if we assume that the two signals are changing on both edges ofclk, that is, the clock edge occurs and thedandenablesignals are assigned and as such change a delta time after the clock edge -- then a block sensitive to the rising edge ofclkwill look at the state ofdandenableon that event. In your latest post, the cursor is on the start of state 5. There, the rising edge ofclkoccurred. At that instant, bothdandenableare 1. The assignment ofdtoqis scheduled. Once the delta cycles have finished, that assignment is completed, soqtakes on the value 1. That is correct.Whatever is drivingdandenablelikewise schedules those signals to go to 0. That assignment occurs at the same time as the assignment toqoccurs. The new values of 0 on those signals don't affect the previously-scheduled assignment.Even though they don't look like it on the waveform display, the clock-to-output times and the setup and hold times are all non-zero. The times are called "delta times." Sometimes, for modeling purposes, the newbie will add an explicit delay to the assignment to show that the output indeed does change some clock-to-output after the clock edge. But that's not necessary; that delay is always there.This is foundational synchronous logic design modeling! Think of it this way. On the active edge of the clock, everything on the right-hand side of non-blocking assignments is "frozen" and evaluated. When all of those evaluations are complete, only then is the assignment to the left-hand side scheduled and those left-hand signals update.

author: promach
author_rank: Frequent Contributor
timestamp: July 04, 2019, 06:42:53 am
content: @Bassman59You only discussed the clock-to-q time for 'enable' and 'd'What about 'reset_sync' ?During 'posedge clk' at the step 5 (look at orange cursor), 'reset_sync' still need to take some amount of delta time to change to '0' as wellHowever, you did not mention this and took this into account.If this is the case, "if(reset_sync)" should be executed instead of "else if(enable)"Could you advise further ?

author: SiliconWizard
author_rank: Super Contributor
timestamp: July 04, 2019, 01:17:37 pm
content: Show your test bench (ie. how you generate reset_sync and enable for instance). reset_sync seems to be changing on clk's rising edge, but it's hard to see what happens only visually.@hamster_nz: as far as I know, this is the usual way of expressing async resets in Verilog. I find that very nasty and don't like Verilog much...

author: promach
author_rank: Frequent Contributor
timestamp: July 04, 2019, 01:31:04 pm
content: It is formal verification.Testbench stimuliis created using formal tool.Also remember to look forsynchronizer.svCode:// Design// D flip-flop// https://www.edaplayground.com/x/5dzJ// If (asynchronous 'reset_sync' & enable') are true on the same clock,// and then 'reset_sync' is low on the next clock,// then the asynchronous 'reset_sync' gets ignored and the 'enable' appliedmodule dff (clk, reset, enable, d, q);input clk;input reset;inputenable;input d;output reg q;always @(posedge clk or posedge reset_sync)beginif (reset_sync) begin// Asynchronous reset when reset goes highq <= 1'b0;endelse if(enable)begin// Assign D to Q on positive clock edgeq <= d;endendwire reset_sync;synchronizer #(.RESET_STATE(1)) reset_synchronizer(.clk(clk),.reset(reset),.data_i(0),.data_o(reset_sync));`ifdef FORMALalways @($global_clock) assume(clk != $past(clk));localparam MAX_CNT = 16;reg[$clog2(MAX_CNT)-1:0] counter;initial counter = 0;always @(posedge clk) counter <= counter + 1;initial assume(reset);initial assume(enable);always @(posedge clk) if(counter == MAX_CNT << 1) assume(reset != $past(reset));//always @(*) assume(d == 1'b1);always @(clk)beginif(clk) assume(d == 1'b0);else assume(d == 1'b1);endalways @(clk)beginif(clk) assume(!enable);else assume(enable);endalways @(posedge clk or posedge reset_sync)beginif(reset_sync) assert(q == 0);else if(enable) assert(q == d);else assert(q == $past(q));endalways @(posedge clk) cover(reset && enable && d && !clk);`endifendmodule

author: SiliconWizard
author_rank: Super Contributor
timestamp: July 04, 2019, 01:37:58 pm
content: Sorry, I'm not sure why you're synchronizing your reset signal to clk if this is supposed to be an asynchronous reset... this alone looks fishy to me, but I'll leave it up to people more skilled with Verilog at this point.

author: rstofer
author_rank: Super Contributor
timestamp: July 04, 2019, 02:01:29 pm
content: I don't know anything about Verilog...If I wanted an asynchronous reset, I certainly wouldn't be looking for an edgeCode:architecture Behavioral of RisingEdge_DFlipFlop_AsyncResetHigh isbeginprocess(Clk,async_reset)beginif(async_reset='1') thenQ <= '0';elsif(rising_edge(Clk)) thenQ <= D;end if;end process;end Behavioral;If I wanted a synchronous reset:Code:architecture Behavioral of RisingEdge_DFlipFlop_SyncReset isbeginprocess(Clk)beginif(rising_edge(Clk)) thenif(sync_reset='1') thenQ <= '0';elseQ <= D;end if;end if;end process;end Behavioral;Over the years there have been many discussion re: synchronous versus asynchronous reset. Not quite to the level of C versus C++ warfare but pretty close.I'm coming around to the idea that asynchronous doesn't make sense in most cases. I suppose there are situations where it is exactly the right thing to do but I haven't run into them.

author: promach
author_rank: Frequent Contributor
timestamp: July 04, 2019, 02:12:46 pm
content: For an explanation of synchronizer.sv used as reset synchronizer, the concept isAsynchronous Assertion, Synchronous De-assertion

author: KrudyZ
author_rank: Frequent Contributor
timestamp: July 04, 2019, 02:33:02 pm
content: Looks like your simulator chooses to evaluate the synchronizer block first and then uses its output to evaluate the upper module's logic.This would mean that reset_sync is actually low at the clock edge in question, which would give you the result you are seeing.You could try pulling the synchronizer code out and putting it in a process on the top module instead of instantiating it.In general, having both clock and asynchronous reset lines change at the same time is asking for trouble.Functional simulation should be done using proper setup and hold times to make it clear what your logic levels are at all times.Adding race conditions is not helpful as you are discovering...

author: promach
author_rank: Frequent Contributor
timestamp: July 04, 2019, 02:51:23 pm
content: QuoteWith regards to this above quoted statement, I need to emphasize that we cannot avoid such situation at all because ofsynchronous reset de-assertionMaybe you need to rephrase this sentence, I may not get your sentence in your original implication or meaning.Additional NOTE:Someone told me that "The problem is that the IEEE verilog standard doesn't specifically state what is supposed to happen when both the clock edge rises and the asynchronous reset is deasserted at the same time."

author: KrudyZ
author_rank: Frequent Contributor
timestamp: July 04, 2019, 03:07:51 pm
content: Quote from: promach on July 04, 2019, 02:51:23 pmObviously, your simulator does not see it that way. Judging by its output it sees the reset de-assert before the clock edge, not after.My guess would be that this has to do with instantiating the synchronizer, even though every simulator that I ever worked with would handle this correctly.Aside from that, why is your test bench driving the d and enable lines like they are clocks?

author: NorthGuy
author_rank: Super Contributor
timestamp: July 04, 2019, 04:52:30 pm
content: I'd say it should work. I'm not a Verilog guy, but I assume that the Verilog construct produces a D-flop with a CLR pin. I don't see any race condition here. The synchronized reset from the synchronizer should go low after the clock edge, not before. Thus the flop should only react to the next clock edge. Of course, there's a clock jitter, setup and hold requiements, and such, but I don't think the simulation accounts for these things.Does your tool let you look on the generated schematics? Can you post it here?

author: promach
author_rank: Frequent Contributor
timestamp: July 05, 2019, 02:53:05 am
content: @NorthGuyThe following two screenshots are generated usingyosys tutorial

author: NorthGuy
author_rank: Super Contributor
timestamp: July 05, 2019, 04:17:01 am
content: Quote from: promach on July 05, 2019, 02:53:05 amThe schematics is what we should expect based on your code.reset_sync is generated by $9, which is clocked by the same clock as $12. Assuming there's no clock skew, $12 must be still in reset for the clock edge which causes $9 to go low (#5 on your screenshot). Therefore, $12 can only change on the next clock edge (#6 on your screenshot). Yet, your screenshot shows it changing at edge #5.

author: SiliconWizard
author_rank: Super Contributor
timestamp: July 05, 2019, 02:09:02 pm
content: Just a thought here (keeping in mind I'm again no Verilog guru...) - the thing that I found weird was the mix between asynchronous and synchronous reset approaches. The process used here has "posedge reset_sync" in its sensitivity list (if that is called that in Verilog...), which (even though it looks ugly for us VHDL guys) I think is the correct way of expressing an asynchronous reset.But in your case, shouldn't the reset_sync signal considered as a synchronous reset? And thus IMO you should remove the "or posedge reset_sync" clause, which is what you would do for a simple synchronous reset. I don't know if that would make a difference here (again I'm no good at Verilog) - but keeping it definitely looks weird, and I don't see the point of it since reset_sync is synchronized to clk if I got it correctly.

author: NorthGuy
author_rank: Super Contributor
timestamp: July 05, 2019, 03:13:49 pm
content: Quote from: SiliconWizard on July 05, 2019, 02:09:02 pmI may be wrong, but I think what OP tries the accomplish is a asynchronous reset (that is the flop gets reset immediatly when reset goes high), but he wants the flop to come back from the reset synchronously (presumably, to make sure that multiple flops come out of reset on the same clock edge). If that's the goal, "reset" edge should be used in always@ (rather than the "reset_sync" edge).If the goal is a simple synchronous reset, I would drop the edge of the "reset_sync" from always@ - the whole point of synchronization is to get rid of unruly reset edges and use clock edges instead.

author: SiliconWizard
author_rank: Super Contributor
timestamp: July 05, 2019, 03:25:35 pm
content: Quote from: NorthGuy on July 05, 2019, 03:13:49 pmIf that's the case, indeed it should probably be:Code:always @(posedge clk or posedge reset)instead, but thats not enough. The following 'if' should also be:Code:if (reset) begininstead. Otherwise there's not going to be an asynchronous reset at all. Now an additional clause is needed to get out of the reset state when reset_sync goes low. Looks like it would warrant some kind of simple FSM to do this. The simplistic original approach can't work IMO.Quote from: NorthGuy on July 05, 2019, 03:13:49 pmYes, that's what I suggested. Since the OP only uses reset_sync in this process, this is what seemed to make sense based on their code. But yes, see above if it's not what was intended.

author: NorthGuy
author_rank: Super Contributor
timestamp: July 05, 2019, 03:35:07 pm
content: Quote from: SiliconWizard on July 05, 2019, 03:25:35 pmI would useCode:if (reset|reset_sync) beginin this case.OP might have wanted something totally different. For example he could have used this construction as a copy-paste simply to infer a flip-flop with reset - I don't use Verilog, so I can't really tell.

author: promach
author_rank: Frequent Contributor
timestamp: July 05, 2019, 04:05:44 pm
content: Hey guys,Code:always @(posedge clk or posedge reset_sync)is to describe asynchronous reset assertion, synchronous reset de-assertion.See synchronizer.sv again

author: SiliconWizard
author_rank: Super Contributor
timestamp: July 05, 2019, 04:08:57 pm
content: Quote from: NorthGuy on July 05, 2019, 03:35:07 pmYes, I guess that should work, although I admit mixing asynchronous and synchronous signals in the same clause makes me uncomfortable.Quote from: NorthGuy on July 05, 2019, 03:35:07 pmYes, this is still not very clear what they intended. If all they wanted is to make an asynchronous reset synchronous, then they can do what we suggested above. Treat it as a synchronous reset.In that case, I'm wondering something. Adding the "or posedge reset_sync" clause, as the OP did, should probably be kinda harmless as far as Verilog is concerned, even if it's not required (to be confirmed by a Verilog specialist), but maybe the simulator they use gets confused by this and handles it incorrectly.

author: SiliconWizard
author_rank: Super Contributor
timestamp: July 05, 2019, 04:19:32 pm
content: Quote from: promach on July 05, 2019, 04:05:44 pmWell, if you're positive this is valid Verilog for this, we'll have to trust you on that one.Then I'm sorry to say that yosys doesn't seem to be handling it well, which I wouldn't be all that surprised about either.

author: promach
author_rank: Frequent Contributor
timestamp: July 05, 2019, 04:58:12 pm
content: QuoteHmm... We need to judge any tool's handling capability based on latest IEEE systemverilog standard, not on our own perception.

author: Bassman59
author_rank: Super Contributor
timestamp: July 05, 2019, 05:23:19 pm
content: Quote from: promach on July 04, 2019, 06:42:53 amOhh, apologies, I see what you're asking about.Since your process, er, always block (sorry, I do VHDL) is sensitive to the clock and resetedges, then here is what happens.Your reset is synchronized to the clock, as are yourenableand yourdinput. This means that these signals all change a delta-timeafterthe clock.Your reset synchronizer appears to stretch thereset_syncoutput, which is fine. It looks like that synchronizer changes thereset_syncoutput on the rising edge of clk.So on some rising edge of the clock, all of the assignment right-hand sides are "frozen" and evaluated. At state five, d and enable are both high, and presumably so is the thing that assigns reset_sync. After the evaluation, q and reset_sync are both scheduled for assignment, and they will end up as '1' and '0' respectively.reset_sync, therefore, changes slightlyafterthe clock, not simultaneouslywithit.This is the important part!Now, in this case of state 5,reset_syncis driven low. This eventdoes not triggerthe always block which assignsq, because right there in the sensitivity list we seeposedge reset_sync. Therefore, there are no new updates for q and that signal retains its value ('1').If the block was sensitive to any event onreset_sync, not just the positive edge, then the block would be triggered and evaluated. But since the change at state five is to deassert reset, then itsifstatement evaluates as false andqis not driven to '0' and instead just retains its current value.One comment about your "asynchronous assertion, synchronous deassertion" of reset -- that is exactly the correct thing to do. Just make sure the resulting synchronized reset ends up on a global low-skew net or else some flip-flops could come out of reset before others.

author: Bassman59
author_rank: Super Contributor
timestamp: July 05, 2019, 05:26:47 pm
content: Quote from: KrudyZ on July 04, 2019, 02:33:02 pmIt will evaluate all blocks that are sensitive to the same signal event, and then schedule all outputs for assignment once all of the evaluations are complete.Put another way, on the sensitive event, the state of all signals on all of the right-hand sides of all of the assignments are frozen, and all of those right-hand sides are evaluated.This is the heart of the non-blocking assignment mechanism!The right-hand sides never see any changes made to their signals as a result of another always block being evaluated.

author: NorthGuy
author_rank: Super Contributor
timestamp: July 05, 2019, 05:31:24 pm
content: Quote from: promach on July 05, 2019, 04:05:44 pmShouldn't the "asynchronous assertion" happen at the pos edge of "reset" rather than "reset_sync", which is synchronized and delayed version of "reset"?

author: Bassman59
author_rank: Super Contributor
timestamp: July 05, 2019, 05:44:10 pm
content: Quote from: SiliconWizard on July 05, 2019, 02:09:02 pmThe correct idiom used when describing asynchronous resets in Verilog is indeedCode:always @(posedge clk or posedge reset)if (reset) q <= '0';else q <= d;Yes, Verilog is weird. And yes, it's a sensitivity list. The top-level "if" in the block first tests to see if reset is indeed true, because if it is not, then the only way the block could have been triggered is by the clock rising edge.QuoteHe may want to use an asynchronous reset for his flip-flops because his unstated chip architecture may not have a synchronous reset. Even though the reset signal is actually synchronized to the clock, the flip-flops can't use it as a proper reset.OK, let me clarify that. After years of Xilinx, where the gospel of "never use asynchronous resets" is preached, I had to do some designs using Microsemi ProASIC-3 devices. The flip-flops in these devices do not have a synchronous reset. However, the synthesis tool will happily create some logic which implements that functionality. So consider all of the logic in front of your flip-flop's D input. Now put a mux between that logic and the D input, with the mux's other input set to '0' (or '1' for preset), and the synchronous reset selects that '0' or the non-reset logic. It's another level of logic, and more importantly for this (kinda shitty) architecture, more routing. I've found that in these devices it's always the routing that kills your timing.So the solution for these devices is to implement a synchronized reset, ensure that it is on a global net (either with library component instantiation or by synthesis setting/inference) and then put that synchronized reset into the flip-flop's sensitivity list as an asynchronous reset, where it will be used as such.

author: NorthGuy
author_rank: Super Contributor
timestamp: July 05, 2019, 05:47:28 pm
content: Quote from: Bassman59 on July 05, 2019, 05:23:19 pmWhat do you mean by that? On OP's screenshot, the state of q prior to edge #5 is '0' - couldn't be anything else since the flop's reset is asserted. Then, after #5, for some strange reason, it goes to '1', as if the reset_sync de-assertion happened prior to the clock edge #5. It's either a simulator bug or some sort of user error while setting up the simulation.

author: Bassman59
author_rank: Super Contributor
timestamp: July 05, 2019, 05:55:00 pm
content: Quote from: NorthGuy on July 05, 2019, 05:31:24 pmNo, what promach wrote is correct. Whether the design flip-flops see the resetassertedsynchronously or asynchronously doesn't matter, all that matters is the deassertion. But the reset will be asserted asynchronously.We don't see the reset synchronizer circuit, but my guess is that it looks something like this (VHDL, because I do mostly VHDL).:Code:signal reset_sr : std_logic_vector(7 downto 0); -- keep reset to flops true after async reset goes awayalias sreset : std_logic is reset_sr(7); -- this is the global synchronized resetreset_synchronizer : process (clk, areset) isbeginif areset = '1' thenreset_sr <= (others => '1'); -- synchonized reset asserted with the async resetelsif rising_edge(clk) then-- the synchronized reset will deassert a few clocks after the async reset input goes awayreset_sr <= reset_sr(reset_sr'left - 1 downto 0) & '0';end if;end process reset_synchronizer;-- here is a flip-flop, reset asynchronously by that synchronized reset.myflop : process (clk, sreset) isif sreset = '1' thenq <= '0';elsif rising_edge(clk) thenq <= d;end if;end process myflop;So look at the reset_synchronizer process. The synchronized reset is asserted immediately with the async reset. It is deasserted synchronously as the clock shifts '0' into the shift register.

author: Bassman59
author_rank: Super Contributor
timestamp: July 05, 2019, 05:57:59 pm
content: Quote from: NorthGuy on July 05, 2019, 05:47:28 pmOhhhh, hmmm ...Let's look at this some more. It's even weirder than we think!We are in state 4.d,enable,reset_syncare all true. Therefore,qis low. Because even though reset_sync isn't changing, the state ofreset_syncis tested on each rising edge ofclk.At the rising edge event that starts state 5,d,enable,reset_syncare all true. The block is triggered.The block is evaluated top to bottom. The first thing we see is "isreset_synctrue?" And the answer is yes. Therefore,qis scheduled to be assigned to '0', the reset.This should end the block evaluation! And yes,qshould end up as '0'. The simulation is not correct, unless there is something in the synchronizer module doing something we do not expect, or the simulator is incorrectly evaluating the "else if" part of the block and seeing enable true so allowing the assignment ofdtoq.Boy, am I glad I do VHDL, where this shit is entirely unambiguous.

author: SiliconWizard
author_rank: Super Contributor
timestamp: July 05, 2019, 06:07:16 pm
content: Quote from: NorthGuy on July 05, 2019, 05:31:24 pmI don't think so, after thinking about it a bit more.'reset_sync' is not quite synchronous: it becomes asynchronous when the 'reset' signal itself is active, because 'reset_sync' itself is asynchronously reset. So what the OP did looks "correct" after all.I actually happen to do this kind of things in VHDL on occasion (even if not that directly): sometimes I create intermediate reset signals that reset some processes "asynchronously", but those reset signals are flipped synchronously - except when they are themselves reset! This is quite the same thing. And I've never had a problem with this. Depending on the target, it may make timing closure a bit more difficult, but it has never really bothered me in practice.Now the question that remains is whether the OP's "problem" (seemingly incorrect simulation outcome) stems from an incorrect way of implementing this in Verilog or from an issue in the simulator itself (which I'm leaning towards).

author: promach
author_rank: Frequent Contributor
timestamp: July 05, 2019, 06:32:49 pm
content: Hey guys,QuoteIt is not the issue with the tool. Please do not blame the tool.

author: NorthGuy
author_rank: Super Contributor
timestamp: July 05, 2019, 06:46:05 pm
content: Quote from: SiliconWizard on July 05, 2019, 06:07:16 pmYou're right. "reset_sync" is reset by "reset" asynchronously, so it' not much difference between them during assertion.

author: SiliconWizard
author_rank: Super Contributor
timestamp: July 05, 2019, 06:50:32 pm
content: Quote from: promach on July 05, 2019, 06:32:49 pmI'm not quite sure where you're getting at... are you a yosys developer? No tool is perfect.If you know (refering to the standard) for sure that what you do here triggers unknown behavior, why then would you even ask? *perplexed*

author: NorthGuy
author_rank: Super Contributor
timestamp: July 05, 2019, 06:56:20 pm
content: Quote from: promach on July 05, 2019, 06:32:49 pmIMHO, the results of the simulations you have posted do not match neither your code, nor the schematics (while the schematics do match the code). This is up to you do find the reason for the discrepancy. But one of the reasons might be a bug in the simulation tools.I suggest running your code in Vivado and comparing the results.

author: Bassman59
author_rank: Super Contributor
timestamp: July 05, 2019, 07:02:09 pm
content: Quote from: NorthGuy on July 05, 2019, 06:56:20 pmHere is the simulation in ModelSim. As you can see, the q output changes with state 7, which is the rising edge of clk when reset_sync is low. This does not match the yosys result.Without seeing the OP's code for the synchonizer nor the test bench, I'm going to go with the assertion that yosys isn't doing the right thing.Source code:Code:`timescale 1 ns / 100 psmodule dff(clk, reset, enable, d, q);input clk;input reset;input enable;input d;output reg q;wire reset_sync;reg [1:0] reset_sr;always @(posedge clk or posedge reset_sync)beginif (reset_sync) beginq <= 1'b0;endelse if (enable) beginq <= d;endendalways @(posedge clk or posedge reset)beginif (reset) beginreset_sr <= 2'b11;endelse beginreset_sr <= {reset_sr, 1'b0};endendassign reset_sync = reset_sr;endmodule // dffTest bench:Code:`timescale 1 ns / 100 psmodule dff_tb ();reg clk;reg reset;reg enable;reg d;wire q;integer step;initial beginstep = 0;clk = 1'b0;#10 clk = ~clk;step = 1;#10 clk = ~clk;step = 2;#10 clk = ~clk;step = 3;#10 clk = ~clk;step = 4;#10 clk = ~clk;step = 5;#10 clk = ~clk;step = 6;#10 clk = ~clk;step = 7;#10 clk = ~clk;step = 8;#10 clk = ~clk;step = 9;#10 clk = ~clk;step = 10;enddff u1 (.clk(clk), .reset(reset), .enable(enable), .d(d), .q(q));initial begind = 1'b1;enable = 1'b1;reset = 1'b1;// state 1@(posedge clk);reset = 1'b0;d = 1'b0;enable = 1'b0;// state 2@(negedge clk);d = 1'b1;enable = 1'b1;// state 3@(posedge clk);d = 1'b0;enable = 1'b0;// state 4@(negedge clk);d = 1'b1;enable = 1'b1;// state 5@(posedge clk);d = 1'b0;enable = 1'b0;// state 6@(negedge clk);d = 1'b1;enable = 1'b1;// state 7@(posedge clk);d = 1'b0;enable = 1'b0;// state 8@(negedge clk);d = 1'b1;enable = 1'b1;// state 9@(posedge clk);d = 1'b0;enable = 1'b0;// state 10@(negedge clk);d = 1'b1;enable = 1'b1;endendmodule // dff_tb

author: promach
author_rank: Frequent Contributor
timestamp: July 07, 2019, 02:12:54 am
content: synchronizer.svCode:// https://github.com/jbush001/NyuziProcessor/blob/master/hardware/core/synchronizer.sv//// Copyright 2011-2015 Jeff Bush//// Licensed under the Apache License, Version 2.0 (the "License");// you may not use this file except in compliance with the License.// You may obtain a copy of the License at//// http://www.apache.org/licenses/LICENSE-2.0//// Unless required by applicable law or agreed to in writing, software// distributed under the License is distributed on an "AS IS" BASIS,// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.// See the License for the specific language governing permissions and// limitations under the License.////// Transfer a signal into a clock domain, avoiding metastability and// race conditions due to propagation delay.//module synchronizer#(parameter WIDTH = 1,parameter RESET_STATE = 0)(input clk,input reset,output logic[WIDTH - 1:0] data_o,input [WIDTH - 1:0] data_i);logic[WIDTH - 1:0] sync0;logic[WIDTH - 1:0] sync1;always_ff @(posedge clk, posedge reset)beginif (reset)beginsync0 <= {WIDTH{RESET_STATE}};sync1 <= {WIDTH{RESET_STATE}};data_o <= {WIDTH{RESET_STATE}};endelsebeginsync0 <= data_i;sync1 <= sync0;data_o <= sync1;endendendmoduleNote that the manual testbench is not needed for yosys formal verification tool.dff.vCode:// Design// D flip-flop// https://www.edaplayground.com/x/5dzJ// If (asynchronous 'reset_sync' & enable') are true on the same clock,// and then 'reset_sync' is low on the next clock,// then the asynchronous 'reset_sync' gets ignored and the 'enable' appliedmodule dff (clk, reset, enable, d, q);input clk;input reset;inputenable;input d;output reg q;always @(posedge clk or posedge reset_sync)beginif (reset_sync) begin// Asynchronous reset when reset goes highq <= 1'b0;endelse if(enable)begin// Assign D to Q on positive clock edgeq <= d;endendwire reset_sync;synchronizer #(.RESET_STATE(1)) reset_synchronizer(.clk(clk),.reset(reset),.data_i(0),.data_o(reset_sync));`ifdef FORMALalways @($global_clock) assume(clk != $past(clk));localparam MAX_CNT = 16;reg[$clog2(MAX_CNT)-1:0] counter;initial counter = 0;always @(posedge clk) counter <= counter + 1;initial assume(reset);initial assume(enable);always @(posedge clk) if(counter == (MAX_CNT >> 1)) assume(reset != $past(reset));//always @(*) assume(d == 1'b1);always @(clk)beginif(clk) assume(d == 1'b0);else assume(d == 1'b1);endalways @(clk)beginif(clk) assume(!enable);else assume(enable);endalways @(posedge clk)beginif(reset_sync) assert(q == 0);else if(enable) assert(q == d);else assert(q == $past(q));endalways @(posedge clk) cover(reset && enable && d && !clk);`endifendmodule

author: KrudyZ
author_rank: Frequent Contributor
timestamp: July 07, 2019, 10:41:30 am
content: Quote from: Bassman59 on July 05, 2019, 05:26:47 pmI know that and a proper simulator will indeed evaluate this correctly as you have proven yourself with Modelsim and your test bench.What I was saying is that the OP's simulator does not seem to be seeing it that way as its output disagrees with what Modelsim correctly shows.So there seem to be two possibilities. Either the (non-existing since not needed) test bench that yosys does something funky with its edge placements, or the simulator simply doesn't work right.This could have something to do with mixing Verilog and Systemverilog as this wouldn't be the first time, this causes problems with EDA tools.To figure out what's wrong the OP could take your test bench and run his simulator on it or, as I already suggested, take the his synchronizer code and add it to his top level as Verilog code instead of instantiating a sv module to see if he can get the correct result.

author: promach
author_rank: Frequent Contributor
timestamp: July 07, 2019, 01:06:51 pm
content: QuoteThis also gives same result which I had tried today.

author: KrudyZ
author_rank: Frequent Contributor
timestamp: July 07, 2019, 02:39:30 pm
content: Quote from: promach on July 07, 2019, 01:06:51 pmHave you also tried running with bassman59's test bench?If that also gives the same result, then your simulator is not working correctly...

author: promach
author_rank: Frequent Contributor
timestamp: July 07, 2019, 03:04:34 pm
content: again, yosys is formal verification tool, not a simulator tool.Both tools require entirely different code for testbench.

author: NorthGuy
author_rank: Super Contributor
timestamp: July 07, 2019, 05:47:03 pm
content: Quote from: promach on July 07, 2019, 03:04:34 pmYou certainly treat it as such in your original post.

author: emece67
author_rank: Frequent Contributor
timestamp: July 07, 2019, 07:55:56 pm
content: .

author: Bassman59
author_rank: Super Contributor
timestamp: July 07, 2019, 08:58:41 pm
content: Quote from: promach on July 07, 2019, 03:04:34 pmLooks like yosys is wrong.Also, it looks likeyosysis a synthesis tool, not a formal verification tool.

author: promach
author_rank: Frequent Contributor
timestamp: July 10, 2019, 02:43:04 pm
content: Hey Guys,Unless you or I could show that yosys-smtbmc does not follow IEEE verilog standard on what is supposed to happen when both the clock edge rises and the asynchronous reset is deasserted at the same time ,yosys developers will just ignore my questions.They only follow standard specifications instead of follow blindly what results the other tools are giving.Do you get it ?Please correct me if wrong.Note: yosys-smtbmc is formal verification tool

author: Bassman59
author_rank: Super Contributor
timestamp: July 10, 2019, 04:10:58 pm
content: Quote from: promach on July 10, 2019, 02:43:04 pmMaybe you can show them your example and ask them to explain why its result differs from what the industry-standard tool gives you?QuoteWhy do you assume that ModelSim is not following standard specifications? Especially given that ModelSim has been around, well, forever.Why do you assume that what yosys-smtbmt is doing is correct?QuoteYou should have said that you were using yosys-smtbmc in your very first post, as the rest of us were wondering why you were doing verification with a synthesis tool.I just spent a few minutes looking at yosys-smtbmc. I found apaper. I even foundone of your posts on Reddit. I don't understand what his verification mechanisms (assert, assume, etc) are doing under the hood.Anyway, looking at Wolf's paper and your FORMAL code, I suspect that there's a race condition. I admit that I don't know anything about SystemVerilog Assertions, so I can't say whether you are using them correctly.

author: NorthGuy
author_rank: Super Contributor
timestamp: July 10, 2019, 05:16:09 pm
content: Quote from: promach on July 10, 2019, 02:43:04 pmThis has nothing to do with Verilog. The schematics they produced is correct. So, you can rule out everything which is related to Verilog. It's the later steps where the problem occur.There's no race condition here. The reset_sync is generated by the clock edge. In simulation, it is assumed to reach the destination by the next clock edge. In real life, where there's a clock skew, the clock at the receiving flop may be too late, so that it arrives after the reset_syn has gone low. But the behavioural simulation is not concerned with timing - it is run as if there's no clock skew and all the setup and hold requirements are met. This applies to about any signal in your design. reset_sync is not special.

author: Bassman59
author_rank: Super Contributor
timestamp: July 11, 2019, 05:06:14 pm
content: Quote from: NorthGuy on July 10, 2019, 05:16:09 pmMy comment about race conditions concerns what the yosys FORMAL stuff does, not what Verilog itself will do (as shown by my test bench).