第六篇 移位寄存器

2024-06-04 11:52
文章标签 移位 寄存器 第六篇

本文主要是介绍第六篇 移位寄存器,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

实验六 移位寄存器

6.1实验目的

  1. 掌握移位寄存器的工作原理;

  2. 掌握利用移位寄存器实现串行与并行的相互转换;

  3. 掌握使用移位寄存器实现乘除法运算;

6.2 原理介绍

6.2.1 基本移位寄存器

在实验四中,我们主要介绍了寄存器的结构及功能,一个N位的寄存器可以存储N位二进制数,即寄存器具有存储数据的功能。移位寄存器(Shift Register)除了具有存储数据的功能以外,还具有移位功能。它们在同一时钟脉冲作用下,可将寄存的二进制数据依次移位,用来实现数据的串行/并行或并行/串行的转换、数值运算以及其他数据处理功能。

将若干个D触发器串接级联在一起构成的具有移位功能的寄存器叫移位寄存器。图6.1是由四个D触发器构成的一个4位移位寄存器的逻辑电路。串行二进制数据从输入端D_{SI}输入,左边触发器的输出作为右邻触发器的数据输入。

图6.1 用D触发器构成的4位移位寄存器

若将串行数据D_3D_2D_1D_0从高位(D_3)至低位(D_0)按时钟序列依次送到D_{SI}端,经过第一个时钟脉冲后,Q_0=D_3。由于跟随D_3后面的是D_2,因此经过第二个时钟脉冲后,触发器FF0的状态移入触发器FF1,而FF0转变为新的状态,即Q_1=D_3、Q_0=D_2,以此类推,可得到该移位寄存器的状态,如表6.1所示(x表示不确定状态)。由表6.1可知,经过四个时钟脉冲后,四个触发器的输出状态Q_3Q_2Q_1Q_0与输入数据D_3D_2D_1D_0相对应。此时,串行输入数据可以从并行数据输出端D_{PO}送出去。可见,数据可以串行输入并行读取,因此,该电路也叫做串-并转换器

如果继续移位,则第七个时钟脉冲作用之后,从D_{SI}逐位输入的数据就能够从输出端D_{SO}(即Q_3端)逐位输出寄存器。可见,该电路串行输入的数据是从左向右移位的。如果将图6.1所示电路中各触发器的连接顺序调换一下,让右边触发器的输出作为左邻触发器的数据输入,则可以构成从右向左移位的寄存器。

表6.1 图6.1电路的状态表

CLK脉冲个数DSIQ0Q1Q2Q3
第一个CLK脉冲之前D3xxxx
1D2D3xxx
2D1D2D3xx
3D0D1D2D3x
40D0D1D2D3
500D0D1D2
6000D0D1
70000D0

为了加深理解,在图6.2中画出了数据1101在寄存器中移位的波形,在经过四个时钟脉冲后,1101出现在触发器的输出端Q_3Q_2Q_1Q_0。在第八个时钟脉冲作用后,数据已从Q_3端(即串行数据输出端D_{SO})全部移出寄存器。随着时钟信号的推移,D_{SO}输出端得到1101的串行输出序列。可以看到,如果首先将4位数据并行地置入移位寄存器的四个触发器中,然后连续加入四个移位脉冲,则移位寄存器里的4位数据将从串行输出端D_{SO}依次送出,因此,该电路叫并-串转换器

image-20210630093719243

图6.2 图6.1电路的时序图

我们来看如何使用Verilog HDL来实现图6.1所示的4位移位寄存器。

对于移位功能,我们可由代码6.1所示的四条语句来实现。

q[0] <= dsi;
q[1] <= q[0];
q[2] <= q[1];
q[3] <= q[2]

代码6.1 4位移位寄存器移位功能的实现方法一

我们可以将上述四条语句简化,如代码6.2所示,这与代码6.1是等价的。

q[0]   <= dsi;
q[3:1] <= q[2:0];

代码6.2 4位移位寄存器移位功能的实现方法二

根据图6.1可以写出4位移位寄存器的Verilog HDL实现,如代码6.3所示。

module shift_reg_4bit(input               clk,        // 时钟信号input               clr_n,      // 异步清零信号,低电平有效input               dsi,        // 串行数据输入output  reg [3:0]   q,          // 并行数据输出output              dso         // 串行数据输出
);
​
​
always@(posedge clk, negedge clr_n)
beginif(~clr_n)                      // clk_n为0,寄存器清零beginq   <= 4'b0000;endelsebegin                           // 数据从低位触发器向高位触发器移位q[0]    <= dsi;q[3:1]  <= q[2:0];end
end
assign  dso =   q[3];               // 串行数据输出endmodule

代码6.3 4位移位寄存器Verilog HDL实现

图6.3是代码6.3对应的4位移位寄存器的RTL Viewer。

image-20210630101523866

图6.3 4位移位寄存器的RTL Viewer

