我有一个非常简单的同步电路,应该使LED闪烁:
module Blinker where
import Clash.Prelude
import Data.Word
{-# NOINLINE topEntity #-}
{-# ANN topEntity
(Synthesize
{ t_name = "blinkerTop"
, t_inputs = [PortName "CLK_32MHZ", PortName "RESET"]
, t_output = PortName "LED"
}) #-}
topEntity
:: Clock System Source
-> Reset System Asynchronous
-> Signal System Bit
topEntity = exposeClockReset $ tickTock 32000000
tickTock :: (HiddenClockReset domain gated synchronous) => Word32 -> Signal domain Bit
tickTock n = mealy step (False, 0) (pure ())
where
step (s, k) () =
let k' = k + 1
finished = k' == n
s' = if finished then not s else s
k'' = if finished then 0 else k'
in ((s', k''), if s' then high else low)
由于当我将其上传到真实的FPGA板上时它不起作用,所以我想我可以在Xilinx的模拟器中通过以下测试平台进行尝试:
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
ENTITY testbench IS
END testbench;
ARCHITECTURE behavior OF testbench IS
COMPONENT blinkerTop
PORT(
CLK_32MHZ : IN std_logic;
RESET : IN std_logic;
LED : OUT std_logic
);
END COMPONENT;
signal CLK_32MHZ : std_logic := '0';
signal RESET : std_logic := '0';
signal LED : std_logic;
constant CLK_32MHZ_period : time := 31.2 ns;
BEGIN
uut: blinkerTop PORT MAP (
CLK_32MHZ => CLK_32MHZ,
RESET => RESET,
LED => LED
);
CLK_32MHZ_process :process
begin
CLK_32MHZ <= '0';
wait for CLK_32MHZ_period/2;
CLK_32MHZ <= '1';
wait for CLK_32MHZ_period/2;
end process;
END;
在模拟器中,这符合现实生活中FPGA板的行为:LED
信号保持低电平。
我查看了生成的VHDL,它是这样的:
-- Automatically generated VHDL-93
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
use IEEE.MATH_REAL.ALL;
use std.textio.all;
use work.all;
use work.blinkertop_types.all;
entity blinkerTop is
port(-- clock
CLK_32MHZ : in std_logic;
-- asynchronous reset: active high
RESET : in std_logic;
LED : out std_logic);
end;
architecture structural of blinkerTop is
signal \#tup_app_arg\ : unsigned(31 downto 0);
signal \s'\ : boolean;
signal \#s'_case_alt\ : boolean;
signal s : boolean;
signal \#finished_case_alt\ : boolean;
signal \#k'_case_alt\ : unsigned(31 downto 0);
signal ds : blinkertop_types.tup2;
signal \#finished_app_arg\ : signed(63 downto 0);
signal x : unsigned(63 downto 0);
signal x_0 : blinkertop_types.tup2;
signal \x#\ : unsigned(63 downto 0);
signal k : unsigned(31 downto 0);
signal \#w\ : unsigned(63 downto 0);
begin
LED <= '1' when \s'\ else
'0';
\#tup_app_arg\ <= resize(to_unsigned(0,64),32) when \#finished_case_alt\ else
\#k'_case_alt\;
\s'\ <= \#s'_case_alt\ when \#finished_case_alt\ else
s;
\#s'_case_alt\ <= false when s else
true;
s <= ds.tup2_sel0;
\#finished_case_alt\ <= tagToEnum(\#finished_app_arg\);
\#w\ <= (\x#\ + to_unsigned(1,64));
\#k'_case_alt\ <= resize((resize(\#w\(31 downto 0),64)),32);
-- register begin
blinkertop_register : process(CLK_32MHZ,RESET)
begin
if RESET = '1' then
ds <= ( tup2_sel0 => false, tup2_sel1 => resize(to_unsigned(0,64),32) )
-- pragma translate_off
after 1 ps
-- pragma translate_on
;
elsif rising_edge(CLK_32MHZ) then
ds <= x_0
-- pragma translate_off
after 1 ps
-- pragma translate_on
;
end if;
end process;
-- register end
\#finished_app_arg\ <= to_signed(1,64) when x = to_unsigned(32000000,64) else to_signed(0,64);
x <= resize(\#k'_case_alt\,64);
x_0 <= ( tup2_sel0 => \s'\
, tup2_sel1 => \#tup_app_arg\ );
\x#\ <= resize(k,64);
k <= ds.tup2_sel1;
end;
我注意到内部状态未初始化,仅在重置时分配。因此,这给了我一个向测试台添加重置过程的想法:
stim_proc: process
begin
RESET <= '1';
wait for 100 ns;
RESET <= '0';
wait;
end process;
进行了此更改之后,我看到LED
在模拟器中开始闪烁。 [*]
负责模拟;但是我如何确保真实板上有类似的复位信号?
[*]当然,对于仿真,我将频率从32,000,000个周期增加到仅100个周期;否则,我必须运行模拟器一段时间才能看到第一个过渡。
答案 0 :(得分:1)
一种解决方案是在FPGA逻辑中创建上电复位序列。这可以实现为计数器,并且只要计数器值低于某个常数,就可以断言复位。当计数器超过恒定值时,取消置位复位。