29

tech2022-09-11  103

Verilog基础模块介绍

1.常量

整数:二进制b或者B、八进制o或者O、十进制d或者D、十六进制h或者H。 x和z:X代表不定值、z代表高阻值,例如5’b00x11第三位不定值,3’b00z表示最低位为高阻值。 下划线:用来做数据分割提高可读性,如:8’b0000_1111 参数parameterparameter用来表示定义常量,提高可读写和维护性。 定义:parameter width = 8 定义寄存器reg[width-1:0]a;定义8位宽度的寄存器。 被调用模块

module rom #( parameter depth =15, parameter width = 8 ) ( input [depth-1:0] addr, input [width-1:0]data, output result ); endmodule

顶层调用模块

module top(); wire [31:0] addr; wire [15:0] data; wire result; rom #( .depth(32), .width(16) ) r1 ( .addr(addr), .data(data). .result(result) ); endmodule

Parameter可以用于模块间的数据传递,但是localparam仅用于本模块内使用,不能用于参数传递。Local多用于状态机的定义。

2.变量

变量是指程序运行可以改变其值的量 wire类型变量也叫网络类型变量,用于结构体实体之间的物理连接,如门与门之间,不能存储值,用连续赋值语句assign赋值。

wire a;assigan a=b;

将b的结点连接到连线a上。两个实体之间的连线即时wire类型变量。 reg类型变量,也叫寄存器变量,必须在always语句里使用 reg[n-1:0]a;表示n位位宽的寄存器,如reg[7:0]a;表示定义8位位宽的寄存器a。如下为D触发器。

module top(d,clk,q); input d; input clk; output reg q; always@(posedge clk) begin q<=d; end endmodule

数据选择器,组合电路

module top(a,b,c,d,sel,Mux); input a; input b; input c; input d; input [1:0] sel; output reg Mux; always @(sel or a or b or c or d) begin case(sel) 2'b00:Mux = a; 2'b01:Mux = b; 2'b10:Mux = c; 2'b11:Mux = d; endcase end endmodule

3.运算符

(1)算术运算符(+,-.*,/,%) "/"除法运算符 7/3=2 "%"取模运算符7%3=1 (2)赋值运算符(=,<=) =阻塞赋值 <=非阻塞赋值 阻塞赋值为执行完成一条赋值语句,再执行下一条,可理解为顺序执行。 非阻塞赋值可理解为并行执行,不考虑顺序。 代码:

module top(din,a,b,c,clk); input din; input clk; output reg a,b,c; always @(posedge clk) begin a = din; b = a; c = b; end endmodule

激励文件:

`timescale 1 ns/1 ns module top_tb(); reg din; reg clk; wire a,b,c; initial begin din = 0; clk = 0; forever begin #({$random}%100) din = ~din; end end always #10 clk = ~clk; top t0(.din(din),.a(a),.b(b),.c(c),.clk(clk)); endmodule

需要仿真

(3)关系运算符(>,<,>=,<=,==,!=) (4)逻辑运算符(&&,||,!)

(5)条件运算符(?😃 (6)位运算符(,|,^,&,^) (7)位移运算符(<<,>>) (8)拼接运算符({}) “{}”拼接运算符,将多个信号按位拼接,如{a[3:0],b[1:0]}将a的低4位,b的低2位拼接成6位数据。 {n{1’b0}}表示n位的o拼接 例如:{8{1’b0}}表示为8’b0000_0000 {n{a[3:0]}}表示将n个a[3:0]拼接。

4.组合逻辑

1.与门

module top(a,b,c); input a; input b; input c; assign c - a & b; endmodule

2.或门

module top(a,b,c); input a; input b; input c; assign c = a | b; endmodule

3.非门

module top(a,b); input a; output b; assign b = ~a; endmodule

4.异或门

module top(a,b,c); input a; input b; output c; assign c = a ^ b; endmodule

5.比较器

module top(a,b,c); input a; input b; output c; assign c=>a > b; endmodule

6.半加器 半加器不考虑来自低位的进位,所以称为半加器,sum表示相加结果,count表示进位,真值表可以表示如下:

module top(a,b,sum,count); input a; input b; output sum; output count; assign sum = a ^ b; assign count = a & b; endmodule

仿真

7.全加器 全加器需要加上低位来的进位信号cin,真值表如下:

module top(cin,a,b,sum,count); input cin; input a; input b; output sum; output count; assign {count,sum} = a + b +cin; endmodule

仿真

8.乘法器 乘法器表示也很简单,利用a*b

module top(a,b,c); input [1:0]a; input [1:0]b; output [3:0]c; assign c =a * b; endmodule

9.数据选择器 通过选择信号,选择不同的输入信号输出到输出端,四选一数据选择器,sel[1:0]为选择信号,a,b,c,d为输入信号,Mux为输出信号。 代码:

module top(a,b,c,d,sel,Mux); input a; input b; input c; input d; input [1:0] sel; output reg Mux; always @(sel or a or b or c or d) begin case(sel) 2'b00:Mux = a; 2'b01:Mux = b; 2'b10:Mux = c; 2'b11:Mux = d; endcase end endmodule

10.3-8译码器 3-8译码器是一个很常用的器件,真值表如下,根据A2,A1,A0的值得出不同的结果

代码

module top(addr,decoder); input [2:0] addr; output reg [7:0] decoder; always @ (addr) begin case(addr) 3'b000 : decoder = 8'b1111_1110; 3'b001 : decoder = 8'b1111_1101; 3'b010 : decoder = 8'b1111_1011; 3'b011 : decoder = 8'b1111_0111; 3'b100 : decoder = 8'b1110_1111; 3'b101 : decoder = 8'b1101_1111; 3'b110 : decoder = 8'b1011_1111; 3'b111 : decoder = 8'b0111_1111; end endmodule

9.D触发器

D触发器在时钟的上升沿或下降沿存储输出,输出与时钟跳变之前输出信号的状态相同。

module top(d,clk,q); input d; input clk; output reg q; always @ (posedge clk) begin q <= d; end endmodule

10.两级D触发器 两级D触发器,同一时刻两级D触发器输出端额数据不同

module top (d,clk,q,q1); input d; input clk; output reg q; output q1; always @(posedge clk) begin q <= d; end always @ (posedge clk) begin q1 < q; end endmodule

11.带异步复位的D触发器 异步复位独立于时钟,一旦异步复位信号有效,就出发复位操作。 module top(d,rst,clk,q); input d; input rst; input clk; output reg q; always @(posedge clk or negedge rst) begin if(rst == 1’b0) q <= 0; else q <= d; end endmodule 12.带异步复位同步清零的D触发器 异步复位独立于时钟操作,同步清零是同步于时钟信号。

module top(d,rst,clr,clk,q); input d; input rst; input clr; input clk; output reg q; always @(posedge clk or negedge rst) begin if(rst ==1'b0) q <= 0; else if(clr ==1'b1) q <= 0; else q<= d; end endmodule

13.移位寄存器 移位寄存器指的是每个时钟脉冲到来时,向左或向右移动一位,由于D触发器的特性,数据输出同步于时钟边沿,每个D触发器的输出q等于前一个D触发器输出的值,从而实现移位操作功能。

module top(d,rst,clk,q); input d; input rst; input clk; output reg[7:0] q; always @(posedge clk or negedge rst) begin if(rst == 1'b0) q <= 0; else q <= {q[6:0],d};//向左移位 //q<= {d,q[7:1]};//向右移位 end endmodule

14.单口RAM 单口RAM的写地址与读地址共用一个地址,代码如下reg[7:0] ram[63:0]意思定义了64个8位宽度的数据。其中定义了addr_reg可以保持度地址。

module top ( input [7:0] data, input [5:0] addr, input wr, input clk, output [7:0] q; ) reg [7:0] ram[63:0];//declare ram reg [5:0] ADDR_REG; //addr always @(posedge clk) begin if(wr) ram[addr] <= data; addr_reg <= addr; end assign q = ram[addr_reg];//read data endmodule

15.伪双口RAM 伪双口RAM的读写地址是独立的,可以随机选择写或读地址,同时进行读写操作。

module top ( input [7:0] data, input [5:0] write_addr, input [5:0] read_addr, input [5:0] read+addr, input wr, input rd, input clk, output reg[7:0] q ); reg [7:0] ram[63:0]; //declare ram register reg [5:0] addr_reg; always @(posedge clk) begin if(wr) ram[write_addr] <= data; if(rd) q <= ram[read_addr]; end endmodule

16.真双口RAM 真双口RAM有两套控制线,数据线,容许两个系统对其进行读写操作

module top ( input [7:0] data_a,data_b, input [5:0] addr_a,addr_b, input wr_a,wr_b, input rd_a,rd_b, input clk, output reg [7:0] q_a,q_b ); reg [7:0] ram[63:0]; //Port A always @(posedge clk) begin if(wr_a) //write begin ram[addr_a] <= data_a; q_a <= data_a; end if(rd_a) q_a <= ram[addr_a]; end // Port B always @(posedge clk) begin if(wr_b) //write begin ram[addr_b] <= data_b; q_b <=data_b; end if(rd_b) q_b <= ram[addr_b]; end endmodule

17.单口ROM ROM是用来存储数据的,可以按照下面代码初始化ROM,但是这种方法处理最大容量的ROMiu比较麻烦。

module top ( input [3:0] addr, input clk, output reg [7:0] q ); always @ (posedge clk) begin case(addr) 4'd0: q<=8'd15; 4'd1: q<=8'd24; 4'd2: q<=8'd100; 4'd3: q<=8'd78; 4'd4: q<=8'd98; 4'd5: q<=8'd105; 4'd6: q<=8'd86; 4'd7: q<=8'd254; 4'd8: q<=8'd76; 4'd9: q<=8'd35; 4'd10: q<=8'd120; 4'd11: q<=8'd85; 4'd12: q<=8'd37; 4'd13: q<=8'd19; 4'd14: q<=8'd22; 4'd15:q<=8'd67; default: q<=8'd0; endcase end endmodule

本节介绍了组合逻辑和时序逻辑中常用的模块,希望在以后的学习中能够深入理解,在代码中多运用,多思考,有利于快速提升水平。

最新回复(0)