Vivado下组合逻辑模块的仿真 您所在的位置:网站首页 vivado如何关联modelsim Vivado下组合逻辑模块的仿真

Vivado下组合逻辑模块的仿真

2023-06-01 11:19| 来源: 网络整理| 查看: 265

文章目录 与门或门非门异或门同或门比较器半加器全加器乘法器数据选择器3-8 译码器三态门 组合逻辑电路的特点是任意时刻的输出仅仅取决于输入信号,输入信号变化,输出立即变化,其变化不依赖于时钟。 本文中的例子中模块名都是gate,仿真测试文件中的模块名都是sim_gate。如果你在一个工程下创建了好几个.v文件,要运行其中的一个仿真,可以选中该文件,点击Set as Top,这样仿真的就是置于顶部的那个文件了。

与门

与门的代码如下。

module gate(a,b,c); input a; input b; output c; assign c = a & b; endmodule

仿真测试代码如下。

`timescale 1ns / 1ps module sim_gate(); reg a; reg b; wire c; initial begin a = 0; b = 0; forever begin #({$random}%100) //生成一个0-99的随机数,以 ns 为单位延迟该随机数的时长 a = ~a; #({$random}%100) b = ~b; end end gate uut_gate( .a(a), .b(b), .c(c) ); endmodule

与门的仿真结果如下图所示,仿真运行时间设置为1us。 在这里插入图片描述 通过仿真图可以看出来,两个输入都为1时,输出结果才是1。 与门的RTL图如下。 在这里插入图片描述 如果上述例子中的a和b位宽大于1,比如a和b的位宽均为4,那么a&b就是对应位的相与,仿真结果如下图所示。 在这里插入图片描述 这时RTL图就是下图所示的这样。 在这里插入图片描述

或门

或门的代码只需要将与门代码中的"&“改为”|"即可。 或门的仿真结果如下图所示。 在这里插入图片描述 通过上面的输出图可以看到,两个输入中只要有一个为1,输出结果就是1。 或门的RTL图如下。 在这里插入图片描述

非门

非门的代码比与门的代码更简单,不再需要变量c,b=~a即可,然后把仿真文件中的代码删减一下即可。 非门的仿真结果如下图所示。 在这里插入图片描述 非门的输出就是将输入取反。 非门的RTL图如下。 在这里插入图片描述

异或门

异或门的代码只需要将与门代码中的"&“改为”^"即可。 异或门的仿真结果如下图所示。 在这里插入图片描述 通过上图可以看到,两个输入不同时,输出为1,输入相同时,输出为0。 异或门的RTL图如下。 在这里插入图片描述

同或门

同或门的代码只需要将与门代码中的"&“改为”^~"即可。 同或门的仿真结果如下图所示。 在这里插入图片描述 通过上图可以看到,两个输入相同时,输出为1,输入不同时,输出为0。 同或门的RTL图如下。 在这里插入图片描述

比较器

比较器这里以 c=a>b 为例说明,如果 a>b,那么c的值为1,否则为0。对于二进制来说,只有a=1,b=0时,c=1。 比较器的代码只需要将与门代码中的"&“改为”>"即可。 比较器的仿真结果如下图所示。 在这里插入图片描述 该例子中,输入a大于输入b时,即只有 a=1,b=0 时,输出才为1。 比较器的RTL图如下。 在这里插入图片描述

半加器

半加器和全加器是算术运算电路中的基本单元,由于半加器不考虑从低位来的进位,所以称为半加器。 半加器的真值表如下表所示。

absumcount0000011010101101

半加器的代码如下。

module gate(a,b,sum,count); input a; input b; output sum; output count; assign sum = a + b; assign count = a & b; endmodule

仿真测试代码如下。

`timescale 1ns / 1ps module sim_gate(); reg a; reg b; wire sum; wire count; initial begin a = 0; b = 0; forever begin #({$random}%100) a = ~a; #({$random}%100) b = ~b; end end gate uut_gate( .a(a), .b(b), .sum(sum), .count(count) ); endmodule

半加器的仿真结果如下图所示。 在这里插入图片描述 将上图输出和其真值表对照,输出与预期一致。 半加器的RTL图如下。 在这里插入图片描述

全加器

全加器在半加器的基础上考虑来自低位的进位,因此实现起来更加复杂,参与运算的数也比半加器多一个。 全加器的真值表如下表所示。

abcinsumcount0000001010100101100100110011011010111111

全加器的代码如下。

module gate(a,b,sum,count,cin); input a; input b; input cin; output sum; output count; assign {count,sum} = a + b + cin; //通过一个位拼接运算达到计算count和sum的目的 endmodule

仿真测试代码如下。

