clash-lang / clash-compiler

Haskell to VHDL/Verilog/SystemVerilog compiler
https://clash-lang.org/
Other
1.4k stars 147 forks source link

`Clash.Sized.Vector.replicate` in SystemVerilog #1791

Open IchiroKawashima opened 3 years ago

IchiroKawashima commented 3 years ago

Hello,

I found clash translates b = replicate d4 a into a kind of code like the following:

logic [1:0] a;
logic [1:0] b [0:3]; // unpacked array

assign y = '{4 {x}}; 

However, the generated SystemVerilog code didn't work in Vivado 2019.2 simulator. The value of b was not {a, a, a, a} but {0, 0, 0, a}.

The assignment pattern for unpacked array seems to be allowed if the replicated value is a constant value like, assign y = '{4{2'b01}}.

I guess assigning values with generate for loop or Using packed arrays instead of unpacked arrays helps to fix the issue.

christiaanb commented 3 years ago

It works correctly in ModelSim. For:

module Replicate where

import Clash.Prelude
import Clash.Explicit.Testbench

topEntity :: Unsigned 4 -> Vec 4 (Unsigned 4)
topEntity = replicate d4
{-# NOINLINE topEntity #-}

testBench :: Signal System Bool
testBench = done
  where
    testInput      = pure 5
    expectedOutput = outputVerifier' clk rst ((5:>5:>5:>5:>Nil):>Nil)
    done           = expectedOutput (topEntity <$> testInput)
    clk            = tbSystemClockGen (not <$> done)
    rst            = systemResetGen

clash --systemverilog Replicate.hs gives me the following topEntity.sv:

/* AUTOMATICALLY GENERATED SYSTEMVERILOG-2005 SOURCE CODE.
** GENERATED BY CLASH 1.5.0. DO NOT MODIFY.
*/
`timescale 100fs/100fs
module topEntity
    ( // Inputs
      input logic [3:0] c$arg

      // Outputs
    , output logic [3:0] result_0
    , output logic [3:0] result_1
    , output logic [3:0] result_2
    , output logic [3:0] result_3
    );
  Replicate_topEntity_types::array_of_4_logic_vector_4 result;

  assign result = '{4 {c$arg}};

  assign result_0 = result[0];

  assign result_1 = result[1];

  assign result_2 = result[2];

  assign result_3 = result[3];

endmodule

and when I simulate the corresponding testBench I see this in the wave viewer: image

So ModelSim handles the variable in the replicate value position just fine.

I guess Clash will have to generate different code for replicate when compiling for Xilinx. We already support generating different HDL for Xilinx when using the -fclash-hdlsyn Xilinx flag, however, the current blackbox template for replicate doesn't yet generate different HDL when compiling for Xilinx.