It looks like GHC automatically inlines combinational logic. The inlining leads to Clash compiling what should be logic gates as muxes.
What follows is an example of code with both the current and desired behaviours:
import Data.Bool
import qualified GHC.Magic
-- Custom Boolean operator suggested by Christiaan as a workaround.
(&!) = GHC.Magic.noinline (&&)
-- Sample circuit will return the normally generated result, alongside the fixed/noinlined version
topEntity :: Bool -> Bool -> (Bool, Bool)
topEntity a b = (a && b, a &! b)
and the resulting circuit in Verilog:
/* AUTOMATICALLY GENERATED VERILOG-2001 SOURCE CODE.
** GENERATED BY CLASH 1.5.0. DO NOT MODIFY.
*/
`timescale 100fs/100fs
module topEntity
( // Inputs
input a
, input b
// Outputs
, output wire result_0
, output wire result_1
);
wire c$app_arg;
wire [1:0] result;
assign c$app_arg = a ? b : 1'b0;
assign result = {c$app_arg, a & b};
assign result_0 = result[1:1];
assign result_1 = result[0:0];
endmodule
It looks like GHC automatically inlines combinational logic. The inlining leads to Clash compiling what should be logic gates as muxes.
What follows is an example of code with both the current and desired behaviours:
and the resulting circuit in Verilog: