Verilog——入门进程学习(四)

Verilog的编程模块结构

  module 模块名(端口1, 端口2, 端口3)
 //内容:
    //I/O说明:
            input 端口名;
            output 端口名;
 //内部信号:
            reg [width-1:0]  r变量1,r变量2;
            wire [width-1:0] w变量1,w变量2;
 //功能定义:
            a. assign 连线
                assign a = b&c;
            b. 实例化其他元件
                and and_inst(q, a, b);
            c. always模块
                always @(posedge clk or posedge clr)
                begin
                    if(clr) 
                        q <= 0;
                    else
                        if(en)
                            q <= d;
                end
endmodule                

在verilog设计中,模块名就是文件名,这是由于软件编译的问题而限制的。所以设置模块名的时候也决定了文件名。因此,模块名的设定要体现出模块的功能,这样设定对于大的工程项目设计很有用处,便于查找分析。

module/endmodule

首先我们要知道Verilog中的module/endmodule是做什么用的。如果你学过C语言,那么你就应该知道模块的概念。而模块是 Verilog 中基本单元的定义形式,是与外界交互的接口。
在Verilog中,我们要使用module开头,endmodule结尾。例子如下:

module counter10(
        //端口定义
        input                   rstn,   //复位端,低有效
        input                   clk,    //输入时钟
        output [3:0]    cnt,    //计数输出
        output                  cout);  //溢出位

        reg [3:0]               cnt_temp ;      //计数器寄存器
        always@(posedge clk or negedge rstn) begin
                if(! rstn)
                begin         //复位时,计时归0
                        cnt_temp        <= 4'b0 ;
                end
                else if (cnt_temp==4'd9) begin  //计时10个cycle时,计时归0
                        cnt_temp        <=4'b000;
                end
                else begin                                      //计时加1
                        cnt_temp        <= cnt_temp + 1'b1 ;
                end
        end

        assign  cout = (cnt_temp==4'd9) ;       //输出周期位
        assign  cnt  = cnt_temp ;                       //输出实时计时器

endmodule
  • 我们能够清楚地看到,在上面这个4 位宽 10 进制计数器中,module和endmodule的使用用法。这个是Verilog的基础。
  • 一个 .v文件中主要由 一个或多个 module … endmodule块组成
  • 每个module块内包括:模块名,输入端口,输出端口,以及多个时序电路,组合电路等组成

input(输入)/output(输出)

我们能够在上面的模块结构中清晰地看到input与output的用法,主要是用来定义端口的类型是输出还是输入。其余则没有什么意义了。这里要将我们所使用的端口给定义成这两类。

数据类型wire/reg

这里如果不懂的话,可以点击下面的链接,就不详细解释了。
数据类型解释

但是这里需要注意的是:reg类型的变量不能使用assign进行连续赋值,这是因为reg类型的变量可以存储数据,并且不需要连续驱动。我们只能在initial以及always块内对reg类型变量进行赋值。

always/ initial

两者的关系 一个程序块可以有多个initial和always过程块。每个initial和always说明语句在仿真的一开始同时立即开始执行

  1. initial语句只执行一次,而always语句则不断重复的活动着,直到仿真结束。
  2. 一段程序中使用的initial和always语句的次数不受限制,他们都是同时开始运行的。
  3. always语句则没有次数限制,是否运行取决于其后面的限制条件,满足则运行一次,直到程序结束。

if与begin/end的关系

我想如果学习过编程的同学,对if这个语句都不陌生,判断语句,如果满足则运行一次。运行的是begin和end里面的语句,这里的begin和end就相当于C语言中的{ }一样。

assign

关键字assign开头则代表的是赋值语句,后面是信号名,可以是单个信号,也可以是不同信号网的连接。

assign <net_expression> = [drive_strength] [delay] <expression of different signals or constant value>

使用 assign 语句时, 需要遵循一些规则:

  • LHS(左值) 应该始终是wire类型的标量或向量网络, 或者标量或矢量网络的串联, 而绝对不能是reg类型的标量或矢量寄存器。
  • RHS 可以包含标量或向量寄存器以及函数调用。
  • 只要 RHS 上的任何操作数的值发生变化, LHS 就会使用新值进行更新。
  • assign 语句也称为连续赋值, 并且始终处于活动状态

如果有什么不对之处,欢迎指正,谢谢

posted @ 2021-03-08 15:15  Xa_L  阅读(588)  评论(0编辑  收藏  举报