6.2.2 双向移位寄存器

有时需要对移位寄存器的数据流向加以控制,实现数据的双向移动,其中一个方向称为右移,另一个方向称为左移,这种移位寄存器称为双向移位寄存器。

注:这里需要注意的是,由于国家标准规定,逻辑图中的最低有效位(LSB)到最高有效位(MSB)的电路排列顺序应从上到下,从左到右。因此定义移位寄存器中的数据从低位触发器移向高位为右移,移向低位为左移。这一点与通常计算机程序中的规定相反,后者从二进制数的自然排列考虑,将数据移向高位定义为左移,反之为右移。

图6.4是双向移位寄存器的一种方案,与普通移位寄存器的连接不同,每个触发器的输入端D连接两个不同的数据源,一个是前级的输出,用于右移操作;另外一个数后一级的输出,用于左移操作。控制信号S用来选择操作的模式,当S=0时,FF0的D_0端与右移串行输入端D_{IR}连通,FF1的D_1端与Q_0连通,FF2的D_2端与Q_1连通,FF3的D_3端与Q_3连通,在时钟脉冲CLK的作用下,D_{IR}端输入的数据将向右移位,并从右移串行输出端D_{OR}输出,电路实现右移操作;当S=1时,FF3的D_3端与左移串行输入端D_{IL}连通,FF2的D_2端与Q_3连通,FF1的D_1端与Q_2连通,FF0的D_0端与Q_1连通,在时钟脉冲CLK的作用下,D_{IL}端输入的数据将向左移位,并从左移串行输出端D_{OL}输出,电路实现左移操作。

image-20210630102106310

图6.4 用D触发器构成的双向移位寄存器

由此可见,图6.4所示电路可作双向移位,当S=0时,数据向右移位;当S=1时,数据向左移位,可实现串行输入-串行输出(由D_{OR}或D_{OL}输出)、串行输入-并行输出(由Q3 \sim Q0输出)的工作方式。

代码6.4是图6.4所示的4位双向移位寄存器的Verilog HDL实现。

module bidir_shift_reg_4bit(input               clk,        // 时钟信号input               clr_n,      // 异步清零信号,低电平有效input               dir,        // 右移串行输入input               dil,        // 左移串行输入input               s,          // 控制信号output  reg [3:0]   q,          // 并行数据输出output              dor,        // 右移串行输出output              dol         // 左移串行输出
);
​
always@(posedge clk, negedge clr_n)
beginif(~clr_n)                      // clk_n为0,寄存器清零beginq   <= 4'b0000;endelsebegin                           if(s == 1'b0)               // 右移q   <=  {q[2:0], dir};else                        // 左移q   <=  {dil, q[3:1]};end
end
assign  dor =   q[3];               // 右移串行输出
assign  dol =   q[0];               // 左移串行输出endmodule

代码6.4 4位双向移位寄存器Verilog HDL实现

图6.5是代码6.4对应的4位双向移位寄存器的RTL Viewer。

image-20210630104321406

图6.5 4位双向移位寄存器的RTL Viewer

6.2.3 并行存取的移位寄存器

并行存取的移位寄存器如图6.6所示,它与双向移位寄存器的连接有些类似,但又有不同。并行存取的移位寄存器的每个触发器的输入端D也是连接两个不同的数据源,一个数据源是前级的输出,用于移位寄存器的右移操作,这与双向移位寄存器是一样的;另外一个数据来自于外部的输入,作为并行操作的一部分,这部分与双向移位寄存器不同。控制信号S用来选择操作的模式,当S=0时,电路实现右移操作;当S=1时,并行数据DI_3 \sim DI_0送到各自的寄存器进行寄存,由此便可实现并行输入(由DI_3 \sim DI_0输入)、并行输出(由Q3 \sim Q0输出)。

image-20210630105252445

图6.6 4位并行存取的移位寄存器

代码6.5是图6.6所示的4位并行存取的移位寄存器的Verilog HDL实现。

module parallel_shift_reg_4bit(input               clk,        // 时钟信号input               clr_n,      // 异步清零信号,低电平有效input               dir,        // 右移串行输入input       [3:0]   di,         // 并行数据输入input               s,          // 控制信号output  reg [3:0]   q,          // 并行数据输出output              dor         // 右移串行输出
);
​
always@(posedge clk, negedge clr_n)
beginif(~clr_n)                      // clk_n为0,寄存器清零beginq   <= 4'b0000;endelsebegin                           if(s == 1'b0)               // 右移q   <=  {q[2:0], dir};else                        // 并行存取q   <=  di;end
end
assign  dor =   q[3];               // 右移串行输出endmodule

代码6.5 4位并行存取移位寄存器Verilog HDL实现

图6.7是代码6.5对应的4位并行存取移位寄存器的RTL Viewer。

image-20210630105618233

图6.7 4位并行存取移位寄存器的RTL Viewer

6.2.4 多功能双向移位寄存器

