二、4【FPGA】简单的组合逻辑——设计多路选择器

目录

前言

理论学习

逻辑电路分类:

多路选择器

实战演练

一、设计规划

1.1 实验(项目)目标

1.2 硬件资源

二、程序设计

2.1、模块框图

2.2、波形图绘制

2.3、端口信号信息与真值表

2.4、代码编写

三、逻辑仿真

3.1、仿真文件编写

3.2、仿真波形图对比

四、上板验证

1、管脚约束

2、实际验证


前言

学习说明:以下为本人学习笔记

学习视频:是根据野火FPGA视频教程——第六讲
https://www.bilibili.com/video/BV1nQ4y1Z7zN?p=3

学习资料:《数字电子技术基础》清华大学出版社

理论学习

相关数字电路基础理论学习请参考本人的另一个笔记,可以让你深刻理解相关知识《数字电子技术基础》4.3 若干常用的组合逻辑电路 学习笔记_FPGA-桥的博客-CSDN博客《数字电子技术基础》常用的组合逻辑电路编码器和译码器、数据选择器和数据分配器、加法器、数值比较器、奇偶发生/校验器https://blog.csdn.net/ARM_qiao/article/details/124052097

逻辑电路分类:

  • 组合逻辑电路:电路的输出只与当时的输入有关,而与电路以前的状态无关。
  • 时序逻辑电路:电路的输出不仅与当时的输入有关,还与以前输入有关。

多路选择器

多路选择器别称数据选择器,在多路数据传送过程中能够根据需要将其任意一路选出来的电路叫做数据选择器,也称多路选择器(Data Selector)或多路开关(Multiplexer)。

现以双4选1数据选择器74HC153为例,说明它的工作原理。

实战演练

一、设计规划

1.1 实验(项目)目标

设计并实现2选1多路选择器,主要功能是通过控制信号S确定A路或B路作为输出信号。当S=1时,输出信号为O=A;当S=0时,信号输出为O=B。

1.2 硬件资源

使用按键与LED灯作为实验的模拟,选取KEY1、KEY2、KEY3分别作为信号A、信号B和选通信号S,LED灯D6作为输出信号O。

二、4【FPGA】简单的组合逻辑——设计多路选择器_第1张图片

二、4【FPGA】简单的组合逻辑——设计多路选择器_第2张图片

二、程序设计

2.1、模块框图

二、4【FPGA】简单的组合逻辑——设计多路选择器_第3张图片

2.2、波形图绘制

sel = 0时,out = in_2;sel = 1时,out = in_1

二、4【FPGA】简单的组合逻辑——设计多路选择器_第4张图片

2.3、端口信号信息与真值表

端口信号信息
信号 位宽 类型 功能描述
in1 1bit input 输入信号1
in2 1bit input 输入信号2
sel 1bit input 选通信号
out 1bit output 输出信号
端口真值表
输入(input) 输出(output)
in1 in2 sel out
0 1 0 1
1 0 0 0
0 1 1 0
1 0 1 1

2.4、代码编写

代码实现方式比较多,这里主要列举三种实现方法。

