赞
踩
设计一个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异步清零:
//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,使数据右移三次;
- 整理设备
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。