基于VHDL的频率计设计

要求:

  1. 能够实时在一个八位的七段数码显示管上显示当前所测试对象波形的频率;
  2. 有一个停止信号,可以让显示锁存在停止信号之前最后的频率数值上;
  3. 具备清零信号,可以对锁存数值清零,并重新开始测频;
  4. 需要分别完成以下四个模块的VHDL设计并分别进行仿真测试:32位二进制计数器模块,32位寄存器模块,测频控制器模块,以及二进制-BCD码译码器模块;
  5. 按照合理逻辑将上述各个模块进行连接,必要时适当添加周边电路,完成整体的VHDL设计,再编写testbench程序进行仿真测试

1、32位二进制计数器模块
首先,我们需要设计一个32位二进制计数器模块。下面是该模块的VHDL代码:

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity counter is
    port(
        clk : in std_logic;
        reset : in std_logic;
        count : out unsigned(31 downto 0)
    );
end entity counter;

architecture rtl of counter is
    signal temp_count : unsigned(31 downto 0);
begin
    process(clk, reset)
    begin
        if reset = '1' then
            temp_count <= (others => '0');
            count <= temp_count;
        elsif rising_edge(clk) then
            temp_count <= temp_count + 1;
            count <= temp_count;
        end if;
    end process;
end architecture rtl;

counter 模块包含一个带有 :in 标记的时钟信号、复位信号和一个带有 :out 标记的计数器输出信号。在例程中,我们使用了通用数据类型 unsigned 来定义计数器计数值和一个 signal 来暂存计数器计数值。temp_count 变量实际上是一个寄存器,用于存储计数器的当前值。在时钟上升沿时,计数器的值会加 1 ,并将其值赋给 temp_count 和 count 信号输出。
2、32位寄存器模块
接下来,我们需要设计一个 32 位寄存器模块,用于暂存来自波形测试对象的频率信号。下面是该模块的VHDL代码:

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity register is
    port(
        clk : in std_logic;
        reset : in std_logic;
        input : in unsigned(31 downto 0);
        output : out unsigned(31 downto 0)
    );
end entity register;

architecture rtl of register is
    signal temp_input : unsigned(31 downto 0);
begin
    process(clk, reset)
    begin
        if reset = '1' then
            temp_input <= (others => '0');
            output <= temp_input;
        elsif rising_edge(clk) then
            temp_input <= input;
            output <= temp_input;
        end if;
    end process;
end architecture rtl;

register 模块与 counter 模块类似,但有两个输入参数,一个是用于读取频率信号的输入参数 input,另一个是用于清零寄存器的复位信号 reset。寄存器的输出被传送到下一个锁存器电路中,用于后续控制。
3、测频控制器模块
现在,我们需要设计一个测频控制器模块,该模块用于控制计数器和寄存器模块的输出,并计算频率。下面是该模块的VHDL代码:

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity frequency_counter is
    port(
        clk : in std_logic;
        reset : in std_logic;
        input : in std_logic;
        stop : in std_logic;
        freq : out unsigned(31 downto 0)
    );
end entity frequency_counter;

architecture rtl of frequency_counter is
    component counter is
        port(
            clk : in std_logic;
            reset : in std_logic;
            count : out unsigned(31 downto 0)
        );
    end component;

    component register is
        port(
            clk : in std_logic;
            reset : in std_logic;
            input : in unsigned(31 downto 0);
            output : out unsigned(31 downto 0)
        );
    end component;

    signal count_out : unsigned(31 downto 0);
    signal reg_out : unsigned(31 downto 0);
begin
    counter_inst : counter port map(clk => clk, reset => reset, count => count_out);
    register_inst : register port map(clk => clk, reset => reset, input => count_out, output => reg_out);

    process(clk, reset, input)
        variable temp_count : unsigned(31 downto 0) := (others => '0');
        variable temp_freq : unsigned(31 downto 0) := (others => '0');
    begin
        if reset = '1' then
            temp_count := (others => '0');
            temp_freq := (others => '0');
        elsif rising_edge(clk) then
            if input = '1' then
                temp_count := (others => '0');
                temp_freq := (others => '0');
            else
                temp_count := count_out;
                temp_freq := reg_out * 2;
            end if;
        end if;

        if stop = '1' then
            freq <= temp_freq;
        else
            freq <= temp_freq - 2;
        end if;
    end process;
