Project

General

Profile

[logo] 
 
Home
News
Activity
About/Contact
Major Tools
  Dinotrace
  Verilator
  Verilog-mode
  Verilog-Perl
Other Tools
  BugVise
  CovVise
  Force-Gate-Sim
  Gspice
  IPC::Locker
  Rsvn
  SVN::S4
  Voneline
  WFH
General Info
  Papers

Wait on rising edge from c++

Added by Michal Orsak 17 days ago

Hello,

how can I emulate trigger on rising/falling edge of the signal?

I have clock from DUT and I need to sample output in right time. If I just change main clock and call eval() all combination paths are evaluated and I am not able to read correct value from simulation, because it is too late.

I need somehow call callback if signal value is updated. Or I need to perform combinational and sequential eval() in separate run.


Replies (6)

RE: Wait on rising edge from c++ - Added by Wilson Snyder 17 days ago

Perhaps I misunderstand the problem, but call eval() without changing any clocks, then compute your combo logic, then call eval() again without changing any clocks, repeat your logic and eval() calls until stable.

RE: Wait on rising edge from c++ - Added by Michal Orsak 17 days ago

module Cntr #(parameter  DATA_WIDTH = 2
    )(input clk,
        output clk_out,
        input en,
        input rst,
        output [DATA_WIDTH- 1:0] val
    );

    reg [DATA_WIDTH- 1:0] counter = 2'b00;
    reg [DATA_WIDTH- 1:0] counter_next;
    assign clk_out = clk;
    always @(posedge clk) begin: assig_process_counter
        if(rst == 1'b1) begin
            counter <= 2'b00;
        end else begin
            counter <= counter_next;
        end
    end

    always @(counter or en) begin: assig_process_counter_next
        if((en)==1'b1) begin
            counter_next = counter + 2'(1);
        end else begin
            counter_next = counter;
        end
    end

    assign val = counter;
endmodule

Problem: If I wait in C++ on clk_out == 1 the value of val will be 1, but on rising edge of clk_out it was 0.

Combinational update and sequential update is not separable
void VCntr::_eval(VCntr__Syms* __restrict vlSymsp) {
    VL_DEBUG_IF(VL_DBG_MSGF("+    VCntr::_eval\n"); );
    VCntr* __restrict vlTOPp VL_ATTR_UNUSED = vlSymsp->TOPp;
    // Body
    vlTOPp->_combo__TOP__2(vlSymsp);
    if (((IData)(vlTOPp->clk) & (~ (IData)(vlTOPp->__Vclklast__TOP__clk)))) {
    vlTOPp->_sequent__TOP__4(vlSymsp);
    vlTOPp->__Vm_traceActivity = (2U | vlTOPp->__Vm_traceActivity);
    }
    vlTOPp->_combo__TOP__5(vlSymsp);
    // Final
    vlTOPp->__Vclklast__TOP__clk = vlTOPp->clk;
}

Possible solutions: use VPI as shown in https://www.veripool.org/projects/verilator/wiki/Manual-verilator#VPI-Example

  • problem: copy of signal memory each time?, multiple simulations, multithreading

hack vlTOPp->_Vclklast_TOP__clk

  • if clk = new val do vlTOPp->_Vclklast_TOP__clk = new val, call eval(), then vlTOPp->_Vclklast_TOP__clk = prev val, call eval()
  • problem: unknown consequences, discovery of all clk signals

Also it is safe to have multiple simulations running in multiple threads?

Cntr.zip - .v, .cpp, .vcd (12.6 KB)

Screenshot.png View (8 KB)

RE: Wait on rising edge from c++ - Added by Michal Orsak 15 days ago

Hello, if you think I am doing something wrong, please tell me.

By combinational update I mean the update of paths before registers. By sequential update I mean the potential update of registers and combinational paths behind registers.

As code for sequential update is always in lower part of _eval() I need just split this function on two. (For arbitrary number of clock signals etc.)

I can create patch for this functionality, do you think this functionality can be part of Verilator?

RE: Wait on rising edge from c++ - Added by Wilson Snyder 15 days ago

Yes, with --threads 1 you can have different simulations in multiple thread.

The fundamental problem is really that generated clocks don't work nicely even in an all-verilator model, much less expecting external code as part of the process.

From a IEEE spec sense there isn't really a difference between combo and sequential code, the real difference is when delayed assignments take effect. However Verilator generally squashes this distinction because to do otherwise would be slow (all delayed assignments would need to be stored.)

However for your case it probably is the case that if you make a separate eval_combo call this would solve your issue. I won't make any claims this will solve more general problems; generally at present with Verilator clocks should be fed in, not out of the model for correct results.

If you want to experiment with an eval_combo() call I'd suggest to reduce performance loss that the eval_combo() replicate most of what is in eval() but without any of the clock detection. (Versus splitting combo out of existing eval() which would cause some optimizations to be lost.) This probably goes in V3Clock.cpp

Note the _combo in the function names isn't necessarily only combo code, you need to check the internal AstActive types to see what code is marked combo or not.

RE: Wait on rising edge from c++ - Added by Michal Orsak 14 days ago

Split of eval() eval_combo/_seq() is not generally possible.
  • Clock can be generated also from the output value of register.
Instead I have found out that different thing is required.
  • Notification before first event condition for each clock.

But that is actually good news as it requires only to add macro which can be empty in default implementation.

if (((IData)(vlTOPp->clk) & (~ (IData)(vlTOPp->__Vclklast__TOP__clk)))) {
    BEFORE_RISING_EDGE(&vlTOPp->clk);
    vlTOPp->_sequent__TOP__4(vlSymsp);
}
...
if (((IData)(vlTOPp->clk2) & (~ (IData)(vlTOPp->__Vclk2last__TOP__clk)))) {
    BEFORE_RISING_EDGE(&vlTOPp->clk2);
    vlTOPp->_sequent__TOP__5(vlSymsp);
}
...
No what features do I expect from simulator.
  • Possibility to write combinational loops in C-code.
  • satisfied, on first clk edge evaluation just break the _eval() and run it again (if required).
  • Possibility to read value on clock edge
  • satisfied, on the BEFORE_RISING_EDGE of specified clock just read the values
  • Clock gating
  • probably can be emulated
  • X, Z, U values
RE:
generated clocks don't work nicely even in an all-verilator model
I think that problem is that Verilator is not discrete event simulator. The problem is that order of events is specified compile time. But it may not be the problem as it can be solved by disabling of segments of eval() and revaluating of the eval(). But it may be quite hard task to find such a conditions for re-evaluation of the segments.

RE: Wait on rising edge from c++ - Added by Wilson Snyder 13 days ago

What do you propose BEFORE_RISING_EDGE will do? Generally this won't work as Verilator assumes all signals are only changed by Verilator itself. Furthermore due to scheduling the same clock may have multiple IF statements.

generated clocks don't work nicely even in an all-verilator model

I think that problem is that Verilator is not discrete event simulator.

Yes, there wasn't a question as to why they didn't work ;)

    (1-6/6)