在同步電路設計中,邊沿檢測是必不可少的!
例如:在一個時鐘頻率16MHz的同步串列匯流排接收電路里,串列匯流排波特率為1Mbps。在串列匯流排的發送端是在同步時鐘(1MHz)的上升沿輸出數據,在接收端在同步時鐘的下降沿對輸入數據進行接收採樣。在這個接收電路里檢測同步時鐘的下降沿是必不可少的。假設主時鐘-clk,同步時鐘-rck,同步數據-data。
有些人在邊沿檢測的時候就喜歡這樣做:
代碼
- signal rck_dly: std_logic;
- signal data_buf: std_logic;
- RCK_Delay:process(clk,rst_n)
- begin
- if rst_n='0' then
- rck_dly <= '0';
- elsif rising_edge(clk) then
- rck_dly <= rck;
- end if;
- end process;
-
- Data_Receivee:process(clk,rst_n)
- begin
- if rst_n='0' then
- data_buf <= '0';
- elsif rising_edge(clk) then
- if (rck_dly='1' and rck='0') then
- data_buf <= data;
- end if;
- end if;
- end process;
但是大家忽略了一種情況,就是clk與rck之間比沒有必然的同步關係,當rck的下降沿剛好略滯後於clk的上升沿(大概幾個ns),這樣就會使高電平 保持時間不足,就會發現在本時鐘上升沿時還是rck_dly='1' and rck='1',而在下一個時鐘的上升沿來的時候,就會出現rck_dly='0' and rck='0',所以就不會有rck_dly='1' and rck='0'的情況出現!! 從而導致丟失數據。
如果用下面的方法就可以避免上面的情況,並且可以做到正確無誤地接收數據:
代碼
- signal rck_dly: std_logic_vector(1 downto 0);
- signal data_buf: std_logic;
- RCK_Delay:process(clk,rst_n)
- begin
- if rst_n='0' then
- rck_dly <= (others=>'0');
- elsif rising_edge(clk) then
- rck_dly <= rck_dly(0) & rck;
- end if;
- end process;
-
- Data_Receiver:process(clk,rst_n)
- begin
- if rst_n='0' then
- data_buf <= '0';
- elsif rising_edge(clk) then
- if rck_dly="10" then
- data_buf <= data;
- edn if;
- end if;
- end process;
至於以上電路為什麼就可以克服上面出現的情況,就留給大家分析了。
不得不承認后一種方法所耗的資源要比前一種方法多(一個觸發器),但是就可以大大提高可靠性,這絕對是物有所值!!