[EDA]8位双向移位寄存器的设计

[EDA]8位双向移位寄存器的设计系统功能设计一个8位双向移位寄存器,实现并行输入数据、数据左移、右移、清空数据的功能。设计要求(1)可以并行置数(用4位拨码开关置数两次得到8位数据);(2)并行输出(8个led显示)功能;(3)具有双向移位输出能力(用按键选择功能);(4)具有异步清零信号;设计方案程序主要包括移位寄存器模块和按键去抖模块① Key1控制拨码输入:a) key_flag1,…

系统功能

设计一个8位双向移位寄存器,实现并行输入数据、数据左移、右移、清空数据的功能。

设计要求

(1)可以并行置数(用4位拨码开关置数两次得到8位数据);
(2)并行输出(8个led显示)功能;
(3)具有双向移位输出能力(用按键选择功能);
(4)具有异步清零信号;

设计方案

程序主要包括移位寄存器模块和按键去抖模块

① Key1 控制拨码输入:

a) key_flag1, key_state1实现Key1去抖(if(key_flag1 && (!key_state1)));
b) key_cnt [3:0]从0开始在每一次Key1 按下后加1,累积到3后再按下Key1, key_cnt 清零;
c) en_num1为高4位输入使能信号,en_num2为低4位输入使能信号,en_num3为输入确认使能信号(都为高水平有效);
d) key_cnt 的数值控制c)中3个使能信号的值;

② Key2 , Key3控制移位方向:

a) 按键去抖同Key1 a);
b) turn_left为左移使能信号,turn_right为右移使能信号(都为高水平有效);
c) key_cnt 的数值控制c)中3个使能信号的值;

③ Clk 同步时钟信号,Reset异步清零:

Verilog源代码

//1、移位寄存器模块

 module shift_register(

input  clk,
input  rst_n,

input sw1,
input sw2,
input sw3,
input sw4,

input key_in_num,	// 控制数字输入按键,按下第一次输入高4位,再按下一次输入低4位,然后再点两下确认输完数字
input key_left,		// 控制左循环按键
input key_right,	// 控制右循环按键

output [7:0] led
);

wire  key_flag1,key_state1,
		key_flag2,key_state2,
		key_flag3,key_state3;

key_filter key_filter0(
.key_in		(key_in_num),
.clk			(clk),
.rst_n		(rst_n),
.key_flag	(key_flag1),
.key_state	(key_state1)
);
reg  en_num1;
reg  en_num2;
reg  en_num3;
reg [2:0]key_cnt;

// key1按下次数改变key_cnt值
always @(posedge clk or negedge rst_n)
begin
	if(!rst_n)
		key_cnt<=3'd0;
	else if(key_flag1&&(!key_state1))
		begin
			if(key_cnt==3)
				key_cnt<=3'b000;
			else
			key_cnt<=key_cnt+1'b1;
			end
	else
	key_cnt<=key_cnt;
	end


// key_cnt值控制置数信号
always @(posedge clk or negedge rst_n )
begin 
	if(!rst_n)
 begin
 en_num1<=1'b0;
 en_num2<=1'b0;
 en_num3<=1'b0;
 end
 else begin
	case(key_cnt)
	0:begin
			en_num1<=1'b0;
			en_num2<=1'b0;
			en_num3<=1'b0;
			end
 1:begin
			en_num1<=1'b1;
			en_num2<=1'b0;
			en_num3<=1'b0;
			end
 2:begin
			en_num1<=1'b0;
			en_num2<=1'b1;
			en_num3<=1'b0;
			end
 3:begin
			en_num1<=1'b0;
			en_num2<=1'b0;
			en_num3<=1'b1;
			end
	default:begin
			en_num1<=1'b0;
			en_num2<=1'b0;
			en_num3<=1'b0;
			end
 endcase
 end
 end


reg   turn_left;
reg   turn_right;
 key_filter key_filter2(
.key_in		(key_left),
.clk			(clk),
.rst_n		(rst_n),
.key_flag	(key_flag2),
.key_state	(key_state2)
);
 key_filter key_filter3(
.key_in		(key_right),
.clk			(clk),
.rst_n		(rst_n),
.key_flag	(key_flag3),
.key_state	(key_state3)
);

// key2, key3控制移位方向
always @(posedge clk or negedge rst_n)
begin
	if(!rst_n)
	begin
	 turn_left<=1'b0;
	 turn_right<=1'b0;
	 end
	else if(key_flag2&&(!key_state2))
		begin
	 turn_left<=1'b1;
	 turn_right<=1'b0;
		end
   else if(key_flag3&&(!key_state3))
		begin
	 turn_left<=1'b0;
	 turn_right<=1'b1;
		end
	else
	begin
	 turn_left<=1'b0;
	 turn_right<=1'b0;
	 end
	 end
	 
