VHDL-非规则时钟模式生成

VHDL-非规则时钟模式生成,vhdl,clock,Vhdl,Clock,我的问题相对简单:在VHDL中,是否有可能在不使用进程和关键字后的的情况下生成具有特定非规则模式的时钟 换句话说,如果我有一个进程生成这样一个时钟: process(Start) begin if Start = '0' then clock <= '0'; else if Start = '1' then clock <= '0', '1' after 25 ns

我的问题相对简单:在VHDL中,是否有可能在不使用进程和关键字
后的
的情况下生成具有特定非规则模式的时钟

换句话说,如果我有一个进程生成这样一个时钟:

process(Start)
    begin   
        if Start = '0' then 
            clock <= '0';
        else if Start = '1' then
            clock <= '0',
            '1' after 25 ns,
            '0' after 35 ns,
            '1' after 50 ns,
            '0' after 75 ns,
            '1' after 105 ns,
            ...
end process;
过程(开始)
开始
如果Start='0',则

时钟好,您可以尝试使用其他关键字在进程块内部生成延迟,如等待循环。这是一个例子:

clock_gen: process
   constant duty_cycle : real := 0.40
   constant period : time := 100 ns ;
   constant clk_high : time := duty_cycle * period ;
begin
   loop
      clk <= '0';
      wait for period - clk_high; -- clock low time
      clk <= '1';
          wait for clk_high; -- clock high time
      end loop;
    end process;
end behavioral;
clock\u gen:进程
恒定占空比:实际值:=0.40
恒定周期:时间:=100ns;
恒定clk_高:时间:=占空比*周期;
开始
环

clk在没有进程的情况下创建时钟没有任何意义(结构化VHDL不提供任何类型的同步),但是您可以通过将正确的逻辑应用于测试台提供的一些常规时钟信号来模拟特殊的时钟模式

例如考虑输入一个2个时钟(一个起始于0个,另一个在1个),这将给您实现2状态机的可能性,根据源时钟的周期性将它想象成计数器。

您还可以有两个时钟源,其中第二个时钟的周期是第一个时钟的两倍,以获得2^2状态机,在这种情况下,您可以在低电平(0)下自由启动两个时钟


通过这种方式,您可以实现所需的模式,而无需使用任何进程(不使用行为VHDL)。

想象一个计数器,它计算5 ns周期时钟,时钟的初始值为“0”,计数器的初始值为(其他=>“0”)。当计数=5(25纳秒)、7(35纳秒)、10(50纳秒)时,组合信号切换变为真('1'),。。。将“其他”切换设置为false(“0”)。如果时钟连续,则选择一个计数以将计数恢复为所有“0”。切换信号是D触发器(时钟为输出)的启用信号,其QD未连接到高速时钟(从测试台外部提供)的D运行。计数的大小最后以5 ns的增量确定

我们将计数比较值向下调整1,以补偿d触发器,其结构如下:

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

entity counter is           -- counts 0 to 31
    port (
        clk:    in  std_logic;
        count:  out std_logic_vector (4 downto 0);
        zero:   out std_logic
    );
end entity;