`timescale 1ns / 1ps module sim_gate(); reg a; reg b; reg cin; wire sum; wire count; initial begin a = 0; b = 0; cin = 0; forever begin #({$random}%100) a = ~a; #({$random}%100) b = ~b; #({$random}%100) cin = ~cin; end end gate uut_gate( .a(a), .b(b), .cin(cin), .sum(sum), .count(count) ); endmodule

全加器的仿真结果如下图所示。 在这里插入图片描述 将上图输出和其真值表对照,输出与预期一致。 全加器的RTL图如下。 在这里插入图片描述

乘法器

乘法器这里在设置时将两个乘数设置为两位的,这样其最大表示十进制的3,相乘后最大表示十进制的9,因此需要4位二进制的输出。 乘法器的代码如下。

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

仿真测试代码如下。

module sim_gate(); reg[1:0] a; reg[1:0] b; wire[3:0] c; initial begin a = 0; b = 0; forever begin #({$random}%100) a = {$random}%4; #({$random}%100) b = {$random}%4; end end gate uut_gate( .a(a), .b(b), .c(c) ); endmodule

乘法器的仿真结果如下图所示。 在这里插入图片描述 将输入和输出以无符号的十进制数显示,可以清楚地看到两数相乘的结果。 乘法器的RTL图如下。 在这里插入图片描述

数据选择器

下面这个例子是四选一数据选择器,选择信号是两位,输入信号是4个,可以将其设置为1位,也可以设置为多位,输出信号与输入信号的位数一致。 四选一数据选择器的选择情况如下表所示。

selmux00(0)a01(1)b10(2)c11(3)d

数据选择器的代码如下。

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

仿真测试代码如下。

`timescale 1ns / 1ps module sim_gate(); reg[2:0] a; reg[2:0] b; reg[2:0] c; reg[2:0] d; reg[1:0] sel; wire[2:0] mux; initial begin a = 0; b = 0; c = 0; d = 0; forever begin #({$random}%100) a = {$random}%8; #({$random}%100) b = {$random}%8; #({$random}%100) c = {$random}%8; #({$random}%100) d = {$random}%8; end end initial begin sel = 2'b00; #250 sel = 2'b01; #250 sel = 2'b10; #250 sel = 2'b11; end gate uut_gate( .a(a), .b(b), .c(c), .d(d), .sel(sel), .mux(mux) ); endmodule

输入是1位时,数据选择器的仿真结果如下图所示。 在这里插入图片描述 可以看到,数据选择器的输出是根据代码编写的那样进行的。 输入是3位时,数据选择器的仿真结果如下图所示。 在这里插入图片描述 为了直观的看到不同,将输入位数设置为3位的,输出也是按照代码编写的那样进行的。 输入是1位时,数据选择器的RTL图如下。 在这里插入图片描述 输入是3位时,数据选择器的RTL图如下。 在这里插入图片描述

3-8 译码器

3-8 译码器的译码情况如下表所示。

addrdecoder000(0)11111110001(1)11111101010(2)11111011011(3)11110111100(4)11101111101(5)11011111110(6)10111111111(7)01111111

3-8 译码器的代码如下。

module gate(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; endcase end endmodule

仿真测试代码如下。

`timescale 1ns / 1ps module sim_gate(); reg[2:0] addr; wire[7:0] decoder; initial begin addr = 3'b000; #125 addr = 3'b001; #125 addr = 3'b010; #125 addr = 3'b011; #125 addr = 3'b100; #125 addr = 3'b101; #125 addr = 3'b110; #125 addr = 3'b111; end gate uut_gate( .addr(addr), .decoder(decoder) ); endmodule

3-8 译码器的仿真结果如下图所示。 在这里插入图片描述 由上述仿真结果可以看到,译码输出和代码中编写的是一致的。 3-8 译码器的RTL图如下。 在这里插入图片描述

三态门

三态门是FPGA中经常用到的器件,使能信号用于打开或关闭三态门。 三态门的代码如下。

module gate(en,in,out); input en; input in; output out; assign out = en ? in : 1'bz; endmodule

仿真测试代码如下。

`timescale 1ns / 1ps module sim_gate(); reg en; reg in; wire out; initial begin en = 1; #250 en = 0; #250 en = 1; #250 en = 0; end initial begin in = 0; forever begin #({$random}%100) in = ~in; end end gate uut_gate( .en(en), .in(in), .out(out) ); endmodule

三态门的仿真结果如下图所示。 在这里插入图片描述 可以看到,使能信号为1时,输出等于输入信号,使能信号为0时,输出为高阻状态。 三态门的RTL图如下。 在这里插入图片描述 接下来在三态门的基础上增加一个输入输出口,将两个三态门进行关联,从而实现双向的输入和输出。 在这里插入图片描述 如上图,当en0为0,en1为1时,1通道打开,双向IO bio就等于1通道的in1,故1通道向外发送数据,0通道接收数据,out0等于bio;当en0为1,en1为0时,0通道打开,双向IO bio就等于0通道的in0,0通道向外发送数据,1通道接收数据,out1等于bio。 双向的输入和输出的代码如下。

module gate(en,in,out,bio); input en; input in; output out; inout bio; assign bio = en ? in : 1'bz; assign out = bio; endmodule

仿真测试代码如下。

module sim_gate(); reg en0; reg in0; wire out0; reg en1; reg in1; wire out1; wire bio; initial begin en0 = 0; en1 = 1; #200 en0 = 0; en1 = 0; #50 en0 = 1; en1 = 0; #200 en0 = 0; en1 = 0; #50 en0 = 0; en1 = 1; #250 en0 = 1; en1 = 0; end initial begin in0 = 0; in1 = 0; forever begin #({$random}%100) in0 = ~in0; #({$random}%100) in1 = ~in1; end end gate uut_gate0( .en(en0), .in(in0), .out(out0), .bio(bio) ); gate uut_gate1( .en(en1), .in(in1), .out(out1), .bio(bio) ); endmodule

双向的输入和输出的仿真结果如下图所示。 在这里插入图片描述 这里out0和out1的值是一样的,因为在定义时,它们都等于bio的值。

参考资料: ZYNQ 开发平台 FPGA 教程 AX7020



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有