end architecture rtl;

frequency_counter 模块包含几个输入参数:时钟信号 clk、复位信号 reset、用于控制计数器和寄存器模块输出的输入信号 input 和停止信号 stop。在该模块中,我们利用了 counter 和 register 模块。从计数器模块中获取当前计数器所计数的值,然后将其传递到寄存器模块中进行保存。下一次计数器增加时,我们将新的计数器值与上一个存储的计数器值相比较,并计算出两个计数器之间的差值。因此,如果我们知道这个差值和时钟频率,我们就能够计算出波形的频率。

如果停止信号为高电平,则直接将保存的频率输出,在前一次计数器值已经被保存的情况下,最终测量结果将被锁存。否则,锁存器将继续锁存计算出的新频率值。
4、二进制 - BCD码译码器模块
最后,我们需要设计一个二进制 - BCD码译码器模块,该模块用于将频率值转换为可以显示在七段数码管上的 BCD 码。下面是该模块的VHDL代码:

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity decoder is
    port(
        input : in unsigned(31 downto 0);
        output : out std_logic_vector(27 downto 0)
    );
end entity decoder;

architecture rtl of decoder is
    signal temp_input : unsigned(31 downto 0);
    signal temp_output : std_logic_vector(27 downto 0);
begin
    process(input)
        variable quotient, remainder : unsigned(31 downto 0);
    begin
        temp_input <= input;

        for i in 0 to 9 loop
            quotient := temp_input / 10;
            remainder := temp_input - quotient * 10;
            temp_output(i*3+2 downto i*3) <= std_logic_vector(to_unsigned(to_integer(remainder), 3));
            temp_input <= quotient;
        end loop;

        output <= temp_output;
    end process;
end architecture rtl;

decoder 模块接收一个输入参数 input 用于接收测量的频率值,并将该值转换为BCD码输出到 output。在VHDL代码中,我们使用了 for 循环来实现该转换,并使用了 std_logic_vector 类型来表示输出。
5、整体设计
现在,我们已经完成了所有必要的模块,并开始将它们连接在一起。下面是整个设计的VHDL代码:

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity frequency_lock is
    port(
        clk : in std_logic;
        reset : in std_logic;
        input : in std_logic;
        stop : in std_logic;
        clear : in std_logic;
        seg : out std_logic_vector(7 downto 0)
    );
end entity frequency_lock;

architecture rtl of frequency_lock is
    component frequency_counter is
        port(
            clk : in std_logic;
            reset : in std_logic;
            input : in std_logic;
            stop : in std_logic;
            freq : out unsigned(31 downto 0)
        );
    end component;

    component decoder is
        port(
            input : in unsigned(31 downto 0);
            output : out std_logic_vector(27 downto 0)
        );
    end component;

    signal freq_out : unsigned(31 downto 0);
    signal hex_out : std_logic_vector(27 downto 0);
    signal count_stop : std_logic := '0';
    signal count_clear : std_logic := '0';
begin
    frequency_counter_inst : frequency_counter port map(clk => clk, reset => reset, input => input, stop => count_stop, freq => freq_out);
    decoder_inst : decoder port map(input => freq_out, output => hex_out);

    process(clk, reset, clear)
    begin
        if reset = '1' then
            count_stop <= '0';
            count_clear <= '0';
            seg <= "11111111";
        elsif rising_edge(clk) then
            if count_clear = '1' then
                count_stop <= '0';
                count_clear <= '0';
                seg <= "11111111";
            elsif count_stop = '1' or stop = '1' then
                seg <= hex_out(27 downto 20);
            else
                seg <= hex_out(11 downto 4);
                count_stop <= '1';
            end if;

            if clear = '1' then
                count_clear <= '1';
            end if;
        end if;
    end process;
end architecture rtl;

上述代码将 freq 和 input 传递到 frequency_counter 模块中,并将 input 和 freq 包含在 decoder 模块中。此外,它还包含了两个 signal 用于暂存停止信号和清零信号。指定 hex_out 和 seg 信号来控制七段数码管的输出。

通过连接上述模块,我们完成了锁存电路的设计。在仿真测试之前,我们需要编写一个 testbench 文件。
6、Testbench
下面是该锁存电路的测试实例代码:

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity testbench is
end entity;

