初始化寄存器

时间:2018-08-01 14:10:36

标签: haskell initialization vhdl fpga clash

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

1 个答案:

答案 0 :(得分:1)

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