`timescale 1ns / 1ps
//
// Company: 追逐者——桥的小作坊
// Engineer: 
// 
// Create Date: 2022/04/10 09:19:21
// Design Name: 不同条件语句实现2-1数据选择器
// Module Name: mux2_1
// Project Name: MUX2_1
// Target Devices: Artix_7 野火开发板
// Tool Versions: Vivado 2018_3
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments: 学习代码
// 
//


module mux2_1(              //语法:module 模块名称 (端口信号列标);  
    input   wire    in_1 ,  //输入信号1,语法:输入输出方式 类型 位宽(当为1bit时可以省略,也可[0:0]) 名字
    input   wire    in_2 ,  //输入信号2,输入信号只能是,wire:线网型数据变量 
    input   wire    sel,    //选择信号,每行信号以‘,’结束,所有量后不加‘,’
    output  reg     out     //输出信号,输出变量类型既可以是wire型也可reg型,
                            //wire型:输出在assign语句中被赋值(即在“=”左边)
                            //reg型:输出在always块中被赋值(即在“<=”的左边)
    );                      //注意加“;”

//实现方式一:always 中 if-else 实现方法
///*    
    always@(*)            //"*"为通配符,表示只要 if 括号中的条件或赋值号右边的变量发生变化
                            //则立即执行下面的代码,“(*)”在此 always 中等价于“(sel, in1, in2)”写法
        if(sel == 1'b1)    
            //begin                //当“if...else...”中只有一个变量时不需要加“begin...end”
                out = in_1;
            //end
        else
            out = in_2;
//*/      
      
//实现方式二: always 中 case 实现方式 
/*
    always @(*)
        case(sel)
            1'b1 : out = in_1;
            1'b0 : out = in_2;
          //default : out = in_1;  //当case不能列举全部情况时需要加入default,这里可以省略
        endcase
*/

//实现方式三:assign中条件运算符(三元运算符)实现方式
/*
    assign out = (sel == 1'b1) ? in_1 : in_2;
*/
            
endmodule


有人可能会有稍稍的疑问,就是为什么 always 块中被赋值的一定要是 reg 型变量,他 并没有生成寄存器而是实现的的组合逻辑的功能?因为在 Verilog 语言中,寄存器的特点 是,它需要在仿真运行器件中保存其值,也就是说这个变量在仿真时需要占据内存空间, 而上面的 always 块只对 selin1in2 三个变量的输入敏感,如果没有这三个变量的变化事件,则 out 变量将需要保存其值,因此它们必须被定义为 reg 型变量,但是在综合之后,并不对应硬件锁存器或者触发器(后面会讲到什么时候会出现综合成这两种的情况)。

三、逻辑仿真

3.1、仿真文件编写

`timescale 1ns / 1ps
//
// Company: 追逐者——桥的小作坊
// Engineer: 
// 
// Create Date: 2022/04/10 11:20:04
// Design Name: 不同条件语句实现2-1数据选择器的仿真文件
// Module Name: tb_mux2_1
// Project Name: MUX2_1
// Target Devices: 
// Tool Versions: Vivado 2018_3
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//


module tb_mux2_1();             //不同的是在 testbench 中端口列表为空
                                //因为 testbench 不对外进行信号的输入输出,只是自己产生
                                //激励信号提供给内部实例化待测 RTL 模块使用,所以端口列表
                                //中没有内容,只是列出“()”,当然可以将“()”省略,括号
                                //后有个“;”不要忘记

//要在 initial 块和 always 块中被赋值的变量一定要是 reg 型
//在 testbench 中待测试 RTL 模块的输入永远是 reg 型变量
    reg in_1;
    reg in_2;
    reg sel;
    
//输出信号,我们直接观察,也不用在任何地方进行赋值
//所以是 wire 型变量(在 testbench 中待测试 RTL 模块的输出永远是 wire 型变量)
    wire out;
    
//initial 语句是可以被综合的,一般只在 testbench 中表达而不在 RTL 代码中表达
//initial 块中的语句上电后只执行一次,主要用于初始化仿真中要输入的信号
//初始化值在没有特殊要求的情况下给 0 或 1 都可以。如果不赋初值,仿真时信号
//会显示为不定态(ModelSim 中的波形显示红色)    
    initial 
        begin                   //在仿真中 begin...end 块中的内容都是顺序执行的,
                                //在没有延时的情况下几乎没有差别,看上去是同时执行的,
                                //如果有延时才能表达的比较明了;
                                //而在 rtl 代码中 begin...end 相当于括号的作用,
                                //在同一个 always 块中给多个变量赋值的时候要加上
            in_1 <= 1'b0;
            in_2 <= 1'b0;
            sel  <= 1'b0;
        end
    
//in_1:产生输入随机数,模拟输入端 1 的输入情况
    always #10 in_1 <= {$random} % 2;   //取模求余,只能产生1'b0、1'b1两个随机数
    always #10 in_2 <= {$random} % 2;   
    always #10 sel  <= {$random} % 2;    
    
