1. 程式人生 > >【轉】verilog的時鐘分頻與時鐘使能

【轉】verilog的時鐘分頻與時鐘使能

verilog的時鐘分頻與時鐘使能

時鐘使能電路是同步設計的基本電路。在很多設計中,雖然內部不同模組的處理速度不同,但由於這些時鐘是同源的,可以將它們轉化為單一時鐘處理。在ASIC中可以通過STA約束讓分頻始終和源時鐘同相,但FPGA由於器件本身和工具的限制,分頻時鐘和源時鐘的Skew不容易控制(使用鎖相環分頻是個例外),難以保證分頻時鐘和源時鐘同相,因此推薦的方法是使用時鐘使能,通過使用時鐘使能可以避免時鐘“滿天飛”的情況,進而避免了不必要的亞穩態發生,在降低設計複雜度的同時也提高了設計的可靠性。

禁止用計數器分頻後的訊號做其它模組的時鐘,而要用改成時鐘使能的方式。否則這種時鐘滿天飛的方式對設計的可靠性極為不利,也大大增加了靜態時序分析的複雜性。

帶使能端的D觸發器,比一般D觸發器多了使能端,只有在使能訊號EN有效時,資料才能從D端被打入D觸發器,否則Q端輸出不改變。

我們可以用帶使能端的D觸發器來實現時鐘使能的功能。

verilog模型舉例

在某系統中,前級資料輸入位寬為8位,而後級的資料輸出位寬為32,我們需要將8bit資料轉換為32bit,由於後級的處理位寬為前級的4倍,因此後級處理的時鐘頻率也將下降為前級的1/4,若不使用時鐘使能,則要將前級的時鐘進行4分頻來作後級處理的時鐘。這種設計方法會引入新的時鐘域,處理上需要採取多時鐘域處理的方式,因而在設計複雜度提高的同時系統的可靠性也將降低。為了避免以上問題,我們採用了時鐘使能以減少設計複雜度。

例1:採用時鐘使能

module clk_en(clk, rst_n, data_in, data_out);
input clk;
input rst_n;
input [7:0] data_in;
output [31:0] data_out;

reg [31:0] data_out;
reg [31:0] data_shift;
reg [1:0] cnt;
reg clken;

always @(posedge clk or negedge rst_n)
begin
   if (!rst_n)
      cnt <= 0;
   else
      cnt <= cnt + 1;
end

always @(posedge clk or negedge rst_n)
begin
   if (!rst_n)
      clken <= 0;
   else if (cnt == 2'b01)
      clken <= 1;
   else
      clken <= 0;
end

always @(posedge clk or negedge rst_n)
begin
   if (!rst_n)
      data_shift <= 0;
   else 
      data_shift <= {data_shift[23:0],data_in};
end

always @(posedge clk or negedge rst_n)
begin
   if (!rst_n)
      data_out <= 0;
   else if (clken == 1'b1)
      data_out <= data_shift;
end

endmodule

例2:採用分頻方法

module clk_en1(clk, rst_n, data_in, data_out);
input clk;
input rst_n;
input [7:0] data_in;
output [31:0] data_out;

reg [31:0] data_out;
reg [31:0] data_shift;
reg [1:0] cnt;
wire clken;

always @(posedge clk or negedge rst_n)
begin
   if (!rst_n)
      cnt <= 0;
   else
      cnt <= cnt + 1;
end

assign clken = cnt[1];

always @(posedge clk or negedge rst_n)
begin
   if (!rst_n)
      data_shift <= 0;
   else 
      data_shift <= {data_shift[23:0],data_in};
end

always @(posedge clken or negedge rst_n)
begin
   if (!rst_n)
      data_out <= 0;
   else 
      data_out <= data_shift;
end

endmodule