系统功能
设计一个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
仿真结果分析
- 初始化:
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;
- 测试数据:
置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
- 复位清零:
置turn_right = 0; rst_n = 0,数据清零;
0100_0000 → 0000_0000
约束与综合
原理图
引脚配置图
系统硬件测试
- 安装usb-blaster驱动,配置引脚,将程序下载到开发板中;
- 按下reset键清空数据;
- 第一次按下key1拨动拨码开关置高4位为0110;
- 第二次按下key1拨动拨码开关置低4位为1010;
- 第三次按下key1,led灯从左至右显示0110_1010;
- 第四次按下key1,锁定输入(此时en_num1、en_num2、en_num3全为低电平);
- 三次按下key3,使数据左移三次;
- 按下reset键清空数据;
- 输入第二组数据,类似2~5置0001_0111;
- 三次按下key2,使数据右移三次;
- 整理设备
今天的文章[EDA]8位双向移位寄存器的设计分享到此就结束了,感谢您的阅读。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/12788.html