为便于扩展逻辑功能和增加使用的灵活性,我们将并行输入、并行输出、左移、右移、保持、异步复位等功能集合到同一个电路中,组成多功能双向移位寄存器。

图6.8所示是实现一个4位的具有数据保持、右移、左移、并行输入和并行输出功能的多功能双向移位寄存器的一种电路方案。该电路主要由四个D触发器和四个四选一数据选择器构成,每个D触发器的数据输入端都插入一个四选一数据选择器MUX,并用2位的输入S1、S0控制MUX,来选择D触发器输入信号D的来源。当S1=S0=0时,选择该D触发器自身的输出Q,使D触发器保持状态不变;当S1=0、S0=1时,前一级D触发器的输出被选中,所以当时钟信号上升沿到来时,D触发器存入前一级D触发器的逻辑值,从而实现右移功能;类似地,当S1=1、S0=0时,实现左移功能;而当S1=S0=1时,选择并行输入数据DI3 \sim DI0,即实现并行输入的功能。表6.2列出了该多功能双向移位寄存器的四种操作。

image-20210630110557264

图6.8 实现多功能双向移位寄存器的一种方案

​​

表6.2 图6.8电路的功能表

控制信号功能
S1S0
00保持
01右移
10左移
11并行输入

代码6.6是图6.8所示的4位多功能双向的移位寄存器的Verilog HDL实现。

module multi_func_shift_reg_4bit(input               clk,        // 时钟信号input               clr_n,      // 异步清零信号,低电平有效input               dir,        // 右移串行输入input               dil,        // 左移串行输入input       [3:0]   di,         // 并行数据输入input       [1:0]   s,          // 控制信号output  reg [3:0]   q,          // 并行数据输出output              dor,        // 右移串行输出output              dol         // 左移串行输出
);
​
always@(posedge clk, negedge clr_n)
beginif(~clr_n)                      // clk_n为0,寄存器清零beginq   <= 4'b0000;endelsebegincase(s[1:0])2'b00:  q   <=  q;              // 保持2'b01:  q   <=  {q[2:0], dir};  // 右移2'b10:  q   <=  {dil, q[3:1]};  // 左移2'b11:  q   <=  di;             // 并行存取endcaseend
end
assign  dor =   q[3];               // 右移串行输出
assign  dol =   q[0];               // 左移串行输出endmodule

代码6.6 4位多功能双向移位寄存器Verilog HDL实现

图6.9是代码6.6对应的4位多功能双向移位寄存器的RTL Viewer。

image-20210630111344065

图6.9 4位多功能双向移位寄存器的RTL Viewer

6.3 实验目标

  • 使用移位寄存器来实现乘以2和除以2的运算;

  • 并将乘以2和除以2的运算加入到实验五实现的计算器中,即计算器可实现与运算、或运算、异或运算、非运算、加(减)法运算、乘以2、除以2运算;

6.4 设计实现

6.4.1 设计思路

图6.10是本实验的系统框图,我们增加了如红色框所示的部分,它们分别实现乘以2、除以2的运算。使用SW3 ~ SW0作为乘法和除法的第一个操作数A,第二个操作数固定为常数2。经过乘法运算后,结果可能会超过16,所以使用两个数码管来显示运算的结果。

image-20240520165005303

图6.10 实验六系统框图

我们再来看乘法、除法运算的实现。

二进制数A乘以2,这相当于在A最低有效位的右边添加一个0,或者说把A的所有位左移1位,如图6.11(a)所示。因此A乘以2可以用左移的移位寄存器来实现。

二进制数A除以2,这相当于在A最高有效位添加一个0,即把A的所有位右移1位,如图6.11(b)所示。因此A除以2可以用右移的移位寄存器来实现。

注:上文中讨论的乘法和除法,都是考虑无符号二进制数A。

image-20210630094009622

图6.11 左移(a)和右移(b)运算示例

图6.12为4位移位寄存器的框图,rst_n为异步清零信号,a为4位输入数据,进行左移1位或右移1位后,输出数据f。该框图可以表示4位左移移位寄存器,也可以表示4位右移移位寄存器,因为它们对外的接口信号都是一样的,进行左移还是右移是在内部实现的,即框图内部实现时会不同。

image-20210630094040193

图6.12 4位移位寄存器的框图

表6.3是4位移位寄存器的输入输出信号描述。

表6.3 4位移位寄存器信号描述

信号名称位宽方向功能描述
clk1-bitInput4位移位寄存器的时钟信号
rst_n1-bitInput4位移位寄存器的异步复位信号
a4-bitInput4位移位寄存器的输入信号
f4-bitOutput4位移位寄存器的输出信号

