關於音頻總線IIS的學習---Verilog
主要思想: 在分析寄存器的值變化的時候,將時鍾的邊沿分兩邊來看,邊沿之前,邊沿之后,在always 塊語句里面用來分析判斷的寄存器的值,都應該用邊沿變化之前的值,邊沿之后, always塊做操作的寄存器的值才發生變化。
記住,一定是寄存器量(reg定義的),像audio_sck 這種外部輸入的異步信號要判斷上升沿狀態下的即時值。
`timescale 1ns / 1ps ////////////////////////////////////////////////////////////////////////////////// // Company: // Engineer: chensimin // // Create Date: 2018/06/08 13:33:40 // Design Name: // Module Name: iis_s2p // Project Name: // Target Devices: // Tool Versions: // Description: // // Dependencies: // // Revision: // Revision 0.01 - File Created // Additional Comments: // ////////////////////////////////////////////////////////////////////////////////// module iis_s2p( input wire reset, input wire clk, // 12.288 input wire audio_sck, input wire audio_ws ); //----------------------------------------------- //將外部輸入的sck,ws 信號通過時鍾clk進行同步采集進來 reg audio_sck_d = 0; reg audio_ws_d = 0; always @(posedge clk or posedge reset) begin if(reset) begin audio_sck_d <= 1'b0; audio_ws_d <= 1'b0; end else begin audio_sck_d <= audio_sck; audio_ws_d <= audio_ws; end end //----------------------------------------------- //監測audio_sck 信號的下降沿 //疑問:為什么不采用組合邏輯的方式 //assign sck_neg = audio_sck_d & ~audio_sck ; reg sck_neg = 0; always @(posedge clk or posedge reset) begin if(reset) sck_neg <= 1'b0; else if (audio_sck_d & audio_sck) sck_neg <= 1'b1; else sck_neg <= 1'b0; end endmodule /* add_force {/iis_s2p/clk} -radix hex {1 0ns} {0 5000ps} -repeat_every 10000ps add_force {/iis_s2p/audio_sck} -radix hex {1 0ns} {0 20000ps} -repeat_every 40000ps add_force {/iis_s2p/reset} -radix hex {1 0ns} {0 20ns} */
仿真結果:
分析:
1.從仿真結果可以看出為什么不能用通常的assign語句來檢測sck的下降沿信號,因為sck_neg為外部輸入信號,通過時鍾采集存入sck_d寄存器中,兩個信號波形完全一樣,根本就不會有sck_neg置高的時候。
2.信號過了主時鍾,存入寄存器,寄存器值的變化分析方法:
以主時鍾的上升沿為邊界,分為 :上升沿到來之前, 上升沿,上升沿之后,數據是在上升沿之后進行更新。
對於如下模塊:
//-----------------------------------------------
//結合波形圖來看,clk上升沿到來之前,寄存器中audio_sck_d的數據為0,clk上升沿時,將audio_sck_d里面的數據進行更新,clk上升沿之后,audio_sck_d里面的數據發生變化 //將外部輸入的sck,ws 信號通過時鍾clk進行同步采集進來 reg audio_sck_d = 0; reg audio_ws_d = 0; always @(posedge clk or posedge reset) begin if(reset) begin audio_sck_d <= 1'b0; audio_ws_d <= 1'b0; end else begin audio_sck_d <= audio_sck; audio_ws_d <= audio_ws; end end
對於如下模塊的分析:
//-----------------------------------------------
//主時鍾clk上升沿到來之前,sck_neg,audio_sck_d,audio_sck 均為0 上身沿到來的時候,audio_sck_d, audio_sck信號的值進行更新,從0-1,此時並不滿足if(audio_sck_d & audio_sck)的要求
//因此,第一個主時鍾clk上升沿之后,sck_neg的值依舊保持為0, 下一個主時鍾clk上升沿到來之前,audio_sck_d, audio_sck,的值為1,滿足if(audio_sck_d & audio_sck)的要求,因此,在第二個clk上升沿之后,sck_neg的
//的值變為1. //監測audio_sck 信號的下降沿 //疑問:為什么不采用組合邏輯的方式 //assign sck_neg = audio_sck_d & ~audio_sck ; reg sck_neg = 0; always @(posedge clk or posedge reset) begin if(reset) sck_neg <= 1'b0; else if (audio_sck_d & audio_sck) sck_neg <= 1'b1; else sck_neg <= 1'b0; end