verilog语法--边沿检测

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了verilog语法--边沿检测相关的知识,希望对你有一定的参考价值。

先看程序:
module count(out,data,load,reset,clk);
output[7:0] out;
input[7:0] data;
input load,clk,reset;
reg[7:0] out;
always @(posedge clk)
begin
if (!reset)
out = 8'h0;
else
if (load)
out = data;
else
out = out + 1;
end
endmodule
1.本想对clk计数,而此程序中不妥地方是只有在clk的上升沿时always才会被执行。如果clk没有变化则reset、load无效,且clk有变化但reset或load有效时将会漏掉计数。如果不采用更高的时钟对clk采样能否解决这个问题。
2.另外上面程序编译时会有如下警告Warning (10230): Verilog HDL assignment warning at count.v(63): truncated value with size 32 to match size of target (8)。双击时指向out = out + 1;不知道为什么

下面是VHDL语言的思路:
process(clk,reset,load) 三个信号中的任意一信号都会触发该进程
begin
if(reset='0')then 如果复位有效
out <= "00000000"; 清0
else
if(load='1')then 如果加载有效
out <= data;
else 否则计数
out <= out + 1;
end if;
end if;
end process;
我想用这verilog实现这种思想。如果有其它方法也很感谢大家能够提出。
VHDL那段程序有误,现改正如下
process(clk,reset,load) 三个信号中的任意一信号都会触发该进程
begin
if(reset='0')then 如果复位有效
out <= "00000000"; 清0
else
if(load='1')then 如果加载有效
out <= data;
else 否则
if(clk'event and clk='1')then 在clk的上升时计数
out <= out + 1;
end if;
end if;
end if;
end process;
-----------------------------------------
to 回答者: ttknw
谢谢您的解答,通过你的方法可以解决问题。
我想请教一下,verilog中有没有像VHDL这样的一种实现方法:
VHDL:在进程中process中还可以使用边沿检测语句if(clk'event and clk='1')。
Verilog:目前只知道能通过always@(posedge clk)实现边沿检测,或者就是你那种方法。而前者中,边沿检测功能只能处于最上层。请教,Verilog能实现VHDL那种方法吗。

参考技术A 先回答你的第二个问题:因为你没有指定位宽,所以系统提示默认为32位
所以你将out <= out + 1 改为out <= out + 1'b1 就可以了。
另外注意:在时序电路里面要用<=

再回答你的第一个问题
只需要将load信号先进行上升沿检测,(即在上升沿装载)即可,这样即使load一直为高电平,也不会影响计数。至于你提到的当reset有效时漏掉计数是正确的,否则复位也就没有意义了。

module count(out,data,load,reset,clk);
output[7:0] out;
input[7:0] data;
input load,clk,reset;
reg[7:0] out;

//下面是进行load上升沿检测的代码,这样即使load一直为高电平,也不会影响计数

reg ld_r1,ld_r2;
wire load_p;

always @(posedge clk) begin
if (!reset) begin
ld_r1<=1'b0;
ld_r2<=1'b0;
end
else begin
ld_r1<=load;
ld_r2<=ld_r1;
end
end

assign load_p = ld_r1 & (~ld_r2);

//----------------------------------
always @(posedge clk) begin
if (!reset)
out <= 8'h0;
else
if (load_p) //这里需要改成 load_p
out <= data;
else
out <= out + 1'b1;
end
endmodule本回答被提问者采纳
参考技术B 你第一个问题到底说的是什么?什么东西不妥?这个思路不是跟VHDL程序的思路完全一样么?
至于第二个问题,我不知道你用的是什么软件,反正我用ISE11.4综合没有提示warning

边沿检测电路设计verilog

Abstract

边沿检测电路(edge detection circuit)是个常用的基本电路。

Introduction

所谓边沿检测就是对前一个clock状态和目前clock状态的比较,如果是由0变为1,能够检测到上升沿,则称为上升沿检测电路(posedge edge detection circuit),若是由1变为0,能够检测到下降沿,则被称为下降沿检测电路(negedge edge dttection circuit),能够同时检测上升沿与下降沿的电路称为双沿检测电路(double edge detection)。

上升沿检测电路

Method 1:  使用两个reg

 

r_data_in0与r_data_in1为DFF,分别hold住上一个与目前clock的i_data_in,当i_data_in由1变为0时,则

r_data_in0    1  1  1  0  0  0

r_data_in1        1  1  1  0  0  0   //对r_data_in0取反相与

o_rising_edge得到一个时钟周期的高电平。

Posedge detection.v / verilog 

 1 module posedge_detection (
 2    input  clk,
 3    input  rst_n,
 4   input  i_data_in,
 5    output o_rising_edge
 6 );
 7  
 8  reg r_data_in0;
 9  reg r_data_in1;
10 
11  assign o_rising_edge = ~r_data_in0 & r_data_in1;
12  
13  always@(posedge clk, negedge rst_n) begin
14   if (!rst_n) begin
15      r_data_in0 <= 0;
16      r_data_in1 <= 0;
17    end
18    else begin
19     r_data_in0 <= r_data_in1;
20      r_data_in1 <= i_data_in;
21    end
22  end
23  
24  endmodule

这种写法经过综合后RTL为一个两位的DFF与一个AND。

Methord 2: 使用一个reg

posedge_detection2.v / verilog 

module posedge_detection2(
    input clk,
    input rst_n,
    input i_data_in,
    output reg o_rising_edge       
);

reg r_data_in0;

always@(posedge clk or negedge rst_n) begin
  if(!rst_n)
  r_data_in0 <= 0;
  else begin
   r_data_in0 <= i_data_in;
   if({r_data_in0,i_data_in} == 2\'b01)
   o_rising_edge <= 1;
   else 
   o_rising_edge <= 0;  
        
 end

end
endmodule 

这种写法综合成RTL之后只有一个D-FF和一个Equal,右边的o_rising_edge 的D-FF主要是因为always过程块内的reg。

Vwf仿真图形如下

 

下降沿检测与上升沿相似,不在叙述

双沿检测电路(double edge detection)

r_data_in0与r_data_in1位reg,分别hold住上一个clock和目前的clock得i_data_in,就是i_data_in由1变0,或者由0变1,也就是r_data_in1为1,r_data_in0为0,或者是r_data_in1为0,r_data_in0为1,因此用异或(xor)连接两个寄存器。

Method1 : 使用两个reg

Double_edge_detection.v/ verilog

 module doubleedge_detection (
   input  clk,
   input  rst_n,
   input  i_data_in,
   output o_double_edge
 );
 
 reg r_data_in0;
 reg r_data_in1;
 
 assign o_double_edge = r_data_in0 ^ r_data_in1;
 
 always@(posedge clk, negedge rst_n) begin
   if (!rst_n) begin
     r_data_in0 <= 0;
     r_data_in1 <= 0;
   end
  else begin
    r_data_in0 <= r_data_in1;
    r_data_in1 <= i_data_in;
   end
 end

endmodule

Method2 :使用一个reg

Double_edge_detection2.v/verilog

 module doubleedge_detection2 (
   input      clk,
   input      rst_n,
   input      i_data_in,
   output reg o_double_edge
 );

 reg r_data_in0;

 always@(posedge clk, negedge rst_n) begin
   if (!rst_n)
     r_data_in0 <= 0;
  else begin
    r_data_in0    <= i_data_in;
    
     if ({r_data_in0, i_data_in} == 2\'b10)
      o_double_edge <= 1;
    else if ({r_data_in0, i_data_in} == 2\'b01)
      o_double_edge <= 1;
    else
       o_double_edge <= 0;
       
     // another method
     // o_double_edge <= r_data_in0 ^ i_data_in;
  end
 end
 
 endmodule

Conclusion

什么时候使用这种电路呢?当input是非同步信号时,为了要让input与同步的FSM一起处理,必须先经过边沿检测,使之与clock同步,然后才能跟FSM一起运作。 

 

以上是关于verilog语法--边沿检测的主要内容,如果未能解决你的问题,请参考以下文章

边沿检测电路设计verilog

边沿检测电路设计verilog

 FPGA边沿检测Verilog代码

verilog hdl中有了posedge和negedge为啥还要用脉冲边沿检测?。

请问怎么用verilog语言来判断一个输入信号是持续高电平还是时钟信号,请大侠指点

verilog 上下边沿同时触发 可综合代码实现