//下面的语句是为了在 ModelSim 仿真中直接打印出来信息便于观察信号变化的状态
    initial
        begin 
            $timeformat(-12, 0, "ps", 6);    //设置时间格式:纳秒,小数点后0位,打印字符ps,
                                             //打印的最小量字符为6个
            
            //只要监测的变量(时间、in_1, in_2, sel, out)发生变化,就会打印相应的信息
            $monitor("@time %t:in_1=%b in_2=%b sel=%b out=%b",$time, in_1, in_2, sel, out);                                 
        end


//待测试RTL模块实例化,相当于将设计块放到激励块,即激励快调用设计块
    mux2_1   mut2_1_inst(                    
        .in_1(in_1),                        //.代表链接
        .in_2(in_2),
        .sel(sel),
        .out(out)
        );                                   
endmodule

运行RTL视图,可以看到代码原理图及管脚约束

二、4【FPGA】简单的组合逻辑——设计多路选择器_第5张图片

3.2、仿真波形图对比

二、4【FPGA】简单的组合逻辑——设计多路选择器_第6张图片

二、4【FPGA】简单的组合逻辑——设计多路选择器_第7张图片

 仿真波形图可以看出与绘制的波形图一致。

四、上板验证

1、管脚约束

二、4【FPGA】简单的组合逻辑——设计多路选择器_第8张图片

约束文件代码:

#按键引脚绑定
set_property IOSTANDARD LVCMOS33 [get_ports in_1]
set_property PACKAGE_PIN V17 [get_ports in_1]
set_property IOSTANDARD LVCMOS33 [get_ports in_2]
set_property PACKAGE_PIN W17 [get_ports in_2]
set_property IOSTANDARD LVCMOS33 [get_ports sel]
set_property PACKAGE_PIN AA18 [get_ports sel]

#led引脚绑定
set_property IOSTANDARD LVCMOS33 [get_ports out]
set_property PACKAGE_PIN M21 [get_ports out]

#4线spi模式
set_property CFGBVS VCCO [ current_design]
set_property CONFIG_VOLTAGE 3.3 [current_design]
set_property BITSTREAM.CONFIG.SPI_BUSWIDTH 4 [current_design]
set_property CONFIG_MODE SPIx4  [current_design]
set_property BITSTREAM.CONFIG.CONFIGRATE 50 [current_design]

2、实际验证

 二、4【FPGA】简单的组合逻辑——设计多路选择器_第9张图片二、4【FPGA】简单的组合逻辑——设计多路选择器_第10张图片

新语法总结
重点掌握
1 always 块描述组合逻辑的用法
2 assign 语句的用法
3 initial 的用法 (不可综合,常用于 Testbech 中初始化信号,但也可以在可综合的模块中
用于初始化寄存器)
4 if-else 的用法
5 case 的用法
6 、条件运算符(三元运算符)的用法
7 begin...end (对多条语句赋值时使用,因为我们设计 RTL 代码的原则是一个 always 块中
最好只有一个变量,所以 begin...end RTL 代码中几乎很少使用,而在 Tetbench 中使用的
更多)
8 # 延时 (不可综合,但允许在可综合的模块中使用,其延时单位仍由可综合模块中的
`timescale 决定,但是综合时被其延时时间被综合器忽略)
9 `timescale (配合“ # ”允许在可综合模块中使用)
10 = (赋值号的一种,阻塞赋值,在可综合的模块中表达组合逻辑的语句时使用)
11 == (常用的比较运算符)
12 // (注释一行代码时使用)
一般掌握
1 $timeformat Testbench 中的用法 (不可综合)
2 $monitor Testbench 中的用法 (不可综合)
3 $time Testbench 中的用法 (不可综合)
知识点总结
1 、功能模块的书写结构、格式 (端口列表推荐使用 Verilog-2001 标准)
2 、仿真模块的书写结构、格式 (端口列表中没有任何信号)
3 、如何进行实例化调用 (信号名的对应关系和连线)

你可能感兴趣的:(#,二,Xilinx,Artix-7基础教程(完),fpga开发,Verilog,HDL,硬件描述语言,数字电路技术)