Register signal from applicative functor is not calculated

Hi, for the circuit:

module Debug where

import Clash.Prelude

type Input = (Bool, Bool)

func :: HiddenClockResetEnable dom => Signal dom Input -> Signal dom Int
func input = cursor
    where 
        cursor = register 0 nextCursorSignal
        nextCursorSignal = nextCursor <$> cursor <*> input

        nextCursor :: Int -> Input -> Int
        nextCursor cur (push, pop) = 
            if push 
            then cur
            else cur + 1


topEntity :: Clock System -> Reset System -> Enable System -> 
    Signal System Input -> Signal System Int
topEntity clk rst en input = exposeClockResetEnable (func input) clk rst en

No output is calculated, not even the default value of 0, as observed in the waveform:

However, when I change the nextCursor to not depend on cur it works.
For example like this:

nextCursor :: Int -> Input -> Int
nextCursor cur (push, pop) = 42

or something like

nextCursor :: Int -> Input -> Int
nextCursor cur (push, pop) = 
            if push 
            then 10
            else 20

Any ideas what might be going on here? Could it be being optimized away?

I am generating verilog and testing by writing a custom testbench as follows:

`timescale 1us/1ns
module testbench;
    reg clk;
    reg rst;
    reg en;

    reg push; 
    reg pop;
    wire signed [63:0] cursor;

    topEntity monitor (
                        clk, rst, en,
                        push, pop, cursor
                       );

    always begin
        #1 clk = ~clk;
    end

    initial begin
        clk = 1;
        rst = 0;
        en = 1;
        
        $printtimescale(testbench);
        $dumpvars(0, testbench);

        #10;
        @(posedge clk);
        push = 1;
        pop = 0;
        @(posedge clk);
        push = 0; 
        pop = 0;

        #10;
        @(posedge clk);
        push = 1;
        pop = 1;
        @(posedge clk);
        push = 0; 
        pop = 0;

        #10;
        @(posedge clk);
        push = 0;
        pop = 0;
        @(posedge clk);
        push = 0; 
        pop = 0;

        #10;
        @(posedge clk);
        push = 0;
        pop = 1;
        @(posedge clk);
        push = 0; 
        pop = 0;

        #40;
        $finish; 
    end

endmodule


Following is the generated verilog for reference:

/* AUTOMATICALLY GENERATED VERILOG-2001 SOURCE CODE.
** GENERATED BY CLASH 1.8.2. DO NOT MODIFY.
*/
`default_nettype none
`timescale 100fs/100fs
module topEntity
    ( // Inputs
      input wire  clk // clock
    , input wire  rst // reset
    , input wire  en // enable
    , input wire  input_0
    , input wire  input_1

      // Outputs
    , output wire signed [63:0] cursor
    );
  // debug.hs:7:1-72
  wire signed [63:0] c$cursor_case_alt;
  // debug.hs:7:1-72
  reg signed [63:0] cursor_1 = (64'sd0);
  // debug.hs:7:1-72
  wire  push;
  // debug.hs:7:1-72
  wire signed [63:0] x;
  wire [1:0] r_input;

  assign r_input = {input_0,   input_1};

  assign c$cursor_case_alt = push ? cursor_1 : ((x + 64'sd1));

  // register begin
  always @(posedge clk or  posedge  rst) begin : cursor_1_register
    if ( rst) begin
      cursor_1 <= (64'sd0);
    end else if (en) begin
      cursor_1 <= c$cursor_case_alt;
    end
  end
  // register end

  assign push = r_input[1:1];

  assign x = cursor_1;

  assign cursor = cursor_1;


endmodule


I managed to make it work by setting the inputs to default values in the beginning and setting a reset to true for a cycle before providing the actual initial values.

Because the input push is undefined, the contents of the register become undefined. And undefined + 1 is still undefined, so only a reset will get you back into defined territory.

If you never have the inputs undefined while the clock is running, you won’t need an initial reset, although it’s pretty common to always reset your circuit at the beginning regardless.

2 Likes