Triggers 基于触发信号的单时钟周期脉冲

Triggers 基于触发信号的单时钟周期脉冲,triggers,vhdl,clock,pulse,Triggers,Vhdl,Clock,Pulse,我正在制作一个midi接口。UART工作正常,它向控制单元发送8位消息和标志。当标志变高时,该装置将把信息存储在寄存器中,并使clr_标志变高,以便再次将UART标志设置为低。问题是我不能使这个clr_标志长一个周期。我需要它是一个周期长,因为这个信号还控制一个状态机,它指示正在存储什么类型的消息,例如note\u on->key\u note->velocity 我这里的问题是,在这种情况下,信号标志如何仅触发一个时钟周期的脉冲?我现在所做的几乎是在一个时钟周期内产生一个脉冲,但我做了两次,因

我正在制作一个midi接口。UART工作正常,它向控制单元发送8位消息和标志。当标志变高时,该装置将把信息存储在寄存器中,并使clr_标志变高,以便再次将UART标志设置为低。问题是我不能使这个clr_标志长一个周期。我需要它是一个周期长,因为这个信号还控制一个状态机,它指示正在存储什么类型的消息,例如note\u on->key\u note->velocity

我这里的问题是,在这种情况下,信号标志如何仅触发一个时钟周期的脉冲?我现在所做的几乎是在一个时钟周期内产生一个脉冲,但我做了两次,因为标志还没有变成0。我尝试了很多方法,现在我有了:

get_data:process(clk, flag)
  begin
  if reset = '1' then
    midi <= (others => '0');
    clr_flag <= '0';
    control_flag <= '0';

  elsif ((clk'event and clk='1') and flag = '1') then
      midi <= data_in;
      clr_flag <= '1'; 
      control_flag <= '1';     
  elsif((clk'event and clk='0') and control_flag = '1') then
    control_flag <= '0';
  elsif((clk'event and clk='1') and control_flag = '0') then
    clr_flag <= '0';
  end if;
end process;
这个双脉冲或大于一个周期脉冲的问题在此之前,我有一个东西使clr_标志成为两个周期的clk脉冲,就是系统将经历两种状态,而不是每个标志一种状态

简言之:当一个信号变高而与变低无关时,应在一个时钟周期内产生一个脉冲


感谢您的帮助。

要使设计只针对一个周期,有几个问题需要解决 脉冲使用触发器寄存器

首先,通常通过VHDL构造在硬件中使用触发器 遵循如下结构:

process (clk, reset) is
begin
  -- Clock
  if rising_edge(clk) then
    -- ... Flip flops to update at rising edge
  end if;
  -- Reset
  if reset = '1' then
    -- Flip flops to update at reset, which need not be all
  end if;
end process;
因此,get_数据过程应相应更新,因此:

灵敏度列表应仅包含时钟时钟和复位 带有if on事件的嵌套结构应如上所述 只应使用clk的上升沿,因此不对clk='0'进行检查 当clr_标志变高时,可使用 标志上的同步“0”到“1”检测器,使用的标志版本为 延迟一个周期,称为下面的flag_ff,然后检查flag= 1和标志_ff='0'

生成的代码可能如下所示:

get_data : process (clk, reset) is
begin
  -- Clock
  if rising_edge(clk) then
    flag_ff  <= flag;  -- One cycle delayed version
    clr_flag <= '0';   -- Default value with no clear
    if (flag = '1') and (flag_ff = '0') then  -- Detected flag going from '0' to '1'
      midi     <= data_in;
      clr_flag <= '1';  -- Override default value making clr_flag asserted signle cycle
    end if;
  end if;
  -- Reset
  if reset = '1' then
    midi     <= (others => '0');
    clr_flag <= '0';
    -- No need to reset flag_ff, since that is updated during reset anyway
  end if;
end process;

产生单周期脉冲的诀窍在于认识到,产生脉冲后,只要触发器输入高,就必须等待,然后才能返回开始。基本上,您正在构建一个非常简单的状态机,但是只有两个状态,您可以使用简单的布尔值来区分它们

Morten关于需要采用一种标准模式来实现计时流程的观点是正确的;我选择了另一个同样有效的

get_data:process(clk, reset)
   variable idle : boolean;
begin
   if reset = '1' then
      idle := true;
   elsif rising_edge(clk) then
      clr_flag <= '0';     -- default action
      if idle then
         if flag = '1' then
            clr_flag <= '1';  -- overrides default FOR THIS CYCLE ONLY
            idle <= false;
         end if;
      else
         if flag = '0' then
            idle := true;
         end if;
      end if;
  end if;
end process;

下面是从至少持续一个时钟周期的信号flag1创建正好持续一个时钟周期的信号flag2的方法


我不使用VHDL编程~以下是我通常在Verilog中为相同建议所做的:

always @(posedge clk or negedge rst) begin

if(~rst) flgD <= 1'b0;

else flgD <= flg;

end

assign trg = (flg^flgD)&flgD;

我是verilog新手,这是用于触发的示例代码。希望这能达到你的目的。您可以在VHDL中尝试相同的逻辑

module main(clk,busy,rd);

input clk,busy;    // busy input condition 
output rd;         // trigger signal
reg rd,en;

always @(posedge clk)
begin
  if(busy == 1)
  begin
    rd <= 0;
    en <= 0;
  end

  else
  begin
    if (en == 0 )
    begin
      rd <= 1;
      en <= 1;
    end
    else 
      rd <= 0; 
  end
end

endmodule

下面的verilog代码应精确保存一个时钟周期的信号值

module PulseGen #(
    parameter integer BUS_WIDTH = 32
    )
    (
    input [BUS_WIDTH-1:0] i,
    input clk,
    output [BUS_WIDTH-1:0] o
    );

    reg [BUS_WIDTH-1:0] id_1 = 0 ;
    reg [BUS_WIDTH-1:0] id_2 = 0 ;
    always @(posedge clk)begin
     id_1 <= i;
     id_2 <= id_1;
    end
    assign o = (id_1 &  ~id_2);

实现这一点的方法是创建一个去抖动电路。如果您需要一个D触发器从0变为1,仅针对第一个时钟,只需在其输入之前添加一个与门,如下图所示: 这里你们可以看到一个D触发器和它的去盎司电路

p.S.电路使用。

同步和FSM边缘检测创建 当检测到这些事件时,上升、边缘和下降输出将选通一个周期。输入和输出是同步的,用于有限状态机

实体同步器 通用的 REG_SIZE:natural:=3-同步寄存器中的默认位数。 ; 港口城市 时钟:标准逻辑; 复位:在标准逻辑中; 异步_-in:in标准_逻辑:='0'; 同步输出:输出标准逻辑:='0'; 上升输出:输出标准输出逻辑:='0'; fall_out:out标准逻辑:='0'; 边缘输出:输出标准逻辑:='0' ; 终止 SynchronizerBIT的架构V1是 常量MSB:natural:=REG_SIZE-1; 信号同步:标准逻辑向量降到0:=其他=>0; 别名sync_in:std_逻辑为sync_regMSB; 信号上升、下降、边缘、上一次同步:标准逻辑:='0'; 开始 资产注册大小>=2报告注册大小应>=2。严重错误; 进程时钟,重置 开始 如果重置,则 同步注册“0”;
在上一篇文章中,我只开始学习vhdl,这对我来说有一些魔力,这就是我在评论中回答的原因。尝试从elsif中删除clk事件。有时这对我很有帮助。我相信你只需要两个状态机,因为低位是空闲状态。显式显示两个状态不是更好,而不是使用idle和not idle吗?@Ayubbargach你可以,但在什么意义上更好?如果您查看布尔类型的定义,您将看到一个具有两个值的枚举类型;形式相同,只是名称不同。你在哪里声明了clr_标志和标志变量?@Unknown123它们不是变量,我只是假设了问题中的声明。
        --------------------------------------------------------------------------------
--------------------------------------------------------------------------------
--input of minimum 1 clock pulse will give output of wanted length.
--load number 5 to PL input and you will get a 5 clock pulse no matter how long input is.
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
library ieee ;
use ieee.std_logic_1164.all ;
use ieee.std_logic_unsigned.all ;
entity fifth is
         port (clk , resetN      : in std_logic;
               pdata             : in integer range 0 to 5; --parallel data in. to choose how many clock the out pulse would be.
               din               : in std_logic;
               dout              : out std_logic
               ) ;
end fifth ;
architecture arc_fifth of fifth is
   signal count   : integer range 0 to 5;
   signal pl      : std_logic; --trigger detect output.
   signal sample1 : std_logic;
   signal sample2 : std_logic;
--trigger sync proccess.
begin
process(clk , resetN)
begin
if resetN = '0' then 
   sample1<='0';
   sample2<='0';

   elsif rising_edge(clk) then
   sample1<=din;
   sample2<=sample1;

end if;
end process;
pl <= sample1 and (not sample2); --trigger detect output. activate the counter.

--counter proccess.
process ( clk , resetN )
begin
   if resetN = '0' then
         count <= 0 ;
         elsif rising_edge(clk) then
               if pl='1' then
               count<=pdata;
               else       
                  if count=0 then
                  count<=count;
                  else
                  count<=count-1;
                  end if;
               end if;       
end if ;
   end process ;

dout<='1' when count>0 else '0';--output - get the wanted lenght pulse no matter how long is input

end arc_fifth ;