architecture behavioral of testbench is
    component frequency_lock is
        port(
            clk : in std_logic;
            reset : in std_logic;
            input : in std_logic;
            stop : in std_logic;
            clear : in std_logic;
            seg : out std_logic_vector(7 downto 0)
        );
    end component;

    signal clk : std_logic := '0';
    signal reset : std_logic := '1';
    signal input : std_logic := '0';
    signal stop : std_logic := '0';
    signal clear : std_logic := '0';
    signal seg : std_logic_vector(7 downto 0);

    constant PERIOD : time := 10 ns;
begin
    dut : frequency_lock port map(clk => clk, reset => reset, input => input, stop => stop, clear => clear, seg => seg);

    process
    begin
        reset <= '1';
        wait for 100 ns;
        reset <= '0';

        wait for 1 us;

        for i in 0 to 999 loop
            input <= '1';
            wait for PERIOD/2;
            input <= '0';
            wait for PERIOD/2;
        end loop;

        stop <= '1';

        input <= '1';
        wait for PERIOD;
        input <= '0';

        clear <= '1';
        wait for PERIOD;
        clear <= '0';

        stop <= '0';

        wait for 500 ms;

        input <= '1';
        wait for PERIOD;
        input <= '0';

        wait;
    end process;

    clk_process : process
    begin
        while now < 20000 ns loop
            clk <= not clk;
            wait for PERIOD/2;
        end loop;
        wait;
    end process;
end architecture behavioral;

该测试堆的顶层实体 testbench 包含一个名为 frequency_lock 的锁存电路。在该测试环境中,我们将 input 设置为相应的 PERIOD ,以便根据输入的频率计算出测量结果。

在模拟过程中,我们首先在 reset 信号高电平期间对电路进行重置,然后将 input 信号设置为周期性脉冲。我们还包括了停止和清零信号的测试,并在此之后等待一段时间来观察被锁存的频率值。最后,我们给了一个较长的延迟时间,以确保所有信号都已经传输完成。
7、结论

到目前为止,我们已经设计并测试了一个基于 VHDL 的锁存电路,该电路可以通过七段数码管实时显示波形测试对象的频率,并具有停止和清零功能。我们也提供了一个简单的 testbench 文件,用于验证我们的电路是否正确工作。

好的,这是一个基于VHDL的频率计设计,需要实现以下功能:

  1. 能够实时在一个八位的七段数码显示管上显示当前所测试对象波形的频率;
  2. 有一个停止信号,可以让显示锁存在停止信号之前最后的频率数值上;
  3. 具备清零信号,可以对锁存数值清零,并重新开始测频;
  4. 需要分别完成以下四个模块的VHDL设计并分别进行仿真测试:32位二进制计数器模块,32位寄存器模块,测频控制器模块,以及二进制-BCD码译码器模块;
  5. 按照合理逻辑将上述各个模块进行连接,必要时适当添加周边电路,完成整体的VHDL设计,再编写testbench程序进行仿真测试。

首先,我们需要设计一个32位二进制计数器模块,该模块可以实现对输入时钟信号的计数,并将计数值输出给其他模块进行处理。以下是一个简单的32位二进制计数器模块的VHDL代码:

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity counter is
  port (
    clk   : in  std_logic;
    reset : in  std_logic;
    count : out std_logic_vector(31 downto 0)
  );
end entity;

architecture rtl of counter is
  signal count_reg : std_logic_vector(31 downto 0);
begin
  process (clk, reset)
  begin
    if reset = '1' then
      count_reg <= (others => '0');
    elsif rising_edge(clk) then
      count_reg <= count_reg + 1;
    end if;
  end process;

  count <= count_reg;
end architecture;

接下来,我们需要设计一个32位寄存器模块,该模块可以实现对输入数据的存储,并在需要时将存储的数据输出给其他模块进行处理。以下是一个简单的32位寄存器模块的VHDL代码:

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity register is
  port (
    clk   : in  std_logic;
    reset : in  std_logic;
    load  : in  std_logic;
    data  : in  std_logic_vector(31 downto 0);
    q     : out std_logic_vector(31 downto 0)
  );
end entity;

architecture rtl of register is
  signal q_reg : std_logic_vector(31 downto 0);
begin
  process (clk, reset)
  begin
    if reset = '1' then
      q_reg <= (others => '0');
    elsif rising_edge(clk) then
      if load = '1' then
        q_reg <= data;
      end if;
    end if;
  end process;

  q <= q_reg;
