【FPGA实战篇六】四位数据选择器与D触发器、移位寄存器原理详解及功能验证

一、数据选择器

1、原理详解

  • 什么是数据选择器?
    数据选择器根据给定的输入地址代码,从一组输入信号中选出指定的一个送至输出端的组合逻辑电路。有时候也叫做多路选择器或者多路调制器

  • 数据选择器基本定义
    在多路数据传输过程中,能够根据需要将其中任意一路选出来的电路,叫做数据选择器。
    在这里插入图片描述

  • 逻辑功能
    数据选择器的逻辑功能是在地址选择信号控制下,从多路数据中选择一路数据作为输出信号。

  • 分类
    2选1,4选1、8选1和16选1等类型的数据选择器。

2、工作方式

结合上图,给A1A0一组信号 比如1 0 那么就相当于给了他一个2进制数字2 也就相当于选通了D2这个输入端这个时候 输出Y 输出的就是D2的信号D2是什么 Y就输出什么。

控制 选择的输出源
A1 A0 Y
0 0 D0
0 1 D1
1 0 D2
1 1 D3

二、四位数据选择器功能验证

1、Verilog实现四位选择器

用Verilog编写一个简单的四位选择器

module multiplexer_s(

       input         clk      ,
       input         rst_n    ,

       input         din_a    ,
       input         din_b    ,
       input         din_c    ,
       input         din_d    ,

       input  [1:0]  sel      ,

       output        dout     
);
    
    //信号定义
    reg          data_dout;
    
    always @(posedge clk or negedge rst_n) begin
        if(!rst_n)begin
          data_dout <= 2'b00;
        end
        else begin
          case(sel)
              2'b00:  data_dout <= din_a ;
              2'b01:  data_dout <= din_b ;
              2'b10:  data_dout <= din_c ;
              2'b11:  data_dout <= din_d ;
              default:data_dout <= 2'b00 ;
          endcase
        end
    end

    assign dout = data_dout;


endmodule

顶层模块

module multiplexer(

    input             clk    ,
    input             rst_n  ,

    output            dout
);

    wire             din_a  ;
    wire             din_b  ;
    wire             din_c  ;
    wire             din_d  ;   

    wire   [1:0]     sel    ;

    //模块例化
    multiplexer_s    u_multiplexer
    (
       .din_a        (din_a    ) ,
       .din_b        (din_b    ) ,
       .din_c        (din_c    ) ,
       .din_d        (din_d    ) ,
       .sel          (sel      ) ,
       .dout         (dout     ) ,
       .rst_n        (rst_n    ) ,
       .clk          (clk      )
    );
    
endmodule

2、创建工程

对于工程创建的详细步骤,可参考此篇文章:
数码管实现秒表计数
工程创建完成后,将四位数据选择器源码导入工程
在这里插入图片描述
将导入项目文件进行全编译
在这里插入图片描述
查看RTL电路图
在这里插入图片描述

3、更改系统内源和探针

点击quartus右上角IP Catalog或者【Tools】→【IP Catalog】
在这里插入图片描述
更改ip
在这里插入图片描述
将小窗展开,点击OK
在这里插入图片描述
配置source和probes的值,然后点击generate HDl…
在这里插入图片描述
再点击generate
在这里插入图片描述
生成完成后,点击close
在这里插入图片描述
可以在prj文件夹下看到生成的issp文件
在这里插入图片描述
在文件目录下找到issp.v文件
在这里插入图片描述
打开文件,将此文件中的该部分例化到四位选择器中

module issp (
		input  wire [31:0] probe,  //  probes.probe
		output wire [31:0] source  // sources.source
	);

例化后各部分代码
①multiplexer.v

module multiplexer(

    input             clk    ,
    input             rst_n  ,

    output            dout
);

    wire             din_a  ;
    wire             din_b  ;
    wire             din_c  ;
    wire             din_d  ;   

    wire   [1:0]     sel    ;

    //模块例化
    multiplexer_s    u_multiplexer
    (
       .din_a        (din_a    ) ,
       .din_b        (din_b    ) ,
       .din_c        (din_c    ) ,
       .din_d        (din_d    ) ,
       .sel          (sel      ) ,
       .dout         (dout     ) ,
       .rst_n        (rst_n    ) ,
       .clk          (clk      )
    );
    wire        [31:0]  probe   ;

    issp u_issp
    (
        .probe          (probe ),
        .source          ({
    
    sel,din_a,din_b,din_c,din_d})
    );
