Ich versuche, Zeitmultiplexing zu implementieren, um eine 7-Segment-Anzeige mit 4 Ziffern zu fahren: Das Gerät verfügt über 7 Datenbeine und 4 Anoden, also wenn Sie vier anzeigen möchten verschiedene Ziffern, müssen Sie zuerst die Anoden auf 0001
setzen und die Datenbeine zu Ihren Segmenten; Setzen Sie nach einer Weile die Anoden auf 0010
und aktualisieren Sie die Datenbeine; und so weiter.Indizieren einer Matrix von Matrizen mit einem Signal in Kansas Lava
Ich versuche, dies in Kansas Lava zu implementieren. Der Xilinx-Compiler weist den generierten VHDL jedoch mit einem Typfehler zurück (und ich betrachte den generierten Code, denke ich, dass er richtig ist).
zuerst, meine Lava-Code: Es implementiert im Grunde genommen ein Signal der Sequenz [0, 1, 2, 3, 0, ...]
, verwendet den Operator von .!.
Language.KansasLava.Signal
zum Indizieren in die Matrix-of-Matrizen-Parameter. Der Anodenwert wird erzeugt, indem bei jedem Zeitschritt nach links 0001
gedreht wird.
{-# 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
Also, wenn ich versuche, das erzeugte VHDL zu kompilieren, erhalte ich diese Fehlermeldung:
ERROR:HDLParsers:800 - "/home/cactus/prog/lava/hello/src/hello.vhdl" Line 85. Type of sig_24_o0 is incompatible with type of sig_28_o0.
Die entsprechenden Zeilen aus hello.vhdl
sind:
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)));
Die Art der sig_24_o0
scheint falsch ; Ich denke, es sollte entweder array (6 downto 0) of std_logic_vector(0 downto 0)
oder std_logic_vector(6 downto 0)
sein, aber ich weiß nicht, was Lava diese std_logic_vector(0 downto 0)
verwendet.
Andy Gill, Betreuer von Kansas Lava, hat mir per Mail mitgeteilt, dass dies tatsächlich wie ein Insekt in Lava selbst aussieht. Ich akzeptiere diese Antwort als eine effektive Umgehungslösung. – Cactus