Verilog.v

A clocked module, a testbench and an Icarus makefile - the same model your software target runs, in gates.

HDL Verified with Icarus Verilog (iverilog, vvp) Q16.16 fixed point 749 of 806 blocks
DPT_Feedback_Discrete.v
✓ verified · 1 %
`include "icore_defs.vh"

module DPT_Feedback_Discrete (
    input clk,
    input rst,
    input [1*`ICORE_WIDTH-1:0] blk2_gain,
    input [1*`ICORE_WIDTH-1:0] in_sig0,
    output [1*`ICORE_WIDTH-1:0] sig0,
    output [1*`ICORE_WIDTH-1:0] sig1,
    output [1*`ICORE_WIDTH-1:0] sig2,
    output [1*`ICORE_WIDTH-1:0] sig3,
    output [1*`ICORE_WIDTH-1:0] sig4
);

    function real to_real;
        input signed [`ICORE_WIDTH-1:0] v;
        begin to_real = $itor(v) / (2.0 ** `ICORE_FRAC_BITS); end
    endfunction
    function signed [`ICORE_WIDTH-1:0] to_fx;
        input real v;
        begin to_fx = $rtoi(v * (2.0 ** `ICORE_FRAC_BITS) + (v >= 0.0 ? 0.5 : -0.5)); end
    endfunction
    function integer fx_to_int;
        input signed [`ICORE_WIDTH-1:0] v;
        begin fx_to_int = v >>> `ICORE_FRAC_BITS; end
    endfunction

    reg [1*`ICORE_WIDTH-1:0] r_sig0 = 0;
    reg [1*`ICORE_WIDTH-1:0] r_sig1 = 0;
    reg [1*`ICORE_WIDTH-1:0] r_sig2 = 0;
    reg [1*`ICORE_WIDTH-1:0] r_sig3 = 0;
    reg [1*`ICORE_WIDTH-1:0] r_sig4 = 0;

    assign sig0 = r_sig0;
    assign sig1 = r_sig1;
    assign sig2 = r_sig2;
    assign sig3 = r_sig3;
    assign sig4 = r_sig4;

    reg signed [`ICORE_WIDTH-1:0] uh_blk3 [0:0][0:0];
    reg signed [`ICORE_WIDTH-1:0] yh_blk3 [0:0][0:0];

    always @(posedge clk) begin : exec
        reg [1*`ICORE_WIDTH-1:0] w_sig0;
        reg [1*`ICORE_WIDTH-1:0] w_sig1;
        reg [1*`ICORE_WIDTH-1:0] w_sig2;
        reg [1*`ICORE_WIDTH-1:0] w_sig3;
        reg [1*`ICORE_WIDTH-1:0] w_sig4;
        reg signed [2*`ICORE_WIDTH-1:0] acc;
        if (rst) begin
            r_sig0 <= 0;
            r_sig1 <= 0;
            r_sig2 <= 0;
            r_sig3 <= 0;
            r_sig4 <= 0;
            uh_blk3[0][0] <= 0;
            yh_blk3[0][0] <= 0;
        end else begin
            w_sig0 = r_sig0;
            w_sig1 = r_sig1;
            w_sig2 = r_sig2;
            w_sig3 = r_sig3;
            w_sig4 = r_sig4;
            acc = 0;

            // blk0: ICore Blocks/Home/DPT_Feedback_Discrete/In1
            w_sig0 = in_sig0;
            // blk1: ICore Blocks/Home/DPT_Feedback_Discrete/Error
            w_sig1[0*`ICORE_WIDTH +: `ICORE_WIDTH] = $signed(w_sig0[0*`ICORE_WIDTH +: `ICORE_WIDTH]) - $signed(w_sig3[0*`ICORE_WIDTH +: `ICORE_WIDTH]);
            // blk2: ICore Blocks/Home/DPT_Feedback_Discrete/Ctrl_Gain
            acc = $signed(w_sig1[0*`ICORE_WIDTH +: `ICORE_WIDTH]) * $signed(blk2_gain[0*`ICORE_WIDTH +: `ICORE_WIDTH]);
            w_sig2[0*`ICORE_WIDTH +: `ICORE_WIDTH] = acc >>> `ICORE_FRAC_BITS;
            // blk3: ICore Blocks/Home/DPT_Feedback_Discrete/Plant
            acc = 0;
            acc = acc + $signed(to_fx(0)) * $signed(w_sig2[0*`ICORE_WIDTH +: `ICORE_WIDTH]);
            acc = acc + $signed(to_fx(0.40000000000000002)) * $signed(uh_blk3[0][0]);
            acc = acc - $signed(to_fx(-0.59999999999999998)) * $signed(yh_blk3[0][0]);
            w_sig3[0*`ICORE_WIDTH +: `ICORE_WIDTH] = acc >>> `ICORE_FRAC_BITS;
            uh_blk3[0][0] <= w_sig2[0*`ICORE_WIDTH +: `ICORE_WIDTH];
            yh_blk3[0][0] <= acc >>> `ICORE_FRAC_BITS;
            // blk4: ICore Blocks/Home/DPT_Feedback_Discrete/Out1
            w_sig4 = w_sig3;
            r_sig0 <= w_sig0;
            r_sig1 <= w_sig1;
            r_sig2 <= w_sig2;
            r_sig3 <= w_sig3;
            r_sig4 <= w_sig4;
        end
    end

endmodule

What Deploy writes for the reference model below, with only the file's header banner removed. The same clocked pass in Verilog: each signal is a packed bus, the blocking working copies (w_sig*) run the ordered pass, and the non-blocking commits at the end make one edge one sample. The plant multiplies into a double-width acc and shifts by ICORE_FRAC_BITS - that shift is where Q16.16 rounding actually happens, and where an HDL residual against the simulation comes from.

Export · Verify · Integrate

From the diagram to your Verilog build.

Deploy writes the folder, ICore checks it against the simulation, and your code calls it once per sample.

01 · ExportICore

Deploy writes

  • icore_defs.vh
  • <name>.v
  • <name>_tb.v
  • Makefile (Icarus)
→ code/<name>/
02 · VerifyICore

Built, run and compared

Built with Icarus Verilog (iverilog, vvp), run across the simulation window and compared with the solver sample by sample, against a 1 % tolerance.

observed ≈1e-3 %
03 · IntegrateYour build

One call, one sample

Numbers are Q16.16 fixed point, and 749 of 806 library blocks export to Verilog.

one clk edge = one sample
With verification on, a failed comparison stops the export and says why, so a core that disagrees with the simulation never reaches your folder.
HDL target

Where Verilog fits.

The diagram becomes a module driven by clk: one edge, one sample. The generated icore_defs.vh carries the shared widths and fixed-point definitions.

Signals are Q16.16 fixed point, so the residual against the simulation is bounded by the 1.5e-5 quantum rather than by the generator. The verifier builds the testbench with Icarus Verilog and runs it with vvp.

Because the same diagram also exports to C or Rust, the usual FPGA workflow - prove the algorithm in software, then move it to fabric - stays one model rather than two implementations to keep in step.

$ Code Engine → Code Export Verifier → Verify All
Target classToleranceObserved
Software · 7 languages0.1 %≈1e-11 %
HDL · Q16.161 %≈1e-3 %
Verilog carries every signal in Q16.16 - about ±32768 with a step of 1.5e-5 - so its residual is set by the number format, not by the generator. See verification.
The reference model

One model, ten targets.

Every target page shows the same model, so the ten are directly comparable: an input, an error junction, a gain of 1.8, a discrete plant and an output, with the plant's output fed back into the junction. The export-verification suite calls it DPT_Feedback_Discrete - which is where the names in the file come from.

DPT_Feedback_Discrete · 5 blocks
In1 Σ + − Error × 1.8 Ctrl_Gain 0.4z⁻¹ 1 − 0.6z⁻¹ Plant Out1 the previous sample, fed back
Get started

See it run on your own model.

Download the application from the customer portal, or read the documentation first - the manual, a page for every block, and the full command reference are public.