平台:ise14.7
仿真平台:modelsim se10.4d
在使用AD采集控制的时候往往需要使用SPI来读取外部的数据,需要逻辑内部产生门控时钟提供给外部器件使用。
逻辑上使用组合逻辑分配时钟。
// *************************
// MODULE DEFINITION
// *************************
`timescale 1 ns / 1 ps
module gate_clk#(
parameter U_DLY = 1
)
(
input wire clk ,
input wire rst_n ,
output wire gate_clk
);
//--------------------------------------
// localparam
//--------------------------------------
//--------------------------------------
// register
//--------------------------------------
reg [7:0] clk_cnt ;
reg clk_flog ;
//--------------------------------------
// wire
//--------------------------------------
//--------------------------------------
// assign
//--------------------------------------
assign gate_clk = clk_flog ? clk : 1'b0;
//------------------------------------------------------------
//------------------------------------------------------------
always@(posedge clk or negedge rst_n)
begin
if(rst_n == 1'b0)
clk_cnt <= 8'd50;
else if(clk_cnt == 8'd0)
clk_cnt <= 8'd50;
else
clk_cnt <= clk_cnt - 1'b1;
end
always@(posedge clk or negedge rst_n)
begin
if(rst_n == 1'b0)
clk_flog <= 1'b0;
else if(clk_cnt >= 8'd20 && clk_cnt <= 8'd30)
clk_flog <= 1'b1;
else
clk_flog <= 1'b0;
end
//------------------------------------------------------------
//------------------------------------------------------------
//------------------------------------------------------------
//------------------------------------------------------------
endmodule
如仿真所示,在门控时钟使能信号的尾端会产生一个毛刺。这个毛刺会影响电路的正常运行。
这里有两种解决办法,他们的解决思路都是一个道理。
- 门控时钟输出是将源时钟取反。
- 将门控时钟使能在源时钟下降沿上打一拍。
使用门控输出将源时钟取反
assign gate_clk = clk_flog ? ~clk : 1'b0;
二将门控时钟使能在源时钟的下降沿寄存一拍。使用打拍后的使能来产生时钟。
// *************************
// MODULE DEFINITION
// *************************
`timescale 1 ns / 1 ps
module gate_clk#(
parameter U_DLY = 1
)
(
input wire clk ,
input wire rst_n ,
output wire gate_clk
);
//--------------------------------------
// localparam
//--------------------------------------
//--------------------------------------
// register
//--------------------------------------
reg [7:0] clk_cnt ;
reg clk_flog ;
reg clk_flog_r ;
//--------------------------------------
// wire
//--------------------------------------
//--------------------------------------
// assign
//--------------------------------------
assign gate_clk = clk_flog_r ? clk : 1'b0;
//------------------------------------------------------------
//------------------------------------------------------------
always@(posedge clk or negedge rst_n)
begin
if(rst_n == 1'b0)
clk_cnt <= 8'd50;
else if(clk_cnt == 8'd0)
clk_cnt <= 8'd50;
else
clk_cnt <= clk_cnt - 1'b1;
end
always@(posedge clk or negedge rst_n)
begin
if(rst_n == 1'b0)
clk_flog <= 1'b0;
else if(clk_cnt >= 8'd20 && clk_cnt <= 8'd30)
clk_flog <= 1'b1;
else
clk_flog <= 1'b0;
end
always@(negedge clk or negedge rst_n)
begin
if(rst_n == 1'b0)
clk_flog_r <= 1'b0;
else
clk_flog_r <= clk_flog;
end
//------------------------------------------------------------
//------------------------------------------------------------
//------------------------------------------------------------
//------------------------------------------------------------
endmodule