3

I have the following CLaSH function:

toBCD :: Word8 -> Vec 3 Word8
toBCD x =
    x `div` 100 :>
    (x `div` 10) `mod` 10 :>
    x `mod` 10 :>
    Nil

Of course, the resulting HDL module is unsynthesizable because of the division by a non-power of 2 constant. So I would like to turn it into a lookup table instead, and put it into a small asynchronous ROM.

At first, I thought it would be enough to do something like

romBCD :: Word8 -> Vec 3 Word8
romBCD = asyncROM $ fmap toBCD $ iterate d256 succ 0

but the resulting VHDL still contains the formula to calculate toBCD 0, toBCD 1, etc. What I would like instead, is to get VHDL which simply contains the precomputed values in a 256x24 table.

One workaround I found was to calculate romBCD's contents via Template Haskell:

romBCD = asyncRom $(listToVecTH $ fmap toBCD [minBound .. maxBound])

but that then forces the definition of romBCD to be in a separate module than toBCD.

Cactus
  • 27,075
  • 9
  • 69
  • 149
  • 3
    You can put `toBCD` in the same module: `$( let toBCD :: Word8 -> Vec 3 Word8; toBCD = … in listToVecTH $ fmap toBCD [minBound .. ] )`. You can even make the part inside the `$( )` multiline if you indent properly. – Chai T. Rex Sep 24 '18 at 05:50
  • @ChaiT.Rex: that's a nice idea! Unfortunately, writing it like that then makes `toBCD` inaccessible from other code. – Cactus Sep 24 '18 at 05:51
  • Unfortunately, the only two solutions I know of are code duplication (in this case, copying and pasting `toBCD` as a top-level function and as a `let` function in every splice you want to use it in) and using a separate module (which you can then reexport functions from). – Chai T. Rex Sep 24 '18 at 05:55
  • 1
    @ChaiT.Rex: I am hoping that there is some CLaSH-specific way to force compilation of that ROM to a precomputed table. – Cactus Sep 24 '18 at 05:56
  • Have not studied the details, but sounds a bit like https://wiki.haskell.org/Memoization – yokto Sep 25 '18 at 07:03

0 Answers0