reg [7:0] t_data;
reg  [7:0] r_data;

always @(posedge clk or negedge rst_n)
begin
	if(!rst_n)
		t_data<=8'd0;
	else if(en_num1)
		t_data[7:4]<={sw1,sw2,sw3,sw4};
	else if(en_num2)
	t_data[3:0]<={sw1,sw2,sw3,sw4};
	else 
		t_data<=t_data;
	end
	

	// 移位
	always @(posedge clk or negedge rst_n)
begin
		if(!rst_n)
		r_data<=8'd0;
		else if(en_num3)
// en_num3==1确认输入 
		r_data<=t_data;
		else if(turn_left)
		r_data<={r_data[6:0],r_data[7]};
		else if(turn_right)
		r_data<={r_data[0],r_data[7:1]};
		else
		r_data<=r_data;
	end
	
	assign led=r_data;
	endmodule
//2、按键防抖模块

module key_filter(
key_in,
clk,
rst_n,
key_flag,
key_state


);

input key_in;
input clk;
input rst_n;

output reg key_flag;
output reg key_state;

reg key_s0,key_s1,key_s2,key_s3;
wire pose,nege;
reg [3:0]state;
reg en_cnt;
reg [24:0]cnt;
reg cnt_full;


localparam 
	IDLE=4'b0001,
	FILTER=4'b0010,
	DOWN=4'b0100,
	FILTER0=4'b1000;
	
	always@(posedge clk or negedge rst_n)
	begin
		if (rst_n==0)
			begin
				key_s0<=1'b0;
				key_s1<=1'b0;
				end
				else begin
				key_s0<=key_in;
				key_s1<=key_s0;
				end
				end
				
	always@(posedge clk or negedge rst_n)
	begin
		if (rst_n==0)
			begin
	key_s2<=1'b0;
	key_s3<=1'b0;
	end
	else begin
	key_s2<=key_s1;
	key_s3<=key_s2;
	end
	end
	assign pose=(!key_s3)& key_s2;
	assign nege=key_s3&&(!key_s2);
	
	always@(posedge clk or negedge rst_n)
	begin
		if (rst_n==0)
			cnt<=25'd0;
			else if(en_cnt)
			begin
			if(cnt==999_999)
			cnt<=25'd0;
			else
			cnt<=cnt+1'b1;
			end
			else
			cnt<=25'd0;
					end
					
		always@(posedge clk or negedge rst_n)
	begin
		if (rst_n==0)
		cnt_full<=1'b0;
		else if(cnt==999_999)
		cnt_full<=1'b1;
		else
		cnt_full<=1'b0;
		end
	
					
	always@(posedge clk or negedge rst_n)
	begin
		if (rst_n==0)
			begin
			state<=IDLE;
			en_cnt<=1'b0;
		
			key_flag<=1'b0;
			key_state<=1'b1;
			end
			else begin
			case(state)
				IDLE:
				begin
				key_flag<=1'b0;
					if(nege)
					begin
					en_cnt<=1'b1;
					state<=FILTER;
					end
					else
					state<=IDLE;
					end
			FILTER:
				if(cnt_full)
				begin
				en_cnt<=1'b0;
				key_flag<=1'b1;
				key_state<=1'b0;
				state<=DOWN;
				end
				else if(pose)
				begin
				state<=IDLE;
				en_cnt<=1'b0;
				end
				else 
				state<=FILTER;
				
			DOWN:
			begin
			key_flag<=1'b0;
				if(pose)
				begin
					en_cnt<=1'b1;
					state<=FILTER0;
					end
					else
					state<=DOWN;
					end
				FILTER0:
				if(cnt_full)
				begin
				en_cnt<=1'b0;
				key_flag<=1'b1;
				key_state<=1'b1;
				state<=IDLE;
				end
				else if(nege)
				begin
				state<=DOWN;
				en_cnt<=1'b0;
				end
				else
				state<=FILTER0;
				
				default:begin
				state<=IDLE;
				en_cnt<=1'b0;
				key_flag<=1'b0;
				key_state<=1'b1;
				end
				
				endcase
				end
			end
				
				endmodule
//3、 testbench测试脚本(未加入防抖模块)

