当前位置:网站首页>第一章 Verilog语言和Vivado初步使用

第一章 Verilog语言和Vivado初步使用

2022-08-11 05:29:00 YOUNIKOJIAO

第一章 Verilog语言和Vivado初步使用

在这一章我将总结Verilog语言的基本语法,并对Vivado软件使用进行说明。

1.1Verilog基本结构

简单的组合逻辑实例

下面以一个简单的组合逻辑来说明Verilog的基本结构

module AND(a, b, out);
    output[3:0] out;     // 4位输出 
    input [3:0] a, b;    // 4位输入a, b
    assign out = a & b;  // out <- a & b
endmodule

从模块的声明开始,最开始的关键词module模块名AND模块结束的关键词为endmodule。除了以上写法还有一种颇为常见的写法如下:

module AND (
    output[3:0] out,
    input [3:0] a, b,
);
    assign out = a & b;
endmodule

简单的时序逻辑实例

下面介绍一个简单的时序逻辑,时序逻辑比组合逻辑复杂且要考虑的的东西更多。

module fenpin (
	input clk_in,
    output clk_out
);
    reg c_out = 0;
    assign clk_out = c_out;V
    always @ (posedge clk_in) begin
        c_out = ~c_out;
    end
endmodule

上述时序逻辑的时序图如下:
在这里插入图片描述

​ Verilog HDL不同于我们常见的C语言,clk_out = c_out是建立了一种电路上的连接,将c_out的值输出到clk_out中,不仅仅是在assign clk_out = c_out这个赋值语句发生时才进行,而是之后无论c_out变为何值clk_out都要为之改变。为了更好的描述这层关系,用如下电路图来表示上面这段代码。

在这里插入图片描述

​ 可以看到c_outclk_out的确建立了永久性的连接,而不是在语句结束后就释放这种连接,这点是要和C语言或者其他语言区别开的,不能忘记HDL是用来描述电路的。

Verilog HDL结构要求

在编写Verilog代码的时候需要注意以下几点

  1. 模块的时序逻辑部分在always块的内部,在always块的内部只能对寄存器变量进行赋值。
  2. 模块中对端口或其他wire型变量的赋值,必须在always块的外部使用assign语句,通常是将寄存器的值送出。
    块中对端口或其他wire型变量的赋值,必须在always块的外部使用assign语句,通常是将寄存器的值送出。

1.2 数据类型及变量、常量

Verilog HDL中有两种常见的数据类型线网类型变量类型。对于线网类型我们主要介绍wire型,对于变量类型则主要介绍reg型。

1.2.1 逻辑值与常量

逻辑值

逻辑值含义
0 0 0逻辑0
1 1 1逻辑1
x x x逻辑值未知
z z z高阻态

常量表示方法

表达方式说明举例
<位宽>'<进制><数字>完整的表达方式4'b0101 or 4'h5
<进制><数字>缺省位宽,位宽由机器决定,最小是32位h05
<数字>缺省进制则默认为10进制,位宽默认为32位5

说明:

  1. 4'h54'b0101实质上是等价的只是采用了不同进制的表示方法
  2. 8'h2x表示为八位二进制数时8'b0010xxxx

1.2.2 线网型wire

在这里插入图片描述

​ 1.1节的例子中clk_inclk_out变量是wire类型,如果没有接触过Verilog HDL对这个类型会感到很不适应,可以先这样想wire类型就是电路中的一条线,可以随着端口的改变而改变电线中的逻辑值,之后进行项目设计的时候会对这些变量有更深刻的理解。

给出wire型变量的两种定义方法:

  1. wire[7:0] a, b, c; // 定义了三个位宽为8位的wire型变量
  2. wire d //定义了一个1位的wire

1.2.3 寄存器型reg

在这里插入图片描述

​ 当定义一个reg类型就相当于使用了一个D触发器,只有在时钟有效边沿到来时,保存的值才能改变。

给出reg型变量的两种定义方法:

  1. reg[7:0] a, b, c; // 定义了三个位宽为8位的reg型变量
  2. reg d //定义了一个1位的reg

1.2.4 符号常量

​ 如果使用关键字parameter来定义一个标识符来代表一个常量,这个常量就被成为符号常量。

例如:parameter width = 3;将程序中的所有width用3替换。

调用模块的时候也可以改变parameter常量的值

module add(sum, a, b);
    parameter time_dl = 5, time_cnt = 10;
    ...
endmodule

module top;
    wire[2:0] a1, b1;
    wire[3:0] a2, b2, sum1;
    wire[4:0] sum2;
    add # (4, 3) AD1(sum1, a1, b1);  //使time_dl=4,time_cnt=8
    add # (12)   AD2(sum2, a2, b2);  //time_dl=12,time_cnt=10
endmodule

1.2.5 存储器型变量

​ 存储器其实就是一个寄存器数组,我们写MIPS CPU的时候接触过寄存器堆,其实就是这个。可以使用如下方法定义

reg [msb:lsb] mem[upper1:lower1]

例如:

  1. reg[3:0] mem1[63:0]; // 定义了64个4位寄存器组
  2. reg mem2[5:1]; // 定义了5个1位的寄存器组
  3. mem2[4] = 1; // 对其中1位的寄存器赋值
  4. mem2[1:5] = 0; // 对存储器大范围赋值,速度很快

原网站

版权声明
本文为[YOUNIKOJIAO]所创,转载请带上原文链接,感谢
https://blog.csdn.net/YOUNIKOJIAO/article/details/126190182