architecture foo of counter is
    signal cnt:     unsigned (count'range) := (others => '0'); -- start at zero
    constant period:    integer := 31;  -- 32 is the period of the the sequence
begin
    process (clk)
    begin
        if rising_edge (clk) then
            if cnt < period then
                cnt <= cnt + 1;
            else
                cnt <= (others => '0');
            end if;
        end if;
    end process;

    count <= std_logic_vector(cnt);

    zero <= '1' when cnt = 0 else  
            '0';
end architecture;

library ieee;
use ieee.std_logic_1164.all;

entity d_flip_flop is   -- has enable
    port (
        resetn: in  std_logic;
        clk:    in  std_logic;
        en:     in  std_logic;
        d:      in  std_logic;
        q:      out std_logic
    );
end entity;

architecture foo of d_flip_flop is
    signal qn: std_logic := '1';
begin
    process (resetn, clk)
    begin
        if resetn = '0' then
            qn <= '1';
        elsif rising_edge (clk) and en = '1' then
            qn <= not d;
        end if;
    end process;
    q <= not qn;
end architecture;

library ieee;
use ieee.std_logic_1164.all;

entity inv is
    port (
        a:  in  std_logic;
        o:  out std_logic
    );
end entity;

architecture foo of inv is
begin
    o <= not a;
end architecture;


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

entity toggle_pla_rom is
    port (
        count:  in  std_logic_vector (4 downto 0);
        toggle: out std_logic
    );
end entity;

architecture foo of toggle_pla_rom is
    type rom_array is array (0 to 31) of std_logic;   -- fully constrained
    constant rom: rom_array := ( 4 | 6 | 9 | 14 | 20 => '1', others => '0');
begin
    toggle <= rom(to_integer(unsigned(count)));
end architecture;

library ieee;
use ieee.std_logic_1164.all;

entity clock_gen is
    port (
        clk:    in  std_logic;
        clock:  out std_logic
    );
end entity;

architecture foo of clock_gen is
    signal toggle:  std_logic;
    signal resetn:  std_logic;
    signal din:     std_logic;
    signal count:   std_logic_vector (4 downto 0);
    signal q:       std_logic;
    signal nq:      std_logic;
    signal zero:    std_logic;
begin
CNTR:
    entity work.counter
        port map (
            clk => clk,
            count => count,
            zero => zero
        );

DIN_INV:
    entity work.inv
        port map (
            a => q,
            o => nq
        );

ZERO_INV:
    entity work.inv
        port map (
            a => zero,
            o => resetn
        );
DFF:
    entity work.d_flip_flop
        port map (
            resetn => resetn,
            clk => clk,
            en => toggle,
            d  => nq,
            q => q
        );

TOGGLE_LUT:
    entity work. toggle_pla_rom
        port map (
            count => count,
            toggle => toggle
        );

    clock <= q;

end architecture;

library ieee;
use ieee.std_logic_1164.all;

entity clock_gen_tb is
end entity;

architecture foo of clock_gen_tb is
    signal clk:     std_logic := '1';  -- clk has 5 ns period
    signal clock:   std_logic;
begin
CLOCKGEN:
    entity work.clock_gen
        port map (
            clk => clk,
            clock => clock
        );

CLKGEN:
    process
    begin
        wait for 2.5 ns;
        clk <= not clk;
        if now > 300 ns then
            wait;
        end if;
    end process;

MONITOR:
    process 
    begin
        wait for 0 ns;
        wait until clock'event;
        report "clock = " & std_logic'image(clock);
    end process;
end architecture;
ieee库;
使用ieee.std_logic_1164.all;
使用ieee.numeric_std.all;
实体计数器为--计数0到31
港口(
clk:标准逻辑中;
计数:输出标准逻辑向量(4到0);
零:输出标准逻辑
);
终端实体;
计数器的结构是
信号cnt:无符号(计数范围):=(其他=>'0');--从零开始
常量周期:整数:=31;--32是序列的周期
开始
过程(clk)
开始
如果上升沿(clk),则
如果cnt<周期,则
cnt零,
o=>resetn
);
DFF:
实体工作d_触发器
港口地图(
resetn=>resetn,
时钟=>clk,
en=>切换,
d=>nq,
q=>q
);
切换逻辑单元:
实体工作。切换pla rom
港口地图(
计数=>计数,
切换=>切换
);
时钟时钟,
时钟=>时钟
);
克莱根:
过程
开始
等待2.5ns;
时钟300纳秒
等待
如果结束;
结束过程;
监视器:
过程
开始
等待0ns;
等到午夜事件;
报告“时钟=”&std_逻辑”图像(时钟);
结束过程;
终端架构;
用于确定发生切换的计数值的查找表可以替换为和/或等,以获得真正的基本体级别描述

计数器包裹,很容易治愈(例如,它可以停止)。因为您没有指定任何进一步的边缘事件,所以它是根据您指定的边缘事件数量所需的大小定制的。计数器的大小和事件的数量可以按比例增加

运行时,clock_gen_tb测试台会报告时钟事件并显示它符合您的规范:

对数时钟。vhdl:188:9:@0ms:(报告注释):时钟='0' 对数时钟。vhdl:188:9:@25ns:(报告注释):时钟='1' 对数时钟。vhdl:188:9:@35ns:(报告注释):时钟='0' 对数时钟。vhdl:188:9:@50ns:(报告注释):时钟='1' 对数时钟。vhdl:188:9:@75ns:(报告注释):时钟='0' 对数时钟。vhdl:188:9:@105ns:(报告注释):时钟='1' 对数时钟。vhdl:188:9:@160ns:(报告注释):时钟='0' 对数时钟。vhdl:188:9:@185ns:(报告注释):时钟='1' 对数时钟。vhdl:188:9:@195ns:(报告注释):时钟='0' 对数时钟。vhdl:188:9:@210ns:(报告注释):时钟='1' 对数时钟。vhdl:188:9:@235ns:(报告注释):时钟='0' 对数时钟。vhdl:188:9:@265ns:(报告注释):时钟='1'

前6次符合您的规格

波形显示器显示计数、切换、零(代表触发器复位)和时钟:


本例指出的一点是,所有能够进行模拟的VHDL结构模型都是以行为方式描述的。

考虑一个计数器、一个时钟(最常见的分母似乎是5纳秒,注意,没有显示整个模式),和门产生低波特率或高波特率,通过时钟触发器组合馈电,以生成
时钟
时钟
切换事件。“高速”时钟可能来自测试台或模拟器本身。@user1155120谢谢您的回答。我想我明白你的意思了,但是我如何设置计数器来计算不同的时间间隔呢?我需要多个计数器吗?您能更好地解释一下我应该如何处理计数器的输出吗?想象一下,一个计数器计算5 ns周期时钟,并且
时钟的初始值为'0',计数器的初始值为(其他=>'0')。当计数=5(25纳秒)、7(35纳秒)、10(50纳秒)a组合时