`timescale 1 ps/ 1 ps
module shift_8in_2direction_register_vlg_tst();
// constants                                           
// general purpose registers
reg eachvec;
// test vector input registers
reg clk;
reg en_num1;
reg en_num2;
reg en_num3;
reg rst_n;
reg sw1;
reg sw2;
reg sw3;
reg sw4;
reg turn_left;
reg turn_right;
// wires                                               
wire [7:0]  led;

// assign statements (if any)                          
shift_8in_2direction_register i1 (
// port map - connection between master ports and signals/registers   
	.clk(clk),
	.en_num1(en_num1),
	.en_num2(en_num2),
	.en_num3(en_num3),
	.led(led),
	.rst_n(rst_n),
	.sw1(sw1),
	.sw2(sw2),
	.sw3(sw3),
	.sw4(sw4),
	.turn_left(turn_left),
	.turn_right(turn_right)
);

initial clk=0;
always #10 clk=~clk;

initial 
begin
    // 第一组测试数据 输入(0100_0000) 先左移5次 后右移5次 
    rst_n=0;

    sw1=0;
    sw2=0;
    sw3=0;
    sw4=0;

    en_num1=0;
    en_num2=0;
    en_num3=0;
    turn_left=0;
    turn_right=0;
    //
    #100;
    rst_n=1;
    // 为高四位赋(0100)
    #100;
    en_num1=1;
    sw1=0;
    sw2=1;
    sw3=0;
    sw4=0;

    #100;
    en_num1=0;
    // 为低四位赋(0000)
    #100;
    en_num2=1;
    sw1=0;
    sw2=0;
    sw3=0;
    sw4=0;

    #100;
    en_num2=0;
    // 确认输入
    #100;
    en_num3=1;

    #100;
    en_num3=0;
    // 左移
    #100;
    turn_left=1;

    #100;
    turn_left=0;
    // 右移
    #100;
    turn_right=1;

    #100;
    turn_right=0;

    // 开始测试第二组数据 类似上组 输入(0001_1110)
    #100;
    rst_n=0;

    #100;
    rst_n=1;
    
    #100;
    en_num1=1;
    sw1=0;
    sw2=0;
    sw3=0;
    sw4=1;
    #100;
    en_num1=0;
    #100;
    en_num2=1;
    sw1=1;
    sw2=1;
    sw3=1;
    sw4=0;
    #100;
    en_num2=0;
    #100;
    en_num3=1;
    #100;
    en_num3=0;
    #100;
    turn_left=1;
    #100;
    turn_left=0;
    #100;
    turn_right=1;
    #100;
    turn_right=0;
    #100;

    $stop;
end
endmodule

仿真结果分析

  1. 初始化:
    rst_n=0; sw1=0; sw2=0; sw3=0; sw4=0;
    en_num1=0; en_num2=0; en_num3=0;
    turn_left=0; turn_right=0;
    在这里插入图片描述
  1. 测试数据:
    置rst_n=1,en_num1=1,为高位赋值(0100);
    置en_num1=0,en_num2=1,为低位赋值(0000);
    置en_num2=0,en_num3=1,确定赋值(0100_0000);
    在这里插入图片描述

a) 置en_num3 = 0; turn_left = 1;数据进行五次左移:
0100_0000 → 1000_0000 → 0000_0001 → 0000_0010 → 0000_0100 → 0000_1000
在这里插入图片描述

b) 置turn_left = 0; turn_right = 1;数据进行5次右移:
0000_1000 → 0000_0100 → 0000_0010 → 0000_0001 → 1000_0000 → 0100_0000

在这里插入图片描述

  1. 复位清零:
    置turn_right = 0; rst_n = 0,数据清零;
    0100_0000 → 0000_0000
    在这里插入图片描述

约束与综合

原理图在这里插入图片描述

引脚配置图

在这里插入图片描述

系统硬件测试

  1. 安装usb-blaster驱动,配置引脚,将程序下载到开发板中;
  2. 按下reset键清空数据;
  3. 第一次按下key1拨动拨码开关置高4位为0110;
  4. 第二次按下key1拨动拨码开关置低4位为1010;
  5. 第三次按下key1,led灯从左至右显示0110_1010;
  6. 第四次按下key1,锁定输入(此时en_num1、en_num2、en_num3全为低电平);
  7. 三次按下key3,使数据左移三次;
  8. 按下reset键清空数据;
  9. 输入第二组数据,类似2~5置0001_0111;
  10. 三次按下key2,使数据右移三次;
  11. 整理设备

今天的文章[EDA]8位双向移位寄存器的设计分享到此就结束了,感谢您的阅读。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/12788.html

(0)
编程小号编程小号

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注