首先是代码......
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信号由多个驱动程序驱动”,因此该代码不可合成。
如何通过其他技术实现相同的功能?
答案 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 ;