3

我有一个非常简单的同步电路,应该让 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 个周期;否则我必须运行模拟器很长时间才能看到第一个过渡。

4

1 回答 1

1

一种解决方案是在 FPGA 逻辑中创建上电复位序列。这可以实现为一个计数器,只要计数器值低于某个常数,就可以断言复位。当计数器超过常数值时,解除复位。

于 2018-08-07T19:09:43.313 回答