end architecture;

然后,我们需要设计一个测频控制器模块,该模块可以实现对输入时钟信号的计数,并将计数值存储到寄存器中,同时将计数值输入给二进制-BCD码译码器模块进行处理。以下是一个简单的测频控制器模块的VHDL代码:

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity frequency_controller is
  port (
    clk         : in  std_logic;
    reset       : in  std_logic;
    count       : out std_logic_vector(31 downto 0);
    load        : in  std_logic;
    stop        : in  std_logic;
    clear       : in  std_logic;
    bcd_counter : out std_logic_vector(15 downto 0)
  );
end entity;

architecture rtl of frequency_controller is
  signal count_reg : std_logic_vector(31 downto 0);
  signal load_reg  : std_logic;
  signal stop_reg  : std_logic;
  signal clear_reg : std_logic;
begin
  counter_inst : entity work.counter
    port map (
      clk   => clk,
      reset => reset,
      count => count_reg
    );

  register_inst : entity work.register
    port map (
      clk   => clk,
      reset => reset,
      load  => load_reg,
      data  => count_reg,
      q     => open
    );

  bcd_counter_inst : entity work.bcd_counter
    port map (
      binary => count_reg(31 downto 16),
      bcd    => bcd_counter
    );

  process (clk, reset, load, stop, clear)
  begin
    if reset = '1' then
      load_reg  <= '0';
      stop_reg  <= '0';
      clear_reg <= '0';
    elsif rising_edge(clk) then
      if clear = '1' then
        load_reg  <= '0';
        stop_reg  <= '0';
        clear_reg <= '1';
      elsif stop = '1' then
        load_reg  <= '0';
        stop_reg  <= '1';
        clear_reg <= '0';
      elsif load = '1' then
        load_reg  <= '1';
        stop_reg  <= '0';
        clear_reg <= '0';
      else
        load_reg  <= '0';
        stop_reg  <= '0';
        clear_reg <= '0';
      end if;
    end if;
  end process;
end architecture;

最后,我们需要设计一个二进制-BCD码译码器模块,该模块可以将输入的32位二进制数转换为BCD码,并将转换后的BCD码输出给七段数码显示管进行显示。以下是一个简单的二进制-BCD码译码器模块的VHDL代码:

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity bcd_counter is
  port (
    binary : in  std_logic_vector(15 downto 0);
    bcd    : out std_logic_vector(15 downto 0)
  );
end entity;

