2013-11-24 29 views
0

我正在制作MIDI界面。 UART工作正常,它将8位消息和标志一起发送给控制单元。当标志变高时,单元会将该信息存储在寄存器中并使clr_flag为高电平,以便再次将UART标志设置为低电平。问题是我无法使这个clr_flag持续一段时间。我需要它长达一个周期,因为这个信号还控制着一个状态机,它指示存储什么类型的消息(例如,note_on - > key_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_flag两期CLK脉冲)的问题,是系统将通过两个国家,而不是每个国旗一个。简而言之,当一个信号变高(独立于变低时),应该产生一个时钟周期内的脉冲。

感谢您的帮助。

+0

我只开始学习vhdl,对我来说有一些魔力,这就是为什么我在评论中回答。尝试从elsif中删除clk'event。有时它对我有帮助。 –

回答

1

为了使用触发器(寄存器)设计一个周期的脉冲,有几个问题需要解决。

首先,利用翻转的在硬件通过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_data过程应该相应地被更新,从而:

  • 灵敏度列表应只包含时钟(clk)和reset
  • 嵌套结构与if上偶数吨应如上
  • clk只有上升沿应使用,从而对clk = '0'

clr_flag制作一个周期脉冲时flag变高可以用 同步进行“0”无复''上的'1'检测器,使用flag即 延迟一个单一周期的版本,在下面调用flag_ff,然后检查(flag = ''1) and (flag_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; 
3

诀窍使单周期脉冲意识到作出的脉搏,你只要触发输入找回之前的高等待到开始。本质上你正在构建一个非常简单的状态机,但只有2个状态,你可以使用一个简单的布尔值来区分它们。

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; 
1

下面是创建一个信号(FLAG2)的方式,持续从一个信号(FLAG1)恰好一个时钟周期,持续至少一个时钟周期。

enter image description here

0

我在VHDL没有计划〜这里是我平时对同样提出了Verilog做:

always @(posedge clk or negedge rst) begin 

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

else flgD <= flg; 

end 

assign trg = (flg^flgD)&flgD; 
0

我是新来的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 
相关问题