2013-11-24 43 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 
相關問題