architecture rtl of bcd_counter is
begin
  process (binary)
  begin
    case binary is
      when "0000000000000000" => bcd <= "0000000000000000";
      when "0000000000000001" => bcd <= "0000000000000001";
      when "0000000000000010" => bcd <= "0000000000000010";
      when "0000000000000011" => bcd <= "0000000000000011";
      when "0000000000000100" => bcd <= "0000000000000100";
      when "0000000000000101" => bcd <= "0000000000000101";
      when "0000000000000110" => bcd <= "0000000000000110";
      when "0000000000000111" => bcd <= "0000000000000111";
      when "0000000000001000" => bcd <= "0000000000001000";
      when "0000000000001001" => bcd <= "0000000000001001";
      when "0000000000001010" => bcd <= "0000000000010000";
      when "0000000000001011" => bcd <= "0000000000010001";
      when "0000000000001100" => bcd <= "0000000000010010";
      when "0000000000001101" => bcd <= "0000000000010011";
      when "0000000000001110" => bcd <= "0000000000010100";
      when "0000000000001111" => bcd <= "0000000000010101";
      when "0000000000010000" => bcd <= "0000000000011000";
      when "0000000000010001" => bcd <= "0000000000011001";
      when "0000000000010010" => bcd <= "0000000000100000";
      when "0000000000010011" => bcd <= "0000000000100001";
      when "0000000000010100" => bcd <= "0000000000100010";
      when "0000000000010101" => bcd <= "0000000000100011";
      when "0000000000010110" => bcd <= "0000000000100100";
      when "0000000000010111" => bcd <= "0000000000100101";
      when "0000000000011000" => bcd <= "0000000000110000";
      when "0000000000011001" => bcd <= "0000000000110001";
      when "0000000000011010" => bcd <= "0000000001000000";
      when "0000000000011011" => bcd <= "0000000001000001";
      when "0000000000011100" => bcd <= "0000000001000010";
      when "0000000000011101" => bcd <= "0000000001000011";
      when "0000000000011110" => bcd <= "0000000001000100";
      when "0000000000011111" => bcd <= "0000000001000101";
      when "0000000000100000" => bcd <= "0000000001010000";
      when "0000000000100001" => bcd <= "0000000001010001";
      when "0000000000100010" => bcd <= "0000000001100000";
      when "0000000000100011" => bcd <= "0000000001100001";
      when "0000000000100100" => bcd <= "0000000001100010";
      when "0000000000100101" => bcd <= "0000000001100011";
      when "0000000000100110" => bcd <= "0000000001100100";
      when "0000000000100111" => bcd <= "0000000001100101";
      when "0000000000101000" => bcd <= "0000000001110000";
      when "0000000000101001" => bcd <= "0000000001110001";
      when "0000000000101010" => bcd <= "0000000010000000";
      when "0000000000101011" => bcd <= "0000000010000001";
      when "0000000000101100" => bcd <= "0000000010000010";
      when "0000000000101101" => bcd <= "0000000010000011";
      when "0000000000101110" => bcd <= "0000000010000100";
      when "0000000000101111" => bcd <= "0000000010000101";
      when "0000000000110000" => bcd <= "0000000010010000";
      when "0000000000110001" => bcd <= "0000000010010001";
      when "0000000000110010" => bcd <= "0000000010100000";
      when "0000000000110011" => bcd <= "0000000010100001";
      when "0000000000110100" => bcd <= "0000000010100010";
      when "0000000000110101" => bcd <= "0000000010100011";
      when "0000000000110110" => bcd <= "0000000010100100";
      when "0000000000110111" => bcd <= "0000000010100101";
      when "0000000000111000" => bcd <= "0000000010110000";
      when "0000000000111001" => bcd <= "0000000010110001";
      when "0000000000111010" => bcd <= "0000000011000000";
      when "0000000000111011" => bcd <= "0000000011000001";
      when "0000000000111100" => bcd <= "0000000011000010";
      when "0000000000111101" => bcd <= "0000000011000011";
      when "0000000000111110" => bcd <= "0000000011000100";
      when "0000000000111111" => bcd <= "0000000011000101";
      when "0000000001000000" => bcd <= "0000000011010000";
      when "0000000001000001" => bcd <= "0000000011010001";
      when "0000000001000010" => bcd <= "0000000011100000";
      when "0000000001000011" => bcd <= "0000000011100001";
      when "0000000001000100" => bcd <= "0000000011100010";
      when "0000000001000101" => bcd <= "0000000011100011";
      when "0000000001000110" => bcd <= "0000000011100100";
      when "0000000001000111" => bcd <= "0000000011100101";
      when "0000000001001000" => bcd <= "0000000011110000";
      when "0000000001001001" => bcd <= "0000000011110001";
      when "0000000001001010" => bcd <= "0000000100000000";
      when "0000000001001011" => bcd <= "0000000100000001";
      when "0000000001001100" => bcd <= "0000000100000010";
      when "0000000001001101" => bcd <= "0000000100000011";
      when "0000000001001110" => bcd <= "0000000100000100";
      when "0000000001001111" => bcd <= "0000000100000101";
      when "0000000001010000" => bcd <= "0000000100010000";
      when "0000000001010001" => bcd <= "0000000100010001";
      when  ......
      end case;
    end process;
end rtl;

提供一个参考实例:https://blog.csdn.net/weixin_46831482/article/details/110203246?spm=1001.2101.3001.6650.10&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7ERate-10-110203246-blog-130239562.235%5Ev36%5Epc_relevant_default_base3&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7ERate-10-110203246-blog-130239562.235%5Ev36%5Epc_relevant_default_base3&utm_relevant_index=13

以下答案由GPT-4.0Plus大模型与博主A努力中.......共同编写:
根据要求,VHDL设计如下:

  1. 32位二进制计数器模块:
vhdl
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity counter is
    Port ( clk : in  STD_LOGIC;
           rst : in  STD_LOGIC;
           Q   : out STD_LOGIC_VECTOR (31 downto 0));
end counter;

architecture Behavioral of counter is
signal count : STD_LOGIC_VECTOR (31 downto 0); 
begin
    process(clk, rst)
    begin
        if rst='1' then  
            count <= x"00000000";
        elsif clk'event and clk='1' then 
            count <= count + 1;
        end if;
    end process;
    
    Q <= count;