6.4.2 代码实现
  • 乘以2运算

    代码6.7是乘以2运算的代码实现。

    module c6(input               clk,        // 时钟信号input               rst_n,      // 异步复位信号input       [ 3: 0] a,          // 输入信号output  reg [ 4: 0] f           // 输出信号
    );
    ​
    always@(posedge clk, negedge rst_n)
    beginif(~rst_n)beginf <= 5'b00000;endelsebeginf[4:1]  <= a[3:0];          // 右移1位f[0]    <= 1'b0;            // 右移1位,最低位填0end
    end
    ​
    endmodule

    代码6.7 c6.v

    如下图是乘以2运算的RTL Viewer。

    image-20210630094433063

    图6.13 乘以2运算的RTL Viewer

  • 除以2运算

    代码6.8是除以2运算的代码实现。

    module c7(input               clk,        // 时钟信号input               rst_n,      // 异步复位信号input       [ 3: 0] a,          // 输入信号output  reg [ 3: 0] f           // 输出信号
    );
    ​
    always@(posedge clk, negedge rst_n)
    beginif(~rst_n)beginf   <= 4'b0000;endelsebeginf[2:0]  <= a[3:1];          // 左移1位f[3]    <= 1'b0;            // 左移1位,最高位填0end
    end
    ​
    endmodule

    代码6.8 c7.v

    图6.14是除以2运算的RTL Viewer。

    image-20210630094543369

    图6.14 除以2运算的RTL Viewer

  • 计算器模块

    计算器模块是在实验五实现的计算器的基础上增加了乘以2、除以2运算,需要修改calculator.v文件,其中第72行 ~ 98行为主要的修改部分,主要是添加了c6、c7模块以及与mux8x1模块之间的连接。

    module calculator(input           clk,        // 时钟信号,50MHzinput           rst_n,      // 异步复位信号input           en,         // 寄存器使能信号input           carry_in,   // 加法的进位输入input   [3:0]   a,          // 计算器的第一个操作数//input   [3:0]   b,          // 计算器的第二个操作数input   [2:0]   sel,        // 计算器的功能选择信号output  [5:0]   ledr_out,   // 寄存器的数据输出output  [6:0]   hex0_out,   // 七段数码管译码器的输出HEX0output  [6:0]   hex1_out    // 七段数码管译码器的输出HEX1
    );// 变量声明
    wire [3:0]  operator_a;
    wire [3:0]  operator_b;
    wire        operator_cin;
    wire [2:0]  operation_s;wire [3:0]  f1;
    wire [3:0]  f2;
    wire [3:0]  f3;
    wire [3:0]  f4;
    wire [5:0]  f5;
    wire [4:0]  f6;
    wire [3:0]  f7;
    wire [5:0]  f;
    wire [5:0]  g;
    wire [6:0]  hex0dec_output;
    wire [6:0]  hex1dec_output;// 输入信号赋值
    assign  operator_a      =   a;
    //assign  operator_b      =   b;
    assign  operator_cin    =   carry_in;
    assign  operation_s     =   sel;// 将输入a存入寄存器中reg4bits reg4bits_inst (.clk(clk), .rst_n(rst_n), .en(~en), .d(a), .q(operator_b));    // 与运算
    c1  c1_inst(.a  (operator_a),.b  (operator_b),.f  (f1)
    );
    // 或运算
    c2  c2_inst(.a  (operator_a),.b  (operator_b),.f  (f2)
    );
    // 异或运算
    c3  c3_inst(.a  (operator_a),.b  (operator_b),.f  (f3)
    );
    // 非运算
    c4  c4_inst(.a  (operator_a),.f  (f4)
    );
    // 加(减)运算
    c5 c5_inst (.a  (operator_a), .b  (operator_b), .ci (operator_cin), .f  (f5)
    );
    // 乘以2
    c6 c6_inst (.clk    (clk),.rst_n  (rst_n),.a      (operator_a),.f      (f6)
    );
    // 除以2
    c7 c7_inst (.clk    (clk),.rst_n  (rst_n),.a      (operator_a),.f      (f7)
    );
    // 在f1,f2,f3,f4,f5,f6,f7七种运算结果中,选择一个运算结果f
    mux8x1 mux8x1_inst(.r  ({2'd0, f1}),.t  ({2'd0, f2}),.u  ({2'd0, f3}),.v  ({2'd0, f4}),.w  (f5),.x  ({1'd0, f6}), .y  ({2'd0, f7}), .z  (6'd0),.s  (operation_s),.m  (f)
    );
    // 将选出的运算结果f存入寄存器中
    reg6bits reg6bits_inst(.clk    (clk),.rst_n  (rst_n),.en     (~en),.d      (f),.q      (g)
    );
    // 寄存器的输出数据g输入至数码管译码器,经译码后显示至两个七段数码管上
    decod7seg decod7seg_inst0(.hex        (g[3:0]),.display    (hex0dec_output)
    );
    decod7seg decod7seg_inst1(.hex        ({2'd0, g[5:4]}),.display    (hex1dec_output)
    );// 寄存器的输出数据g直接显示在LED上
    assign  ledr_out    = g;
    assign  hex0_out    = hex0dec_output;
    assign  hex1_out    = hex1dec_output;endmodule

    代码6.9 calculator.v

    calculator模块的RTL Viewer如图6.15所示,可以看出和6.3.1节画的系统框图是一致的。

    image-20240520170238619

    图6.15 calculator模块的RTL Viewer

6.5 实验步骤

6.5.1 创建工程和代码输入
  1. 点击电脑右下角的开始菜单找到Quartus软件,双击Quartus (Quartus Prime 17.1)打开Quartus Prime软件。

  2. 点击菜单File-->New Project Wizard弹出工程创建的对话框。在弹出的对话框中点击Next。

  3. 在您的DE1-SOC 工作文件夹下创建一个lab7的文件夹,并将工程路径指向该文件夹,且工程的名称也命名calculator。如图6.16-1所示。

image-20240520145247493

图6.16-1 创建Quartus工程

image-20240520145425656

图6.16-2

image-20240520145514303

图6.17

完成创建工程后,打开后的工程Quartus Prime工程界面如图6.18所示。

image-20240520145535274

图6.18 Quartus打开的工程窗口

在lab6工程文件夹下新建名为v的文件夹。点击Quartus软件工具栏的File --> New --> Verilog HDL File,创建c6.v、c7.v文件保存到v文件夹,并依次添加代码6.7、代码6.8中的代码。

image-20240520165319356

图6.19 c6.v

image-20240520165417025

图6.20 c7.v

实验五 加法器中的c1.v、c2.v、c3.v、c4.v、c5.v、decod7seg.v、fa.v、mux2x1.v、mux8x1.v、reg6bits.v、calculator.v文件复制到本实验工程文件夹下,如图6.21所示。

image-20240520165634751

图6.21 复制文件至本实验的工程路径下

点击Quartus软件工具栏的Assignments --> Settings --> Files,将前面拷贝的文件添加至本实验的Quartus工程,如图6.22所示。

image-20240520165745111

图6.22 添加文件至Quartus工程

修改calculator.v文件,参考代码6.9。

image-20240520170327952

图6.23 修改calculator.v文件

  1. 点击Quartus软件工具栏的Processing --> Start --> Start Analysis & Synthesis或点击

    image-20210603145513555

    按钮对Verilog HDL代码执行语法检查和综合。如果在该过程中提示有错误,请检查Verilog HDL代码语法,确保与上述代码块完全一致。

    image-20240520170410592

    图6.25 执行语法检查和综合

6.5.2 仿真
  1. 点击Quartus工具栏File --> New --> Verilog HDL File,点击OK,添加如下仿真代码,点击File --> Save保存,并命名为calculator_tb.v,保存在v文件夹中。

`timescale 1ns/1ns
module calculator_tb();// 产生50MHz时钟信号
reg clk;
localparam  PERIOD = 20;                // 20ns = 50MHz
initial 
beginclk     =   1'b0;forever #(PERIOD/2) clk = ~clk;     // 每隔10ns,clk翻转一次
end// 产生复位信号,用作6位寄存器的异步复位
reg rst_n;
initial 
beginrst_n = 1'b0;#(PERIOD)   rst_n = 1'b1;
end// 产生计算器的操作数a、运算操作选择sel和4位寄存器的使能信号en
reg [3:0] a;
//reg [3:0] b;
reg       ci;
reg [2:0] sel;
reg       en;
initial 
begin#0a   = 4'd0;//  b   = 4'd0;ci  = 1'b0;sel = 3'b000;en  = 1'b0;#(PERIOD)a   = 4'd3;sel = 3'b101;       // a=2, 乘以2#(PERIOD)a   = 4'd8;sel = 3'b101;       // a=8, 乘以2#(PERIOD)a   = 4'd12;sel = 3'b101;       // a=12, 乘以2#(2 * PERIOD)a   = 4'd14;sel = 3'b110;       // a=14, 除以2#(PERIOD)a   = 4'd7;sel = 3'b110;       // a=7, 除以2#(PERIOD)a   = 4'd4;sel = 3'b110;       // a=4, 除以2#(3 * PERIOD)$stop();
end// 例化 calculator
wire    [5:0]   ledr_out;
wire    [6:0]   hex0_out;
wire    [6:0]   hex1_out;
calculator calculator_inst(.clk        (clk),.rst_n      (rst_n),.en         (en),.carry_in   (ci),.a          (a),// .b          (b),.sel        (sel),.ledr_out   (ledr_out),.hex0_out   (hex0_out),.hex1_out   (hex1_out)
);endmodule

代码6.11 calculator_tb.v

  1. 点击Quartus工具栏Assignments --> Settings --> EDA Tool Settings --> Simulation,设置Quartus自动调用ModelSim仿真软件,并设置test bench为calculator_tb,设置完成后如图6.26所示。

image-20240520172125103

图6.26 设置test bech为calculator_tb

  1. 其中,添加Compile test bench的具体步骤如下。

image-20240520172026817

图6.27 设置test bech的具体步骤

点击Quartus工具栏Tools --> Run Simulation Tool --> RTL Simulation启动ModelSim仿真,再点击Wave切换到仿真波形窗口,并点击Zoom Full按钮,如图6.28所示。

image-20240521142320987

图6.28 打开的初始仿真波形

点击上图左侧的Calculator_inst旁的"+"按钮,再单击选中c6_inst,将c6模块的输出信号f添加到wave中,如下图6.29所示。依此再将reg4bits_inst的输出信号q、c7模块的输出信号f和mux8x1模块的输出信号m添加到wave中。

image-20240520173148390

图6.29 添加c6、c7和mux8x1模块的输出信号

右键选中下图中的a、q(其实就是操作数b)、c6、c7和mux8x1,点击Radix-->Hexadecimal,以十六进制数显示。

image-20240520174853712

图6.30 更改十六进制显示

点击ModelSim工具栏的Simulate-->Restart,在弹出的Restart窗口,保持默认选择并点击OK按钮,然后再点击Run -All图标进行仿真。

image-20240520175018139

图6.31 开始仿真

仿真波形如下图6.32所示。

image-20240521142757841

图6.32 calculator仿真波形

仿真波形分析

  • 0 ~ 20ns,复位信号rst_n=0,c6、c7处于复位状态,ledr_out=(00)16,hex0_out=hex1_out=(1000000)2,即数码管HEX1、HEX0都显示十六进制数“0”;

  • 20ns,复位信号rst_n=1,移位寄存器c6、c7恢复正常状态,a=(3)16,sel=(101)2,但此时clk上升沿还没有到来,所以ledr_out=(00)16,hex0_out=hex1_out=(1000000)2,即数码管HEX1、HEX0都显示十六进制数“0”;

  • 30ns,clk上升沿到来,数据选择器选择乘以2运算的结果输出m=(06)16;

  • 50ns,clk上升沿时刻,寄存器的输出ledr_out=(06)16,hex1_out=(1000000)2,hex0_out=(0000010)2,即数码管HEX1、HEX0分别显示显示十六进制数“0”、“6”;

  • 同样是在50ns,clk上升沿时刻,a=(8)16,sel=(101)2,m=(10)16;

  • 70ns,clk上升沿时刻,寄存器的输出ledr_out=(10)16,hex1_out=(1111001)2,hex0_out=(1000000)2,即数码管HEX1、HEX0分别显示显示十六进制数“1”、“0”;

  • 同样是在70ns,clk上升沿时刻,a=(c)16,sel=(101)2,m=(18)16;

  • 90ns,clk上升沿时刻,寄存器的输出ledr_out=(18)16,hex1_out=(1111001)2,hex0_out=(0000000)2,即数码管HEX1、HEX0分别显示显示十六进制数“1”、“8”;

  • 100ns,sel由(101)2变为(110)2,但此时处于clk下降沿,数码管HEX1、HEX0保持不变;

  • 110ns,clk上升沿时刻,a=(e)16,sel=(110)2,数据选择器选择除以2运算的结果输出m=(7)16;

  • 130ns,clk上升沿时刻,寄存器的输出ledr_out=(07)16,hex1_out=(1000000)2,hex0_out=(1111000)2,即数码管HEX1、HEX0分别显示显示十六进制数“0”、“7”;

  • 同样是在130ns,clk上升沿时刻,a=(7)16,sel=(110)2,m=(3)16;

  • 150ns,clk上升沿时刻,寄存器的输出ledr_out=(03)16,hex1_out=(1000000)2,hex0_out=(0110000)2,即数码管HEX1、HEX0分别显示显示十六进制数“0”、“3”;

  • 同样是在150ns,clk上升沿时刻,a=(4)16,sel=(110)2,m=(2)16;

  • 170ns,clk上升沿时刻,寄存器的输出ledr_out=(02)16,hex1_out=(1000000)2,hex0_out=(0100100)2,即数码管HEX1、HEX0分别显示显示十六进制数“0”、“2”;

6.5.3 引脚分配、全编译与烧录

这个实验的操作数a及sel可以通过拨码开关SW0~SW3以及SW7~SW9来控制,carry_in从SW6输入。out信号分别输出到LEDR0到LEDR5,hex0_out输出到数码管0,hex1_out输出到数码管1,en和rst_n连接到按键key1和key0。

  1. 点击Quartus菜单Assignments——Pin Planner进行引脚分配。

img

图4.41

关于引脚分配信息可以查看DE1-SoC_v.5.1.3_HWrevF.revG_SystemCD\UserManual\DE1-SoC_User_manual.pdf第 22、25、26、28页或者E:\CD_Package\01-DE1-SoC\DE1-SoC_v.5.1.3_HWrevF.revG_SystemCD\Schematic\DE1-SoC.pdf的第3页。

img

image-20240517165745573

img

image-20240517165857589

image-20240521091242725

image-20240521092456466

image-20240521092534583

  1. 点击Quartus软件工具栏的Processing --> Start Compilation或点击

    image-20210603145755433

    按钮编译lab6工程,并检查是否生成calculator.sof。

    image-20240521093008816

    图6.33 编译lab6工程

  2. 连接DE1-SOC开发板到PC, 给开发板上电开机。

  3. 点击Quartus软件工具栏的Tools --> Programmer

    image-20210603150014201

    按钮打开Programmer窗口,点击Hardware Setup选择USB-Blaster设备,点击Auto Detect选择5CSEBA6器件,左键单击选中5CSEBA6器件再点击Change File,选择lab6.sof,勾选Program/configure,点击Start下载calculator.sof。

    image-20240521093339274

    图6.34 烧录lab6.sof

6.5.4 实验现象观察
  1. 拨动界面上的滑动开关,并观察实验现象:

  • 先按一次KEY0,寄存器异步复位,c6、c7模块和6位寄存器中的数据被清0,LEDR5 ~ LEDR0全部熄灭,HEX1HEX0都显示十六进制数字“0”;

    IMG_20240521_093536(1)

    图6.38 实验现象1

  • 拨动SW10 ~ SW8为“up、down、up”,SW3 ~ SW0为“down、down、up、up”,按一次KEY1LEDR5 ~ LEDR0显示为“熄灭、熄灭、熄灭、点亮、点亮、熄灭”,HEX1、HEX0分别显示十六进制数字“0”、“6”;

    即:a=(3)_{16},sel=(101)_2,计算器作乘以2运算,a*2=(6)_{16}。

    IMG_20240521_093716(1)

    图6.39 实验现象2

  • 拨动SW10 ~ SW8为“up、down、up”,SW3 ~ SW0为“up、down、down、down”,SW7 ~ SW4为“down、down、down、down”;按一次KEY1LEDR5 ~ LEDR0显示为“熄灭、点亮、熄灭、熄灭、熄灭、熄灭”,HEX1、HEX0分别显示十六进制数字“1”、“0”;

    即:a=(8)_{16},sel=(101)_2,计算器作乘以2运算,a*2=(10)_{16}。

    IMG_20240521_135759(1)

    图6.40 实验现象3

  • 拨动SW10 ~ SW8为“up、down、up”,SW3 ~ SW0为“up、up、down、down”,SW7 ~ SW4为“down、down、down、down”;按一次KEY1LEDR5 ~ LEDR0显示为“熄灭、点亮、点亮、熄灭、熄灭、熄灭”,HEX1、HEX0分别显示十六进制数字“1”、“8”;

    即:a=(c)_{16},sel=(101)_2,计算器作乘以2运算,a*2=(18)_{16}。

    IMG_20240521_135826(1)

    图6.41 实验现象4

  • 拨动SW10 ~ SW8为“up、up、down”,SW3 ~ SW0为“up、up、up、down”,SW7 ~ SW4为“down、down、down、down”;按一次KEY1LEDR5 ~ LEDR0显示为“熄灭、熄灭、熄灭、点亮、点亮、点亮”,HEX1、HEX0分别显示十六进制数字“0”、“7”;

    即:a=(e)_{16},sel=(110)_2,计算器作除以2运算,a/2=(7)_{16}。

    IMG_20240521_135900(1)

    图6.42 实验现象5

  • 拨动SW10 ~ SW8为“up、up、down”,SW3 ~ SW0为“down、up、up、up”,SW7 ~ SW4为“down、down、down、down”;按一次KEY1LEDR5 ~ LEDR0显示为“熄灭、熄灭、熄灭、熄灭、点亮、点亮”,HEX1、HEX0分别显示十六进制数字“0”、“3”;

    即:a=(7)_{16},sel=(110)_2,计算器作除以2运算,a/2=(3)_{16}。

    IMG_20240521_135916(1)

    图6.43 实验现象6

  • 拨动SW10 ~ SW8为“up、up、down”,SW3 ~ SW0为“down、up、down、down”,SW7 ~ SW4为“down、down、down、down”;按一次KEY1LEDR5 ~ LEDR0显示为“熄灭、熄灭、熄灭、熄灭、点亮、熄灭”,HEX1、HEX0分别显示十六进制数字“0”、“2”;

    即:a=(4)_{16},sel=(110)_2,计算器作除以2运算,a/2=(2)_{16}。

    IMG_20240521_135933(1)

    图6.44 实验现象7

6.6 实验小结

本章我们学习了如何使用寄存器组成移位寄存器,移位寄存器不仅可以存储数据,还可以用来实现数据的串-并转换、数据处理以及数值的运算,像我们在实验中使用移位寄存器来实现了乘以2、除以2运算。

使用移位寄存器还可以实现环形计数器和扭环形计数器,由于这不是我们本章的主旨,没有做过多的介绍,有兴趣的同学可查阅相关资料学习。

这篇关于第六篇 移位寄存器的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1030006

相关文章

Modbus初学者教程,第三章:modbus寄存器说明

第三章:modbus寄存器说明 寄存器种类 Modbus协议中一个重要的概念是寄存器,所有的数据均存放于寄存器中。Modbus寄存器是指一块内存区域。Modbus寄存器根据存放的数据类型以及各自读写特性,将寄存器分为4个部分,这4个部分可以连续也可以不连续,由开发者决定。寄存器的意义如下表所示。 Modbus协议定义了设备间的数据传输方式,包括数据格式和通信规则。Modbus寄存器是协议中用

读线圈和离散状态寄存器信息

一.功能码操作类型 二.读线圈状态 需求实例 读取设备地址为 3 的从设备的线圈状态寄存器,线圈地址为 19 到 55(从 0 开始计算)共 37 个状态。 分析:由需求可知读取地址,则功能码是0x01,地址为3即为0x03,线圈地址为19到55则起始地址为19,即0x13,数量为37,即是0x25,查询报表如下所示: 假设从设备的状态值如下: 对应的响应包如下: 使

STM32读写备份寄存器和实时时钟

文章目录 1. 硬件电路 2. RTC操作注意事项 操作步骤 3. 代码实现 3.1 读写备份寄存器 3.1.1 main.c 3.2 实时时钟 3.2.1 MyRTC.c 3.2.2 MyRTC.h 3.2.3 main.c 1. 硬件电路 对于BKP备份寄存器和RTC实时时钟的详细解析可以看下面这篇文章: STM32单片机BKP备份寄存器和RTC实时时钟详解

c语言移位运算超出类型所能表示的范围告警

错误代码: *(unsigned int *)GPIOC_CRH &= ~(0xf << 28); 告警内容: integer operation result is out of range 分析:  integer operation result is out of range是因为在尝试对一个32位整型执行移位操作时超出了该类型所能表示的范围。在C语言中,整型字面量(如0xf

第六篇 zabbix创建主机群组

Zabbix可以同时监控多台机器,要想查看对某台机器的监控,只需要添加相应的主机即可(当然该主机必须要安装好zabbix_agentd,不然zabbix_server无法获取到该主机的监控数据) 点击配置-》主机 我们可以看到创建主机的按钮,但是在创建主机之前我们要先创建主机群主,每个主机都要对应一个主机群主。 点击配置-》主机群主-》创建主机群组 右侧可以选择添加我们需要的模板,或者已

java 位运算符 位逻辑运算符 和 移位运算符

参考:《Java语言程序设计》第二章              《Java核心技术 卷I:基础知识》第三章 #####################################################################333 在Java中,有关位的运算有两类:位运算符运算(Bitwise)和移位运算(Shift)。 位运算符只能用于整型数据,包括by

一文概括:内容可寻址寄存器(CAR)

一、概述         内容可寻址寄存器(Content-Addressable Register,CAR)是一种能够根据内容(数据)而非传统的存储地址来进行数据访问的特殊存储单元。与地址可寻址寄存器不同,内容可寻址寄存器可以通过指定的数据值来查找存储的位置,使其在需要高效数据检索的应用中尤其有用。 二、工作原理         内容可寻址寄存器的操作基于数据内容匹配而非地址访问。其工作过

寄存器和存储器的区别与联系

在计算机系统中,寄存器和存储器是两个重要的概念,它们在数据存储和处理过程中扮演着不同但互补的角色。本文将详细讨论寄存器和存储器的区别与联系。 1. 基本概念 **寄存器(Register)**是一种速度极快的小容量存储单元,通常集成在CPU内部,用于暂存数据和指令。寄存器可以在一个CPU时钟周期内被读取或写入。 **存储器(Memory)**通常指随机存取存储器(RAM),是一种速度较慢但容

【SkiaSharp绘图05】SKPaint详解(三)之ImageFilter(颜色、组合、膨胀、移位、光照、反射、阴影、腐蚀、变换)

文章目录 ImageFilterCreateColorFilter 颜色滤镜CreateCompose 滤镜组合CreateDilate 膨胀滤镜CreateDisplacementMapEffect 移位映射CreateDistantLitDiffuse 光照CreateDistantLitSpecular 反射光照CreateDropShadow阴影效果CreateDropShadowO

74HC595移位寄存器

参考文章 参考文章 1-7,15号端口接8个LED或者8位数码管; 8号口接地; 9号口连接下一个595或者置空; 10号口接vcc; 11号口接D2; 11脚SRCLK移位寄存器时钟输入:当一个新的位数据要进来时,已经进入的位数据就在移位寄存器时钟脉冲的控制下,整体后移,让出位置。 12号口D3; 12脚RCLK存储寄存器:数据从位移寄存器转移到存储寄存器,也是需要时钟脉冲驱动的,这就是12