Verilog学习之时序控制、语句块(1)

推荐Verilog学习网址:

HDLbits

EDAPlayground

菜鸟教程

因为自己以前学过Verilog,现在要重新捡起来,所以就记录了一下不熟悉的部分。

时序控制

代码来自菜鸟教程4.3 Verilog 时序控制 | 菜鸟教程

1.时延控制

常规时延

#10  value1 = value_test;

内嵌时延

value1 =  #10   value_test;

value_test的当前值(而不是#10后的值),在#10后,赋给value1

`timescale 1ns/1ns
 
module test ;
    reg  value_test ;
    reg  value_general, value_embed, value_single ;
 
    //signal source
    initial begin
        value_test        = 0 ;
        #25 ;      value_test        = 1 ;
        #35 ;      value_test        = 0 ;        //absolute 60ns
        #40 ;      value_test        = 1 ;        //absolute 100ns
        #10 ;      value_test        = 0 ;        //absolute 110ns
    end
 
    //(1)general delay control
    initial begin
        value_general     = 1;
        #10 value_general  = value_test ; //10ns, value_test=0
        #45 value_general  = value_test ; //55ns, value_test=1
        #30 value_general  = value_test ; //85ns, value_test=0
        #20 value_general  = value_test ; //105ns, value_test=1
    end
 
    //(2)embedded delay control
    initial begin
        value_embed       = 1;
        value_embed  = #10 value_test ; //0ns, value_test=0
        value_embed  = #45 value_test ; //10ns, value_test=0
        value_embed  = #30 value_test ; //55ns, value_test=1
        value_embed  = #20 value_test ; //85ns, value_test=0
    end
 
    always begin
        #10;
        if ($time >= 150) begin
            $finish ;
        end
    end
 
endmodule

2.事件触发

1. @        敏感列表

e.g.        always@(clk)        //clk的上升沿与下降沿触发

              always@(posedge clk or negedge rst)        //clk的上升沿,rst的下降沿

              always@(posedge clk ,   negedge rst)

              always@(*)

2. event       (触发->)

event     start_receiving ;
always @( posedge clk_samp) begin
        -> start_receiving ;       //采样时钟上升沿作为时间触发时刻
end
 
always @(start_receiving) begin
    data_buf = {data_if[0], data_if[1]} ; //触发时刻,对多维数据整合
end

 

3.边沿触发

4.电平触发

initial begin
    wait (start_enable) ;      //等待 start 信号
    forever begin
        //start信号使能后,在clk_samp上升沿,对数据进行整合
        @(posedge clk_samp)  ;
        data_buf = {data_if[0], data_if[1]} ;      
    end
end

块语句

1.顺序块        begin end

2.并行块        fork  join

3.嵌套块

4.命名块

代码来自菜鸟教程4.4 Verilog 语句块 | 菜鸟教程

        begin:模块名

                int i;        // module名.模块名.i        就可以调用此变量

        end

模块名可以嵌套

`timescale 1ns/1ns
 
module test;
 
    initial begin: runoob   //命名模块名字为runoob,分号不能少
        integer    i ;       //此变量可以通过test.runoob.i 被其他模块使用
        i = 0 ;
        forever begin
            #10 i = i + 10 ;       
        end
    end
 
    reg stop_flag ;
    initial stop_flag = 1'b0 ;
    always begin : detect_stop
        if ( test.runoob.i == 100) begin //i累加10次,即100ns时停止仿真
            $display("Now you can stop the simulation!!!");
            stop_flag = 1'b1 ;
        end
        #10 ;
    end
 
endmodule

5.disable

disable可以终止命名块的执行,可以用来从循环中退出、处理错误等。

`timescale 1ns/1ns
 
module test;
 
    initial begin: runoob_d //命名模块名字为runoob_d
        integer    i_d ;
        i_d = 0 ;
        while(i_d <= 100) begin: runoob_d2
            # 10 ;
            if (i_d >= 50) begin       //累加5次停止累加
                disable runoob_d3.clk_gen ;//stop 外部block: clk_gen
                disable runoob_d2 ;       //stop 当前block: runoob_d2
            end
            i_d = i_d + 10 ;
        end
    end
 
    reg clk ;
    initial begin: runoob_d3
        while (1) begin: clk_gen  //时钟产生模块
            clk=1 ;      #10 ;
            clk=0 ;      #10 ;
        end
    end
 
endmodule

disable在always或forever中使用时只能退出当前回合,下一次语句还是会在always或forever中执行。

casex/casez

casex 用 "x" 来表示无关值,casez 用问号 "?" 来表示无关值。

两者的实现的功能是完全一致的,语法与 case 语句也完全一致。

但是 casex、casez 一般是不可综合的,多用于仿真

repeat

repeat (循环次数) begin        //循环次数必须是常量

end

过程连续赋值

4.8 Verilog 过程连续赋值 | 菜鸟教程

过程连续赋值是过程赋值的一种。这种赋值语句能够替换其他所有 wire 或 reg 的赋值,改写了 wire 或 reg 型变量的当前值。

与过程赋值不同的是,过程连续赋值的表达式能被连续的驱动到 wire 或 reg 型变量中,即过程连续赋值发生作用时,右端表达式中任意操作数的变化都会引起过程连续赋值语句的重新执行

assign-deassign

assign(过程赋值操作)与 deassign (取消过程赋值操作)

赋值对象只能reg型

module dff_assign(
    input       rstn,
    input       clk,
    input       D,
    output reg  Q
 );
 
    always @(posedge clk) begin
        Q <= D ;       //Q = D at posedge of clock
    end
 
    always @(negedge rstn) begin
        if(!rstn) begin
            assign Q = 1'b0 ; //在复位信号为 0 时,Q 端被 assign 语句赋值,始终输出为 0。
        end
        else begin        //cancel the Q value overlay
            deassign Q ;  //复位信号为 1 时,Q 端被deassign语句取消赋值,在时钟上升沿被重新赋值
        end
    end
 
endmodule

force-release

force (强制赋值操作)与 release(取消强制赋值)

赋值对象可以是 reg 型变量,也可以是 wire 型变量。

因为是无条件强制赋值,一般多用于交互式调试过程,不要在设计模块中使用

当 force 作用在寄存器上时,寄存器当前值被覆盖;release 时该寄存器值将继续保留强制赋值时的值。之后,该寄存器的值可以被原有的过程赋值语句改变。

当 force 作用在线网上时,线网值也会被强制赋值。但是,一旦 release 该线网型变量,其值马上变为原有的驱动值

在 Verilog 中,端口隐式的声明为 wire 型变量。

模块例化

generate

可以对同一个模块进行重复例化

defparam

可以用关键字 defparam 通过模块层次调用的方法,来改写低层次模块的参数值。

defparam 一般也不可综合。

defparam     u_ram_4x4.MASK = 7 ;
ram_4x4    u_ram_4x4
    (
        .CLK    (clk),
        .A      (a[4-1:0]),
        .D      (d),
        .EN     (en),
        .WR     (wr),    //1 for write and 0 for read
        .Q      (q)    );
//在ram_4x4模块中,定义了parameter MASK = 3;

将新的参数值写入模块例化语句

(推荐该方法)

module  ram
    #(  parameter       AW = 2 ,
        parameter       DW = 3 )
    (
        input                   CLK ,
        input [AW-1:0]          A ,
        input [DW-1:0]          D ,
        input                   EN ,
        input                   WR ,    //1 for write and 0 for read
        output reg [DW-1:0]     Q
     );
 
endmodule

//例化:
ram #(.AW(4), .DW(4))
    u_ram
    (
        .CLK    (clk),
        .A      (a[AW-1:0]),
        .D      (d),
        .EN     (en),
        .WR     (wr),    //1 for write and 0 for read
        .Q      (q)
     );

在编译器看来,如果有模块在端口声明时的参数,那么实体中的参数将视为 localparam 类型,使用 defparam 将不能改写模块实体中声明的参数。

  • 22
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值