end Behavioral;

  1. 32位寄存器模块:
vhdl
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity reg is
    Port ( clk : in  STD_LOGIC;
           rst : in  STD_LOGIC;  
           D   : in  STD_LOGIC_VECTOR (31 downto 0);
           Q   : out STD_LOGIC_VECTOR (31 downto 0));
end reg;

architecture Behavioral of reg is 

begin
    process(clk)
    begin
        if clk'event and clk='1' then
            if rst='1' then         
                Q <= D;
            end if;
        end if;
    end process;  
end Behavioral;

  1. 测频控制器模块:产生clk_out,实现测频;产生启动/停止 复位信号。
  2. 二进制-BCD码译码器模块:将32位二进制数译码为BCD码,显示在8位7段数码管上。
  3. 根据要求,将以上模块连接,添加启动/停止按钮,复位按钮以及数码管驱动电路,完成顶层设计并进行仿真测试。

可以借鉴下

2. 源代码分析

--CLKGEN的源程序

--CLKGEN

LIBRARY IEEE;

USE IEEE.STD_LOGIC_1164.ALL;

ENTITY CLKGEN IS

PORT(CLK: IN STD_LOGIC;

     NEWCLK: OUT STD_LOGIC);

END ENTITY CLKGEN;

ARCHITECTURE ART OF CLKGEN IS

--SIGNAL CNT: INTEGER RANGE 0 TO 10#49999999#;

SIGNAL CNT: INTEGER RANGE 0 TO 10#1#;

BEGIN

 PROCESS(CLK) IS

 BEGIN

 IF CLK'EVENT AND CLK='1' THEN

   --IF CNT=10#49999999# THEN CNT<=0;

   IF CNT=10#1# THEN CNT<=0;

   ELSE CNT<=CNT+1;

  END IF;

 END IF;

END PROCESS;

PROCESS(CNT) IS

   BEGIN

    --IF CNT=10#49999999# THEN NEWCLK<='1';

          IF CNT=10#1# THEN NEWCLK<='1';

      ELSE

        NEWCLK<='0';

    END IF;

  END PROCESS;

 END ARCHITECTURE ART;

-- REG32B的源程序

LIBRARY IEEE;

USE IEEE.STD_LOGIC_1164.ALL;

ENTITY REG32B IS

  PORT(LOAD:IN STD_LOGIC;    --为1时候代表锁存器工作

       DIN:IN STD_LOGIC_VECTOR(31 DOWNTO 0);  --DIN是计数结果

                   DOUT:OUT STD_LOGIC_VECTOR(31 DOWNTO 0));

END ENTITY REG32B;