endmodule

将设置的issp实体加入工程文件中
在这里插入图片描述
对整个工程进行全编译
在这里插入图片描述

4、逻辑分析

【Tools】→【Signal Tap Logic Analyzer】
在这里插入图片描述
连接到开发板,先进行烧录,确保驱动无异常
在这里插入图片描述
选择所使用的驱动以及下载文件,设置好采样时钟与深度
在这里插入图片描述
下载文件
在这里插入图片描述
设置时钟,点击Clock后面的三个小点,出现如示界面
在这里插入图片描述
选中Filter下拉框中的Design Entry(all names)。再点击list
在这里插入图片描述
再出现的界面中选择采样时钟
在这里插入图片描述
将.sof文件进行下载
在这里插入图片描述
选择【Tools】→【In_System Source and Probes Editor】
在这里插入图片描述
将.sof文件下载进去
在这里插入图片描述
出现如示界面,将source展开赋值,可以看到输出变化
在这里插入图片描述
点击运行图标,可看到【Signal Tap Logic Analyzer】中出现如下波形
![在这里插入图片描述](https://img-blog.csdnimg.cn/c570b9f8dbab459db28de3b44260200c.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA5aSp5Lya5pm05bCx5Lya5pqX,size_20,color_FFFFFF,t_70,g_se,x_16
点击红色方框图标,进行自往返分析
在这里插入图片描述
通过对source进行相应的赋值,可以观察到波形的变化。

5、功能验证

片选信号示意图
在这里插入图片描述

{sel,din_a,din_b,din_c,din_d}中{}方式是由高到低的,拼接不允许出现未指明位宽的变量。

根据此段代码块,验证其逻辑功能:

 case(sel)
              2'b00:  data_dout <= din_a ;
              2'b01:  data_dout <= din_b ;
              2'b10:  data_dout <= din_c ;
              2'b11:  data_dout <= din_d ;
              default:data_dout <= 1'b0  ;
          endcase

当片选信号sel为00时,data_out输出din_a
在这里插入图片描述
当片选信号sel为01时,data_out输出din_b
在这里插入图片描述
当片选信号sel为10时,data_out输出din_c
在这里插入图片描述
当片选信号sel为11时,data_out输出din_d
在这里插入图片描述

三、D触发器

1、基本概念

  • D触发器是一个具有记忆功能的,具有两个稳定状态的信息存储器件,是构成多种时序电路的最基本逻辑单元,也是数字逻辑电路中一种重要的单元电路。
  • D触发器在时钟脉冲CP的前沿(正跳变0→1)发生翻转,触发器的次态取决于CP的脉冲上升沿到来之前D端的状态,即次态=D。因此,它具有置0、置1两种功能。由于在CP=1期间电路具有维持阻塞作用,所以在CP=1期间,D端的数据状态变化,不会影响触发器的输出状态。
    在这里插入图片描述

2、工作原理

SD 和RD 接至基本RS 触发器的输入端,分别是预置和清零端,低电平有效。当SD=0且RD=1时,不论输入端D为何种状态,都会使Q=1,Q=0,即触发器置1;当SD=1且RD=0时,触发器的状态为0,SD和RD通常又称为直接置1和置0端。

工作流程

  • CP=0时,与非门G3和G4封锁,其输出Q3=Q4=1,触发器的状态不变。同时,由于Q3至Q5和Q4至Q6的反馈信号将这两个门打开,因此可接收输入信号D,Q5=D,Q6=Q5非=D非;
  • 当CP由0变1时触发器翻转。这时G3和G4打开,它们的输入Q3和Q4的状态由G5和G6的输出状态决定。Q3=Q5非=D非,Q4=Q6非=D。由基本RS触发器的逻辑功能可知,Q=Q3非=D;

四、D触发器功能验证

1、Verilog实现简易D触发器

D触发器模块
data_flip_flop.v

module data_flip_flop(

    input               clk      ,//系统时钟
    input               rst_n    ,//复位信号
    input               en       ,//使能信号(cp)
    input               d        ,//D触发器输入       
     
    output              q        ,//输出q
    output              q_n       //输出非q
);
    

    //信号定义
    reg            dout_q  ;//输出定义

    always @(posedge clk or negedge rst_n) begin
        if(~rst_n)begin
          dout_q <= 0;
        end
        else if(en) begin
          dout_q <= d;
        end
        else begin
          dout_q <= 0;
        end
    end

    assign q   =  dout_q ;
    assign q_n = ~dout_q ;
endmodule

顶层模块
data_flip_flop_top.v

module data_flip_flop_top(

    input       clk    ,
    
    output      q      ,
    output      q_n
);

   //信号定义
   wire         d     ;
   wire         en    ;
   wire         rst_n ;
   

   //模块例化
   data_flip_flop     u_data_flip_flop
   (
    .clk      ( clk  ),
    .rst_n    ( rst_n),
    .en       (  en  ), 
    .d        (   d  ),        
   
    .q        ( q    ),   
    .q_n      ( q_n  )  
   );
endmodule

查看有Verilog生成的RTL原理图
在这里插入图片描述
点击+展开,查看组成电路的结构
在这里插入图片描述

2、步骤略解(详细步骤雷同数据选择器)

配置ip,改名并保存在ip(知识产权)目录下
在这里插入图片描述
更改系统内源与探针
在这里插入图片描述
将生成的issp文件添加到工程中
在这里插入图片描述
添加后如示
在这里插入图片描述
将此部分代码例化到顶层模块

module issp (
		input  wire [7:0] probe,  //  probes.probe
		output wire [7:0] source  // sources.source
	);

例化后的顶层模块源码

module data_flip_flop_top(

    input       clk    ,
    
    output      q      ,
    output      q_n
);

   //信号定义
   wire         d     ;
   wire         en    ;
   wire         rst_n ;

   wire   [7:0] probe ;
   

   //模块例化
   data_flip_flop     u_data_flip_flop
   (
    .clk      ( clk  ),
    .rst_n    ( rst_n),
    .en       (  en  ), 
    .d        (   d  ),        
   
    .q        ( q    ),   
    .q_n      ( q_n  )  
   );

   issp  u_issp
   (
      	.source    ( {
    
    rst_n,en,d} ) ,
      	.probe     (   probe      ) 
   );
endmodule

3、逻辑分析

出GIF动图,给大家看看步骤
在这里插入图片描述
双击界面空白,添加信号
在这里插入图片描述
出现红色则代表出错,所添加的为wire型信号,需要更改
在这里插入图片描述
鼠标右键单击【select all】,再次鼠标右键点击【delete】
在这里插入图片描述
再次双击空白,添加信号
在这里插入图片描述
添加信号如图所示
在这里插入图片描述
在内源探针编辑器中,将.sof文件下载进去
在这里插入图片描述
在【Tap】界面,按照图示箭头一次操作
在这里插入图片描述
最后出现如示界面
在这里插入图片描述
下面,我们通过赋值验证D触发器的功能

4、功能验证

信号示意图
在这里插入图片描述
结果如示
在这里插入图片描述

五、移位寄存器

移位 寄存器可以用来寄存代码,还可以用来实现数据的串行—并行转换、数值的运算以及数据的处理等。

1、基本概念

  • 移位寄存器(外文名:shift register)在数字电路中,是一种在若干相同时间脉冲下工作的以触发器为基础的器件,数据以并行或串行的方式输入到该器件中,然后每个时间脉冲依次向左或右移动一个比特,在输出端进行输出。
  • 移位寄存器可分为一维和多维移位寄存器。多维移位寄存器的输入、输出的数据本身就是一些列位。
    在这里插入图片描述

2、原理介绍

四位移位寄存器的原理图如图所示。F 0、F 1、F 2、F 3是四个边沿触发的D触发器,每个触发器的输出端Q接到右边一个触发器的输入端D。因为从时钟信号CP的上升沿加到触发器上开始到输出端新状态稳定地建立起来有一段延迟时间,所以当时钟信号同时加到四个触发器上时,每个触发器接收的都是左边一个触发器中原来的数据(F 0接收的输入数据D 1)。寄存器中的数据依次右移一位。

3、寄存器分类

  • 根据移位方向,常把它分成左移寄存器、右移寄存器和双向移位寄存器三种。
  • 根据移位数据的输入-输出方式,又可将它分为串行输入-串行输出、串行输入-并行输出、并行输入-串行输出和并行输入-并行输出四种电路结构。
  • 此外,有些移位寄存器还具有预置数功能,可以把数据并行地置入寄存器中。
  • 利用移位寄存器能进行数据运算、数据处理,实现数据的串行—并行互相转换,还可接成各种移位寄存器式计数器,如环形计数器、扭环形计数器等。

六、移位寄存器功能验证

1、Verilog实现移位寄存器

shift_reg.v

module shift_reg (
   
   input           clk     ,
   input           rst_n   ,
   input   [3:0]   din     ,  
   input           dsr     ,
   input           en      ,
   input   [1:0]   mode    ,

   output  [3:0]   dout    ,
   output          one_out 
);

    //信号定义
    reg        [3:0]      dout_r    ;
    reg                   one_out_r ;

    //输出
    always @(posedge clk or negedge rst_n) begin
        if(~rst_n)begin
          dout_r <= 0;
          one_out_r <= 0;
        end
        else if(en)begin
          case({
    
    mode,dsr})
              3'b000:begin
              dout_r <= dout_r;
              one_out_r <= 0;
              end
              3'b001:begin
              dout_r <= dout_r;
              one_out_r <= 0;
              end
              3'b010:begin
              dout_r <= {dsr,dout_r[3:1]};
              one_out_r <= dout_r[0];
              end
              3'b011:begin
              dout_r <= {
    
    dsr,dout_r[3:1]};
              one_out_r <= dout_r[0];
              end
              3'b100:begin
              dout_r <= {dout_r[2:0],dsr};
              one_out_r <= dout_r[3];
              end
              3'b101:begin
              dout_r <= {
    
    dout_r[2:0],dsr};
              one_out_r <= dout_r[3];
              end
              3'b110:begin
              dout_r <= din;
              one_out_r <= 0;
              end
               3'b111:begin
              dout_r <= din;
              one_out_r <= 0;
              end
              default:begin
              dout_r <= dout_r;
              one_out_r <= 0;
              end
            endcase
    end

    else begin
      dout_r <= 0;
      one_out_r <= 0;
    end
    end
    assign dout = dout_r;
    assign one_out = one_out_r;
    
endmodule

shift_reg_top.v

module shift_reg_top (
   
   input clk,
   input rst_n,

   output [3:0] dout,
   output       one_out
);

   //信号定义
   wire    en;
   wire  [3:0] din;
   wire        dsr;
   wire        mode;

   //模块例化
   shift_reg   u_shift_reg
   (
      .clk     (clk),
      .rst_n   (rst_n),
      .din     (din),
      .dsr     (dsr),
      .en      (en),
      .mode    (mode),
      .dout    (dout),
      .one_out (one_out)
   );
    
endmodule

查看RTL图
在这里插入图片描述
创建issp,并对内源以及探针进行例化

module shift_reg_top (
   
   input clk,
   input rst_n,

   output [3:0] dout,
   output       one_out
);

   //信号定义
   wire    en;
   wire  [3:0] din;
   wire        dsr;
   wire        mode;

   wire [12:0] probe;

   //模块例化
   shift_reg   u_shift_reg
   (
      .clk     (clk),
      .rst_n   (rst_n),
      .din     (din),
      .dsr     (dsr),
      .en      (en),
      .mode    (mode),
      .dout    (dout),
      .one_out (one_out)
   );

   issp u_issp
   (
       .source({
    
    en,din,dsr,mode}),
       .probe(probe)
   )
    
endmodule

2、功能验证


在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

Guess you like

Origin blog.csdn.net/QWERTYzxw/article/details/120667810