一 实验要求
1实验目的及实验内容要求
1.1 实验目的
1.熟悉VIVADO的编译环境
2.熟悉在 VIVADO 环境下运用 Verilog HDL 语言的编程开发流程,包括源程序的编写、编译、模拟仿真及程序下载。
3.使用Verilog语言设计一个通用寄存器,包括复位、置位、装载、清除基础功能,而且包括左移、右移、循环左移、循环右移功能。
1.2 实验内容
1.VIVADO 环境下源程序的编写、编译
2.模拟仿真
3.程序下载
1.3实验要求
- 基础任务:设计一位具有复位、置位、装载、存储功能的寄存器和多位这样功能的寄存器(4位或8位),两种方法,一是可以将一位寄存器封装成IP核,多位寄存器使用IP核设计而成,二是将一位寄存器作为底层,多位寄存器调用,即直接使用层次化方式设计而成(两种方式二选一)。
(2)拓展任务: 设计一个N位通用寄存器,除了要有复位、置位、装载、存储功能外,还要有左移和右移功能,由外部给移入数据。
(3)提高任务: 设计一个N位通用寄存器,除了要有复位、置位、装载、存储功能外,还要有左移和右移功能,由外部给移入数据,还要有循环左移和循环右移功能。
2 实验设备或运行软件平台
Vivado 2017.4
EG01开发板
二 实验内容及过程
1 实验设计及分析
1.1流程分析
输入信号接收:模块接收来自外部的时钟信号 clk 和复位信号 reset,以及控制信号 left、right、rotate_left、rotate_right、clear、load 和 set1,以及输入数据信号 in。
辅助时钟信号生成:使用一个寄存器 count 作为计数器,根据时钟信号 clk 和复位信号 reset 来生成一个辅助时钟信号 clk1。这个辅助时钟信号的频率比主时钟信号 clk 低,用于控制一些操作的触发。
左移、右移、循环左移和循环右移操作:使用辅助时钟信号 clk1 来触发左移、右移、循环左移和循环右移的操作。
当 clk1 上升沿触发时,根据控制信号执行相应的操作:如果接收到 clear 信号,将寄存器 inreg 清零。如果接收到 load 信号,根据 set1 信号的状态选择将寄存器 inreg 加载为全 1 还是输入的数据。如果接收到 left 信号,将寄存器 inreg 左移一位。如果接收到 right 信号,将寄存器 inreg 右移一位。如果接收到 rotate_left 信号,将寄存器 inreg 进行循环左移操作。如果接收到 rotate_right 信号,将寄存器 inreg 进行循环右移操作。
输出信号生成:最后,将当前寄存器 inreg 的值赋给输出信号 out,以供外部使用。
1.2实验设计
模块声明:module jicunqi; 定义了一个模块名为 jicunqi,其中包含输入和输出端口。输入端口包括时钟信号 clk、复位信号 reset、左移信号 left、右移信号 right、循环左移信号 rotate_left、循环右移信号 rotate_right、清除信号 clear、输入数据 in、加载信号 load、设置信号 set1。输出端口为 8 位寄存器的当前值 out。
内部信号声明:wire clk1;:声明了一个辅助时钟信号 clk1,用于触发特定操作。reg [7:0] inreg;:声明了一个 8 位的寄存器 inreg,用于存储数据。
wire [7:0] rotated_left; 和 wire [7:0] rotated_right;:声明了两个 8 位的辅助信号,用于存储左移和右移后的数据。wire [7:0] left1; 和 wire [7:0] right1;:声明了两个 8 位的辅助信号,用于存储左移和右移操作的结果。reg [26:0] count;:声明了一个 27 位的寄存器 count,用于生成辅助时钟信号 clk1。
分频时钟信号生成:assign clk1 = count[26];:将寄存器 count 的最高位作为辅助时钟信号 clk1。
时序逻辑:always @(posedge clk or negedge reset):定义了一个时序逻辑块,在时钟信号的上升沿或者复位信号的下降沿触发。if (reset == 0) count<=0;:如果复位信号为低电平,则将寄存器 count 清零。else count<=count+1;:否则,在时钟上升沿时,将寄存器 count 加一。
左移、右移、循环左移和循环右移操作:assign rotated_left = {inreg[6:0], inreg[7]}; 和 assign rotated_right = {inreg[0], inreg[7:1]};:通过连接寄存器 inreg 的位来生成左移和右移后的数据。assign left1 = inreg << 1; 和 assign right1 = inreg >> 1;:将输入数据 inreg 分别左移一位和右移一位,生成左移和右移操作的结果。always @(posedge clk1):定义了一个时序逻辑块,在辅助时钟信号 clk1 的上升沿触发。根据接收到的控制信号执行相应的操作:清除、加载、左移、右移、循环左移、循环右移。
输出信号生成:assign out = inreg;:将当前寄存器 inreg 的值赋给输出端口 out。
2 实验步骤及实验数据记录
2.1 实验步骤
(1)双击启动VIVADO。
(2)利用向导,建立一个新项目。
(3)输入设计
新建一个Verilog HDL文件,在左侧“Flow Navigator”栏中的“Project Manager”下点击“Add Sources”,在弹出的窗口中选择“Add or create design sources”。或者可以通过右击Design sourse选择Add Sourse创建文件。
在“Sources”窗口中的“Design Sources”下双击创建的源文件。在用户区Verilog HDL文件窗口中编写代码,保存时文件名与实体名保持一致。
寄存器设计的Verilog参考程序。编辑代码如下:
module jicunqi(
input wire clk,
input wire reset,
input wire left,
input wire right,
input wire rotate_left,
input wire rotate_right,
input wire clear,
input wire [7:0] in,
input wire load,
input wire set1,
output wire [7:0] out
);
wire [7:0] left1;
wire [7:0] right1;
reg [26:0] count;
wire clk1;
reg [7:0] inreg;
wire [7:0] rotated_left;
wire [7:0] rotated_right;
assign clk1 = count[26];
always @(posedge clk or negedge reset)
begin
if (reset == 0) count<=0;
else count<=count+1;
end
assign left1 = inreg << 1;
assign right1 = inreg >> 1;
assign rotated_left = {inreg[6:0], inreg[7]};
assign rotated_right = {inreg[0], inreg[7:1]};
always @(posedge clk1) begin
if (clear) begin
inreg <= 8'b0;
end else if (load) begin
if (set1) begin
inreg <= 8'b11111111;
end else begin
inreg <= in;
end
end else if (left) begin
inreg <= left1;
end else if (right) begin
inreg <= right1;
end else if (rotate_left) begin
inreg <= rotated_left;
end else if (rotate_right) begin
inreg <= rotated_right;
end
end
assign out = inreg;
endmodule
(4)VIVADO 程序编译
完成Synthesize的综合编译。编译成功后,关闭弹出窗口。双击Schematic可以查看RTL级电路图。
图1 RTL级电路图
(5)仿真
创建仿真文件,在左侧“Flow Navigator”栏中的“Project Manager”下点击“Add Sources”,在弹出的窗口中选择“Add or create simulationsources”,在“Sources”窗口中的“ Simulation Sources ”下双击新建的仿真文件,在编辑窗口完成仿真文件编写。
module test;
reg clk;
reg reset;
reg [7:0] data_in;
reg load;
reg set1;
reg clear;
reg shift_left;
reg shift_right;
reg rotate_left;
reg rotate_right;
wire [7:0] data_out;
jicunqi uut (
.clk(clk),
.reset(reset),
.in(data_in),
.load(load),
.clear(clear),
.set1(set1),
.left(shift_left),
.right(shift_right),
.rotate_left(rotate_left),
.rotate_right(rotate_right),
.out(data_out)
);
initial begin
clk = 0;
forever #5 clk = ~clk;
end
// 测试序列
initial begin
// 初始化
#10 reset = 0;
#10 reset = 1; // 释放复位
// 置位操作
load = 1;
set1 = 1;
#10 load = 0;
set1 = 0;
#30;
#10 clear = 1;
#20 clear = 0;
// 置位操作
#20
// 装载数据
load = 1;
data_in = 8'b10101010;
set1 = 0;
#20 load = 0;
#10;
#20
// 左移操作
shift_left = 1;
#40;
shift_left = 0;
#10;
#100
// 右移操作
shift_right = 1;
#40;
shift_right = 0;
#10;
#100
// 循环左移操作
rotate_left = 1;
#100 rotate_left = 0;
#50;
#100
// 循环右移操作
rotate_right = 1;
#50 rotate_right = 0;
#50;
$finish;
end
endmodule
在左侧“Flow Navigator”一栏中的“Simulation”下点击“Run Simulation”,选择“Run Behavior Simulation”。进入仿真界面。
图2 仿真波形图
调整界面布局,将波形窗口拉大。点击“Zoom Fit”,将波形缩放到合适大小。仿真结束之后,在波形窗口上方的浅蓝色区域最右边点击叉号,在确认窗口点击“OK”,关闭仿真界面。
(6)分配引脚(添加约束)
右击约束子目录下文件夹,选择Add Sourse,选择第一项Add orcreate constraints 编写约束文件如下:
set_property PACKAGE_PIN P17 [get_ports clk]
set_property IOSTANDARD LVCMOS33 [get_ports clk]
set_property PACKAGE_PIN P15 [get_ports reset]
set_property IOSTANDARD LVCMOS33 [get_ports reset]
set_property PACKAGE_PIN U3 [get_ports clear]
set_property IOSTANDARD LVCMOS33 [get_ports clear]
set_property PACKAGE_PIN U2 [get_ports set1]
set_property IOSTANDARD LVCMOS33 [get_ports set1]
set_property PACKAGE_PIN P5 [get_ports data_in[7]]
set_property IOSTANDARD LVCMOS33 [get_ports data_in[7]]
set_property PACKAGE_PIN P4 [get_ports data_in[6]]
set_property IOSTANDARD LVCMOS33 [get_ports data_in[6]]
set_property PACKAGE_PIN P3 [get_ports data_in[5]]
set_property IOSTANDARD LVCMOS33 [get_ports data_in[5]]
set_property PACKAGE_PIN P2 [get_ports data_in[4]]
set_property IOSTANDARD LVCMOS33 [get_ports data_in[4]]
set_property PACKAGE_PIN R2 [get_ports data_in[3]]
set_property IOSTANDARD LVCMOS33 [get_ports data_in[3]]
set_property PACKAGE_PIN M4 [get_ports data_in[2]]
set_property IOSTANDARD LVCMOS33 [get_ports data_in[2]]
set_property PACKAGE_PIN N4 [get_ports data_in[1]]
set_property IOSTANDARD LVCMOS33 [get_ports data_in[1]]
set_property PACKAGE_PIN R1 [get_ports data_in[0]]
set_property IOSTANDARD LVCMOS33 [get_ports data_in[0]]
set_property PACKAGE_PIN V2 [get_ports load]
set_property IOSTANDARD LVCMOS33 [get_ports load]
set_property PACKAGE_PIN V4 [get_ports shift_left]
set_property IOSTANDARD LVCMOS33 [get_ports shift_left]
set_property PACKAGE_PIN R3 [get_ports shift_right]
set_property IOSTANDARD LVCMOS33 [get_ports shift_right]
set_property PACKAGE_PIN T3 [get_ports rotate_left]
set_property IOSTANDARD LVCMOS33 [get_ports rotate_left]
set_property PACKAGE_PIN T5 [get_ports rotate_right]
set_property IOSTANDARD LVCMOS33 [get_ports rotate_right]
set_property PACKAGE_PIN F6 [get_ports data_out[7]]
set_property IOSTANDARD LVCMOS33 [get_ports data_out[7]]
set_property PACKAGE_PIN G4 [get_ports data_out[6]]
set_property IOSTANDARD LVCMOS33 [get_ports data_out[6]]
set_property PACKAGE_PIN G3 [get_ports data_out[5]]
set_property IOSTANDARD LVCMOS33 [get_ports data_out[5]]
set_property PACKAGE_PIN J4 [get_ports data_out[4]]
set_property IOSTANDARD LVCMOS33 [get_ports data_out[4]]
set_property PACKAGE_PIN H4 [get_ports data_out[3]]
set_property IOSTANDARD LVCMOS33 [get_ports data_out[3]]
set_property PACKAGE_PIN J3 [get_ports data_out[2]]
set_property IOSTANDARD LVCMOS33 [get_ports data_out[2]]
set_property PACKAGE_PIN J2 [get_ports data_out[1]]
set_property IOSTANDARD LVCMOS33 [get_ports data_out[1]]
set_property PACKAGE_PIN K2 [get_ports data_out[0]]
set_property IOSTANDARD LVCMOS33 [get_ports data_out[0]]
(7)综合
在“Flow Navigator”一栏中的“Synthesis”下点击“Run Synthesis”。等待右上角显示综合完成。
(8)实现
单击Run implementation,运行完成后弹出下面窗口,生成比特流文件。
(9)下载
运行完成,选择OpenHardwareManager,将实验板通过USB连接至电脑,然后点击Auto Connect,连接成功后,右击FPGA芯片选择ProgramDevice,下载完成OK,开发板即可演示。
2.2 实验数据分析
1.仿真波形
图3 仿真波形图
分析:load为装载信号,load为高电平时,外部输入的数据才能装载到寄存器中,load为低电平时,外部输入的数据被存储,改变外部输入不影响寄存器存储的数据;clear为清除信号,clear为高电平时,寄存器中存储的数据全部清空置0;left为左移信号,left为1时,寄存器中所存储的数据进行左移,直到全部移出寄存器;right为1时,寄存器中所存储的数据进行右移,直到全部移出寄存器;rolate_left为1时,寄存器中所存储的数据进行循环左移,低位移到高位,不会移出寄存器;rolate_right为1时,寄存器中所存储的数据进行循环右移,高位移到低位,不会移出寄存器;例如图中输入数据10101010时,寄存器存储10101010,当left为1时,变为01010100,移出了一位;当right为1后,变为了00101010;当进行循环左移时,变成01010100、10101000;当进行循环右移时,变成了10101000、01010100。满足实验设计要求。
分析:拨码开关SW7、SW6、SW5、SW4、SW3、SW2、SW1、SW0为外部数据的输入,SW7-U3为复位信号输入、SW6-U2为置位信号输入、SW5-V2为装载信号输入、SW3-V4为左移信号输入、SW2-R3为右移信号输入、SW1-T3为循环左移信号输入、SW0-T5为循环右移信号输入。LD2为寄存器中数据的展示,如上图展示了置位、复位、左移、存储、装载功能,符合实验设计要求。