verilog 移位寄存器与流水灯「建议收藏」

2022-09-13 10:24:48 浏览数 (1)

大家好,又见面了,我是你们的朋友全栈君。

用Verilog写一个简单的多功能移位寄存器,并在移位寄存器的基础上进行修改,利用移位功能形成流水灯的效果 基本的功能如下:

寄存器示意图见下方虚拟面板图 有两种改进方式: 第一种是把最后一个功能改成循环右移,即此功能模式下,按一下时钟按键(代表时钟信号到来),高三位往右移一位,最低位移动到最高位。按一次移位一次,形成流水灯效果 第二种在第一种的基础上把按键时钟改成接入内部时钟,每隔一段时间时钟信号来临一次,无需手动操作,形成自动移位的流水灯效果

基本功能的移位寄存器的主要文件Virtual_Lab_Top.v中的代码:

代码语言:javascript复制
//移位寄存器实验
`default_nettype none 
module Virtual_Lab_Top 
(
    input  wire  CLOCK,
    input  wire  [4:0] BUTTON, //按键
    input  wire [35:0] SWITCH, //开关
    output wire [35:0] LED,    //指示灯 
    output wire  [3:0] HEX0,   //数码管
	 output reg   [3:0] Z
); 

//输入端口赋值给内部信号
wire C    = BUTTON[1];
wire R    = BUTTON[0];
wire E    = SWITCH[6];
wire f1   = SWITCH[5];
wire f0   = SWITCH[4];
wire [3:0] X = SWITCH[3:0];

//实验逻辑
wire i;
wire [3:0] D;
assign i = f1&~f0&Z[3];
assign D = {4{~f1&f0}}&X|{4{f1&i}};

always @ (posedge C or posedge R)
begin
	if(R)
		Z<=0;
	else if(C&E&~f1)
		Z<=D;
	else
		Z<={i,Z[3:1]};
end

//内部信号赋值给输出端口(指示灯)观察
assign LED[3:0]  = Z[3:0];

//内部信号赋值给输出端口(数码管)观察
assign HEX0 = D;

endmodule

第一种改进后主要文件Virtual_Lab_Top.v中的代码:

代码语言:javascript复制
//流水灯实验
`default_nettype none 
module Virtual_Lab_Top 
(
    input  wire  CLOCK,
    input  wire  [4:0] BUTTON, //按键
    input  wire [35:0] SWITCH, //开关
    output wire [35:0] LED,    //指示灯 
	 output reg   [3:0] Z
); 

//输入端口赋值给内部信号
wire C    = BUTTON[1];
wire R    = BUTTON[0];
wire E    = SWITCH[6];
wire f1   = SWITCH[5];
wire f0   = SWITCH[4];
wire [3:0] X = SWITCH[3:0];

//实验逻辑
wire i;
assign i = f1&~f0&Z[3];

always @ (posedge C or posedge R)
begin
	if(R)
		Z<=0;
	else if(C&E&~f1&~f0)
		Z<={Z[0],Z[3:1]};
	else if(C&E&~f1&f0)
		Z<=X;
	else
		Z<={i,Z[3:1]};
end

//内部信号赋值给输出端口(指示灯)观察
assign LED[3:0]  = Z[3:0];

endmodule

第二种改进: 把第一种改进的代码中的 wire C = BUTTON[1]; 这条语句删掉,然后把 always @ (posedge C or posedge R) 语句中的C改成CLOCK。我们要接入内部时钟,所以要先把按键时钟删掉。 加入分频器文件clock_divider.v,采用的是偶分频方法。一般板子的晶振频率太高,所以要将原有时钟频率分频降低,常见板子的晶振频率为50MHz,以这个频率为标准,在工程中的JuLabPocket_TOP.v文件中,将直接接入原频率的语句 wire CLOCK = CLOCK_50; 删去,然后在该文件合适处加入下列语句

代码语言:javascript复制
//------------ 时钟 --------------------------------------------------------// 
	wire CLOCK_divided;
	//使用时钟分频器模块产生1kHz的时钟。可以修改RATIO参数改变输出频率。
	clock_divider #(.RATIO(10000000)) clk_inst(.clkin(CLOCK_50), .rst(1'b0), .clkout(CLOCK_divided));

   wire CLOCK = CLOCK_divided;  //用分频后的CLOCK_divided作为时钟

这样调用了分频器给时钟信号变量接入分频后的频率,如果流水灯移位的速度还是太快,可以把参数RATIO调大,太慢就调小,建议直接在后面加一个0或减一个0或着减半

完整的工程文件我已经上传到CSDN了,可以去我的主页查看并下载完整的工程文件进行使用,压缩包中有三个文件夹,对应三个版本的完整工程文件,基础版本的是shifter文件夹,第一种改进的是led文件夹,第二种改进的是CLOCK & led文件夹,若CLOCK & led文件夹的工程文件不能在Quartus II中正常打开,则把文件夹名中的&符号删掉再打开即可 前两种版本的工程内包含文件如下图,第三种的多了一个clock_divider.v:

WeLab虚拟面板设置图片:

以上为基础版本,第一种改进版本删去数码管,第二种改进版本删去clock时钟对应的按键 X输入数据,f1、f0是输入控制位F的高位和地位,数码管表示选择器的结果,enable开关置1则使能,置0则不使能,重置按键重置显示结果,按键时钟按下即代表时钟信号来临一次

注意:接入内部时钟的时候虚拟实验板由于软件的接收静态数据原因可能显示不出来流水灯的自动移位动态效果,但实际板子上会有效果显示出来,实际板子上分配的led灯真的会有流水灯的自动移位动态效果,如果是使用实际的实验板可以观察实验板

发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/160230.html原文链接:https://javaforall.cn

0 人点赞