门控时钟产生

时间:2013-03-31 14:53:10

标签: verilog clock fpga

首先是代码......

always@(posedge clk)
begin
if(cstate==idle)    rclk<=1;
else rclk<=0;
end

always@(negedge clk)
rclk<=0;

我想要实现的是:每次在时钟信号的上升沿,如果信号cstate等于空闲(4'b0000),则rclk变为1,否则变为0,同时每次时间clk的下降沿将rclk设置为零。由于编译器提供错误“rclk信号由多个驱动程序驱动”,因此该代码不可合成。

如何通过其他技术实现相同的功能?

1 个答案:

答案 0 :(得分:1)

看起来你想要一个时钟门单元。基于1个周期的宽使能信号产生一个时钟脉冲,其时间与输入时钟相同。

这种天真的做法可能是:

assign rclk = (cstate==idle) ? clk : 1'b0 ;

可以很容易地合成assign rclk = (cstate==idle) & clk ;
cstate == idle会出现故障,这就是为什么它通常被触发器使用,允许在使用之前解决问题。

使用时钟门控单元可以阻止您在(rclk)时钟线上产生毛刺。为此,在rtl中实例化库时钟门单元是很常见的。在RTL中,它可能类似于:

reg result;
always @(posedge clk or negedge rst_n) begin
  if (~rst_n) begin
    result <= 1'b0;
  end
  else begin
    result <= (cstate == idle);
  end
end

assign rclk = (result) ? clk : 1'b0 ;

这意味着每个时钟周期的结果都是稳定的,不允许来自比较器的毛刺。

扩大回答

我已将下面的示例再次包含在波形中,我已将一个简单的计数器替换为状态比较,该计数器溢出以重置自身。不是比较与2'b10匹配;这意味着时钟出现在下面的计数(2'b11)。如果时钟与您的比较匹配的时间恰好相同,那么您的时钟就不会出现毛刺抑制,并且可能会产生不可靠的硬件。

reg [1:0] counter = 0;

always @(posedge clk) 
  counter <= counter+1;

reg  result;
wire result_a = (counter == 2'b10 );

always @(posedge clk or negedge rst_n) begin
  if (~rst_n) begin
    result <= 1'b0;
  end
  else begin
    result <= result_a;
  end
end

assign rclk = (result) ? clk : 1'b0 ;

Example waveform of Clock Gate