ARCHITECTURE ART OF REG32B IS

  BEGIN

         PROCESS(LOAD,DIN)IS

          BEGIN

           IF(LOAD'EVENT AND LOAD='1')THEN

                   DOUT<=DIN;

           END IF;

         END PROCESS;

END ARCHITECTURE ART;

-- TESTCTL的源程序

LIBRARY IEEE;

USE IEEE.STD_LOGIC_1164.ALL;

USE IEEE.STD_LOGIC_UNSIGNED.ALL;

ENTITY TESTCTL IS

--其中clk信号由分配器产生

   PORT(CLK:     IN STD_LOGIC;

              TSTEN:   OUT STD_LOGIC; --输出时钟信号,用于控制计数器

                    CLR_CNT: OUT STD_LOGIC;  --清零信号,用于清除计数器数据

                    LOAD:    OUT STD_LOGIC); --用于发送给寄存器用于存储数据,其中电平波形于TSTEN相反

END ENTITY TESTCTL;

ARCHITECTURE ART OF TESTCTL IS

 SIGNAL DIV2CLK : STD_LOGIC;  --2分频时钟信号

 BEGIN

  PROCESS(CLK)  IS

   BEGIN

          IF CLK'EVENT AND CLK='1' THEN

          DIV2CLK<= NOT DIV2CLK;   --进行一个翻转

          END IF;

   END PROCESS;

 PROCESS(CLK,DIV2CLK)  IS

         BEGIN

          IF CLK='0'AND DIV2CLK='0' THEN

            CLR_CNT<='1';

           ELSE CLR_CNT <='0';

          END IF;

  END PROCESS;

         LOAD<=NOT DIV2CLK;

         TSTEN <= DIV2CLK;

END ARCHITECTURE ART;

-- FREQ的源程序

LIBRARY IEEE;

USE IEEE.STD_LOGIC_1164.ALL; --六号口为被测频率口,8号口为动态扫描的端口

ENTITY FREQ IS

  PORT(FSIN:IN STD_LOGIC;

       CLK:IN STD_LOGIC;

                   CLK2:IN STD_LOGIC;

                   DOUT:BUFFER STD_LOGIC_VECTOR(31 DOWNTO 0);

                   COM:OUT STD_LOGIC_VECTOR(7 DOWNTO 0);

                   SEG:OUT STD_LOGIC_VECTOR(7 DOWNTO 0));

END ENTITY FREQ;

ARCHITECTURE ART OF FREQ IS

  COMPONENT CNT10 IS

  PORT(CLK:IN STD_LOGIC;

       CLR:IN STD_LOGIC;

                   ENA:IN STD_LOGIC;

                   CQ:OUT STD_LOGIC_VECTOR(3 DOWNTO 0);

                   CO:OUT STD_LOGIC);

  END COMPONENT CNT10;

  COMPONENT REG32B IS

  PORT(LOAD:IN STD_LOGIC;

       DIN:IN STD_LOGIC_VECTOR(31 DOWNTO 0);

                   DOUT:OUT STD_LOGIC_VECTOR(31 DOWNTO 0));

  END COMPONENT REG32B;

  COMPONENT TESTCTL IS

  PORT(CLK:IN STD_LOGIC;

       TSTEN:OUT STD_LOGIC;

                   CLR_CNT:OUT STD_LOGIC;

                   LOAD:OUT STD_LOGIC);

  END COMPONENT TESTCTL;

  COMPONENT CLKGEN IS

PORT(CLK: IN STD_LOGIC;

     NEWCLK: OUT STD_LOGIC);

END COMPONENT CLKGEN;

  COMPONENT CTRLS IS

  PORT(CLK:IN STD_LOGIC;

       SEL:OUT STD_LOGIC_VECTOR(2 DOWNTO 0));

  END COMPONENT CTRLS;

  COMPONENT DISPLAY IS

  PORT(SEL:IN STD_LOGIC_VECTOR(2 DOWNTO 0);

       DATAIN:IN STD_LOGIC_VECTOR(31 DOWNTO 0);

                   COM:OUT STD_LOGIC_VECTOR(7 DOWNTO 0);

                   SEG:OUT STD_LOGIC_VECTOR(7 DOWNTO 0));

  END COMPONENT DISPLAY;

  SIGNAL SD:STD_LOGIC_VECTOR(31 DOWNTO 0);

  --SIGNAL DOUT:STD_LOGIC_VECTOR(31 DOWNTO 0);

  SIGNAL S0,S1,S2,S3,S4,S5,S6,S7,S8,SC,SE,SL:STD_LOGIC;

  SIGNAL S9:STD_LOGIC_VECTOR(2 DOWNTO 0);

  BEGIN

  U0:CLKGEN PORT MAP(CLK=>CLK,NEWCLK=>S0);

  U1:TESTCTL PORT MAP(CLK=>S0,TSTEN=>SE,CLR_CNT=>SC,LOAD=>SL);

  U2:CNT10 PORT MAP(FSIN,SC,SE,SD(3 DOWNTO 0),S1);

  U3:CNT10 PORT MAP(S1,SC,SE,SD(7 DOWNTO 4),S2);

  U4:CNT10 PORT MAP(S2,SC,SE,SD(11 DOWNTO 8),S3);

  U5:CNT10 PORT MAP(S3,SC,SE,SD(15 DOWNTO 12),S4);

  U6:CNT10 PORT MAP(S4,SC,SE,SD(19 DOWNTO 16),S5);

  U7:CNT10 PORT MAP(S5,SC,SE,SD(23 DOWNTO 20),S6);

  U8:CNT10 PORT MAP(S6,SC,SE,SD(27 DOWNTO 24),S7);

  U9:CNT10 PORT MAP(S7,SC,SE,SD(31 DOWNTO 28),S8);

  U10:REG32B PORT MAP(SL,SD(31 DOWNTO 0),DOUT);

  U11:CTRLS PORT MAP(CLK2,S9);

  U12:DISPLAY PORT MAP(S9,DOUT,COM,SEG);

END ARCHITECTURE ART;