Haskell 堪萨斯熔岩中用信号索引矩阵矩阵

Haskell 堪萨斯熔岩中用信号索引矩阵矩阵,haskell,vhdl,fpga,lava,Haskell,Vhdl,Fpga,Lava,我正在尝试实现时间多路复用,以驱动具有4位数字的7段显示器:该设备有7个数据脚和4个阳极,因此,如果要显示四个不同的数字,必须先将阳极设置为0001,然后将数据脚设置为段;然后在一段时间后,将阳极设置为0010,并更新数据;等等 我正试图在堪萨斯州实施这一计划。但是,Xilinx编译器拒绝生成带有类型错误的VHDL(查看生成的代码,我认为这是正确的) 首先,我的Lava代码:它基本上实现了序列的信号[0,1,2,3,0,…],然后使用运算符从语言.KansasLava.Signal索引到矩阵的矩

我正在尝试实现时间多路复用,以驱动具有4位数字的7段显示器:该设备有7个数据脚和4个阳极,因此,如果要显示四个不同的数字,必须先将阳极设置为
0001
,然后将数据脚设置为段;然后在一段时间后,将阳极设置为
0010
,并更新数据;等等

我正试图在堪萨斯州实施这一计划。但是,Xilinx编译器拒绝生成带有类型错误的VHDL(查看生成的代码,我认为这是正确的)

首先,我的Lava代码:它基本上实现了序列的信号
[0,1,2,3,0,…]
,然后使用
运算符从
语言.KansasLava.Signal
索引到矩阵的矩阵参数。阳极值是通过在每个时间步向左旋转
0001
生成的

{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE DataKinds #-}
import Language.KansasLava
import Hardware.KansasLava.Boards.Papilio.LogicStart -- from http://github.com/gergoerdi/kansas-lava-papilio
import Data.Sized.Matrix
import Data.Sized.Unsigned as Unsigned
import Data.Bits

driveSS :: forall clk sig n. (Clock clk, sig ~ Signal clk, Size n, Rep n, Num n, Integral n) => Matrix n (Matrix X7 (sig Bool)) -> SevenSeg clk ActiveLow n
driveSS segss = SevenSeg (fmap bitNot anodes) segs high
  where
    clkAnode :: sig Bool
    clkAnode = divideClk (Witness :: Witness X8)

    selector :: sig n
    selector = counter clkAnode

    segss' :: sig (Matrix n (Matrix X7 Bool))
    segss' = pack . fmap pack $ segss

    segs :: Matrix X7 (sig Bool)
    segs = unpack $ segss' .!. selector

    anodes :: Matrix n (sig Bool)
    anodes = rotatorL clkAnode

test_sseg :: Fabric ()
test_sseg = do
    sw <- switches
    let sw' = cropAt sw 1
    sseg $ driveSS $ matrix [sw', zero, zero, zero]
  where
    zero = matrix $ replicate 7 low

divideClk :: forall c sig ix. (Clock c, sig ~ Signal c, Size ix) => Witness ix -> sig Bool
divideClk _ = counter high .==. (0 :: sig (Unsigned ix))

counter :: (Rep a, Num a, Clock c, sig ~ Signal c) => sig Bool -> sig a
counter inc = loop
  where
    reg = register 0 loop
    loop = mux inc (reg, reg + 1)

rotatorL :: (Clock c, sig ~ Signal c, Size ix, Integral ix) => sig Bool -> Matrix ix (sig Bool)
rotatorL step = fromUnsigned loop
  where
    reg = register 1 loop
    loop = mux step (reg, rotateL reg 1)

fromUnsigned :: (sig ~ Signal c, Size ix) => sig (Unsigned ix) -> Matrix ix (sig Bool)
fromUnsigned = unpack . coerce Unsigned.toMatrix

main :: IO ()
main = do
    writeVhdlPrelude "lava-prelude.vhdl"
    kleg <- reifyFabric $ do
        board_init
        test_sseg
    writeVhdlCircuit "hello" "hello.vhdl" kleg
    writeUCF "hello.ucf" kleg
hello.vhdl
中的相关行包括:

type sig_24_o0_type is array (7 downto 0) of std_logic_vector(0 downto 0);
signal sig_24_o0 : sig_24_o0_type;

signal sig_25_o0 : std_logic_vector(1 downto 0);

type sig_28_o0_type is array (3 downto 0) of std_logic_vector(6 downto 0);
signal sig_28_o0 : sig_28_o0_type;

sig_24_o0 <= sig_28_o0(to_integer(unsigned(sig_25_o0)));
type sig_24_o0_type是标准逻辑向量(0到0)的数组(7到0);
信号sig_24_o0:sig_24_o0型;
信号sig_25_o0:std_逻辑_向量(1到0);
类型sig_28_o0_类型是标准逻辑_向量(6向下到0)的数组(3向下到0);
信号sig_28_o0:sig_28_o0型;

sig_24_o0我最终通过每根导线多路复用而不是整个总线多路复用来解决这个问题:

segss' :: Matrix X7 (Matrix n (sig Bool))
segss' = columns . joinRows $ segss

segs :: Matrix X7 (sig Bool)
segs = fmap (nary selector) segss'
使用helper函数

nary :: forall a clk sig n. (Clock clk, sig ~ Signal clk, Rep a, Size n, Rep n) => sig n -> Matrix n (sig a) -> sig a
nary sel inps = pack inps .!. sel

由此生成的VHDL编译得很好;尽管我不知道这是否会使电路变得更复杂(甚至更简单)。

堪萨斯熔岩公司的维护人员安迪·吉尔在私人邮件中告诉我,这确实看起来像熔岩本身的一个缺陷。我接受我的回答,认为这是一个有效的解决办法。
nary :: forall a clk sig n. (Clock clk, sig ~ Signal clk, Rep a, Size n, Rep n) => sig n -> Matrix n (sig a) -> sig a
nary sel inps = pack inps .!. sel