Hi, I ran into a weird case while trying to create a FIFO queue. Simulation in Haskell works correctly, but when testing the generated Verilog code with testbench I get the nonsensical outputs. I have tried to isolate one of those cases with a simple example here. Any insight would be highly appreciated
So, for a simple mealy machine like below:
module Rough where
import Clash.Prelude
type State = Vec 6 Int
type Input = Int
type Output = State
fx :: State -> Input -> (State, Output)
fx state input = (nextState, nextState)
where
nextState = input +>> state
machine :: HiddenClockResetEnable dom => Signal dom Input -> Signal dom Output
machine = mealy fx (repeat 0)
topEntity :: Clock System -> Reset System -> Enable System
-> Signal System Input -> Signal System Output
topEntity = exposeClockResetEnable machine
--- TEST --
inputs :: HiddenClockResetEnable dom => Signal dom Input
inputs = fromList [0,0,1,2,3,4,5,6,7,8]
outputs = sampleN @System 10 (machine inputs)
The outputs
from the test gives me the result as expected. However, generating a Verilog and simulating it in a testbench gives a weird output.
Here is the generated Verilog code.
/* 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 eta // clock
, input wire eta1 // reset
, input wire eta2 // enable
, input wire signed [63:0] c$arg
// Outputs
, output wire signed [63:0] result_0
, output wire signed [63:0] result_1
, output wire signed [63:0] result_2
, output wire signed [63:0] result_3
, output wire signed [63:0] result_4
, output wire signed [63:0] result_5
);
// rough.hs:14:1-78
reg [383:0] c$ds_app_arg = {64'sd0, 64'sd0, 64'sd0, 64'sd0, 64'sd0, 64'sd0};
wire [767:0] result_12;
// rough.hs:10:1-2
wire [383:0] nextState;
wire [447:0] nextState_projection;
wire [383:0] result;
// register begin
always @(posedge eta or posedge eta1) begin : c$ds_app_arg_register
if ( eta1) begin
c$ds_app_arg <= {64'sd0, 64'sd0, 64'sd0, 64'sd0, 64'sd0, 64'sd0};
end else if (eta2) begin
c$ds_app_arg <= result_12[767:384];
end
end
// register end
assign result = result_12[383:0];
assign result_12 = {nextState, nextState};
assign nextState_projection = ({c$arg,c$ds_app_arg});
assign nextState = nextState_projection[447:64];
assign result_0 = $signed(result[383:320]);
assign result_1 = $signed(result[319:256]);
assign result_2 = $signed(result[255:192]);
assign result_3 = $signed(result[191:128]);
assign result_4 = $signed(result[127:64]);
assign result_5 = $signed(result[63:0]);
endmodule
Here is my Verilog testbench.
`timescale 1us/1ns
module testbench;
reg clk;
reg rst;
reg en;
reg signed [63:0] data;
wire signed [63:0] mem0;
wire signed [63:0] mem1;
wire signed [63:0] mem2;
wire signed [63:0] mem3;
wire signed [63:0] mem4;
wire signed [63:0] mem5;
topEntity monitor (clk, rst, en,
data,
mem0, mem1, mem2, mem3, mem4, mem5
);
always begin
#1 clk = ~clk;
end
initial begin
clk = 0;
rst = 0;
en = 1;
$printtimescale(testbench);
$dumpvars(0, testbench);
#1;
data = 1;
#2;
data = 2;
#2;
data = 3;
#2;
data = 4;
#2
data = 5;
#2
data = 6;
#2
data = 7;
#2
data = 8;
#2;
$finish;
end
endmodule
It gives me the following output.
This output doesn’t make sense to me as the newest value of data gets propagated 2 steps forward instead of being shifted one by one.
Furthermore when I disable the enable signal I get the following result:
Here, the first output gets updated even with enable = false, suggesting something might be going wrong.
At first glance, I don’t see any obvious mistake in the generated code.
Any ideas?