完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
扫一扫,分享给好友
本帖最后由 zz912 于 2015-11-6 17:50 编辑
前段时间在闲暇至于,偶然之间在本论坛上看到了小梅哥发【芯航线FPGA学习平台众筹进度帖】然后自己就没事去关注它的进度,后来梅总开始慢慢地上传关于这块开发板的视频,自己没事就去看看,看过之后给我留下了较深的印象。 视频质量,自己去看吧看了好坏自己定,下面是链接(https://bbs.elecfans.com/home.phpmod=space&uid=696507&do=thread&view=me&from=space) 为啥说给我留下深刻印象,是因为本视频上来不是简单的将原理讲完就完事了,而是它有关于这个东西的设计文档,而且代码是全部是手敲,看出来梅总的用心。哈哈说了半天估计有人又开始说打广告了,哈哈实事求是。 水了这么半天下面开始进入正题,如何将按键次数显示到数码管上,通过标题我首先做了一个系统框架图 下来根据设计题目子模块也很快就出来了,按键检测模块和数码管显示模块,除了这两个模块之后还有按键计数模块,应该还有个二进制转BCD码的模块,可能会有人问为要加这个原因是咱们计数的是按键的次数所以数码管现实的的每位无非是0~9这十个数。至于你的A~F计数先使用不到,为啥是二进制转BCD码呢原因是数码显示的结果是以BCD码的形式输入的。下面是各个模块的框架图: 现在总的架构图以实现,接下来就是实现每个模块的设计比如状态转移图及代码实现过程后续后接着上传的 按键检测部分程序代码 01 module key_scan_flctek(clk, rst_n,key_in, key_n); 02 03 inputclk; 04 inputrst_n; 05 inputkey_in; 06 outputreg key_n; 07 08 regtemp; 09 reg[31:0] count; 10 regstate; 11 12 localparam MASK_tiME = 1000000; 13 14 always@(posedge clk or negedge rst_n) 15 begin 16 if(!rst_n) 17 begin 18 state<= 0; 19 temp<= 1; 20 count<= 0; 21 key_n<= 1; 22 end 23 else 24 case(state) 25 0 : begin 26 if(key_in== temp) 27 state <= 0; 28 else begin 29 state <= 1; 30 temp<= key_in; 31 end 32 end 33 1: begin 34 if(key_in == temp) 35 if(count < MASK_TIME-1) 36 begin 37 count<= count + 1; 38 state<= 1; 39 end 40 else 41 begin 42 key_n<= temp; 43 count<= 0; 44 state<= 0; 45 end 46 else 47 begin 48 temp<= key_in; 49 count <=0; 50 state<= 1; 51 end 52 end 53 endcase 54 end 55 56 endmodule 计数模块程序 01 modulecount_key(rst_n, key_n, count_key); 02 03 inputkey_n,rst_n; 04 output reg [19:0] count_key; 05 06 //此处必须以按键状态为时钟不能采用组合逻辑以按键状态为判断条件做判断, 07 //这样的话当按键状态为低电平时计数器会一直计数 08 //而实际的要求是如果按键按下则计一次数相背。 09 always @(posedge key_n or negedge rst_n) 10 begin 11 if(!rst_n) 12 begin 13 count_key= 0; 14 end 15 else if((count_key < 20'd999999)) 16 count_key= count_key + 1; 17 else 18 count_key= count_key; 19 20 21 end 22 23 endmodule 二进制转BCD部分(采用“大四加三”法)给大家来个例子说明一下例如输入的二进制数是8’b1111_1111,经过逐步移位的方法最终得到的BCD码为:12’b1_0101_0101,其对应的十进制百位,十位,个位,分别是:2,5,5.这种移位的方法首先设计者必须清楚的是被转换的二进制数的位宽,和最终转换为BCD码的位宽,由于中间用到一个移位寄存器此移位寄存器的位宽等于被转的二进制数位宽加上最终转换的BCD码的位宽。所以本例中的移位寄存器位宽为20,采用这种方法移位的此处比位修正的次数多一次,即就是最后一次只进行移位操作,而不进行位修正计数(每位所对应的4位BCD码如果大于四必须进行加三操作)。应用这种方法移完即可得到对应的BCD码。本例子的以为过程及修正如下表所示: 二进制转BCD代码部分 01 moduleb_BCD(count_key, data_out); 02 03 input[19:0] count_key; 04 output[23:0] data_out; 05 06 wire[43:0] shift_reg [19:0]; 07 08 assignshift_reg[19] = {23'b0, count_key, 1'b0}; 09 10 11 bcd_modify b19(.data_in(shift_reg[19]), .data_out(shift_reg[18])); 12 bcd_modify b18(.data_in(shift_reg[18]), .data_out(shift_reg[17])); 13 bcd_modify b17(.data_in(shift_reg[17]), .data_out(shift_reg[16])); 14 bcd_modify b16(.data_in(shift_reg[16]), .data_out(shift_reg[15])); 15 bcd_modify b15(.data_in(shift_reg[15]), .data_out(shift_reg[14])); 16 bcd_modify b14(.data_in(shift_reg[14]), .data_out(shift_reg[13])); 17 bcd_modify b13(.data_in(shift_reg[13]), .data_out(shift_reg[12])); 18 bcd_modify b12(.data_in(shift_reg[12]), .data_out(shift_reg[11])); 19 bcd_modify b11(.data_in(shift_reg[11]), .data_out(shift_reg[10])); 20 bcd_modify b10(.data_in(shift_reg[10]), .data_out(shift_reg[9])); 21 bcd_modify b9(.data_in(shift_reg[9]), .data_out(shift_reg[8])); 22 bcd_modify b8(.data_in(shift_reg[8]), .data_out(shift_reg[7])); 23 bcd_modify b7(.data_in(shift_reg[7]), .data_out(shift_reg[6])); 24 bcd_modify b6(.data_in(shift_reg[6]), .data_out(shift_reg[5])); 25 bcd_modify b5(.data_in(shift_reg[5]), .data_out(shift_reg[4])); 26 bcd_modify b4(.data_in(shift_reg[4]), .data_out(shift_reg[3])); 27 bcd_modify b3(.data_in(shift_reg[3]), .data_out(shift_reg[2])); 28 bcd_modify b2(.data_in(shift_reg[2]), .data_out(shift_reg[1])); 29 bcd_modify b1(.data_in(shift_reg[1]), .data_out(shift_reg[0])); 30 31 32 assigndata_out = shift_reg[0][43:20];//取出data_out的高24位即为所求的BCD码 33 34 endmodule 01 modulebcd_modify(data_in, data_out); 02 03 input[43:0] data_in; 04 output[43:0] data_out; 05 06 wire[43:0] reg_out; 07 08 bcd_sigle_modifybcd_6(.data_in(data_in[43:40]), .data_out(reg_out[43:40])); 09 bcd_sigle_modifybcd_5(.data_in(data_in[39:36]), .data_out(reg_out[39:36])); 10 bcd_sigle_modifybcd_4(.data_in(data_in[35:32]), .data_out(reg_out[35:32])); 11 bcd_sigle_modifybcd_3(.data_in(data_in[31:28]), .data_out(reg_out[31:28])); 12 bcd_sigle_modifybcd_2(.data_in(data_in[27:24]), .data_out(reg_out[27:24])); 13 bcd_sigle_modifybcd_1(.data_in(data_in[23:20]), .data_out(reg_out[23:20])); 14 15 16 assignreg_out[19:0] = data_in[19:0]; //相当于将每次只做高24位的修正地位不做修正,低20位的数据 17 assign data_out = {reg_out[42:0],1'b0}; 18 19 endmodule 01 module bcd_sigle_modify(data_in,data_out); 02 03 input[3:0] data_in; 04 outputreg [3:0] data_out; 05 06 always@ (data_in) 07 begin 08 if(data_in> 4) 09 data_out = data_in + 3; 10 else 11 data_out = data_in; 12 end 13 14 endmodule 01 module seg_n(clk, rst_n, data_in, sel,seg); 02 03 inputclk; 04 inputrst_n; 05 input[23:0] data_in; 06 outputreg [2:0] sel; 07 outputreg [7:0] seg; 08 09 wireclk_en; //数码管显示时钟标志高电平有效 10 reg[31:0] count; 11 12 13 always@(posedgeclk or negedge rst_n) 14 begin 15 if(!rst_n) begin 16 count<= 0; 17 end 18 elseif(count < 24999) 19 count<= count + 1'b1; 20 elsebegin 21 count <= 0; 22 end 23 end 24 25 assignclk_en = (count == 24999)? 1'b1 : 1'b0; 26 27//产生片选信号 28 always@(posedgeclk or negedge rst_n) 29 begin 30 if(!rst_n) 31 sel<= 3'b101; 32 elseif(clk_en) 33 begin 34 if((0< sel)&&(sel <= 5)) 35 sel<= sel- 1'b1; 36 elsesel <= 3'b101; 37 end else 38 sel<= sel; 39 end 40 41 reg[3:0] data_n; 42//获取所要显示的数据 43 always@(*) 44 begin 45 if(!rst_n) 46 data_n<= 24'hfffff0; 47 elsecase(sel) 48 0:data_n <= data_in [23:20]; 49 1:data_n <= data_in [19:16]; 50 2:data_n <= data_in [15:12]; 51 3:data_n <= data_in [11:8]; 52 4:data_n <= data_in [7:4]; 53 5:data_n <= data_in [3:0]; 54 default:data_n <=0; 55 endcase 56 end 57//进行译码操作 58 always@(*) 59 begin 60 if(!rst_n) 61 seg<= 8'hff; 62 elsecase(data_n) 63 0:seg = 8'hc0; 64 1:seg = 8'hf9; 65 2:seg = 8'ha4; 66 3:seg = 8'hb0; 67 4:seg = 8'h99; 68 5:seg = 8'h92; 69 6:seg = 8'h82; 70 7:seg = 8'hf8; 71 8:seg = 8'h80; 72 9:seg = 8'h90; 73 10: seg = 8'h8f; 74 11: seg = 8'hbf; 75 12: seg = 8'h89; 76 13: seg = 8'had; 77 14: seg = 8'hb7; 78 15: seg = 8'hff; 79 endcase 80 end 81 endmodule module key_seg_top(clk, rst_n, key_in, sel,seg); inputclk; inputrst_n; inputkey_in; output[2:0] sel; output[7:0] seg; wirekey_n; wire[19:0] count_key; wire[23:0] data_in ; key_scan_flctekkey_scan_flctek_inst(.clk(clk), .rst_n(rst_n), .key_in(key_in),.key_n(key_n)); //该模块主要是用来进行按键检测及按键消抖用的 count_keycount_key_inst(.rst_n(rst_n), .key_n(key_n), .count_key(count_key));//此模块主要是实现按键次数的计数 b_BCDb_BCD_inst(.count_key(count_key), .data_out(data_in)); //此模块主要实现将按键次数的计数值转化为BCD码,然后将转化的数值发送给数码管显示模块 seg_nseg_inst(.clk(clk), .rst_n(rst_n), .data_in(data_in), .sel(sel), .seg(seg));//实现数码管显示模块 endmodule 测试模块程序`timescale 1ns/1ns module key_seg_top_tb; regclk; regrst_n; regkey_in; wire[2:0] sel; wire[7:0] seg; key_seg_topkey_seg_top_inst(.clk(clk), .rst_n(rst_n), .key_in(key_in), .sel(sel),.seg(seg)); initial begin clk = 1; rst_n= 0; key_in = 1; #20.1 rst_n = 1; #200 key_in= 0; //抬起小于10拍 #400 key_in= 1; #10 key_in= 0; #20 key_in= 1; #80 key_in= 0; //一直抬起 key_in= 1; #200 key_in= 0; //抬起小于10拍 #400 key_in= 1; #10 key_in= 0; #20 key_in= 1; #80 key_in= 0; //一直抬起 key_in= 1; #200 key_in= 0; //抬起小于10拍 #400 key_in= 1; #10 key_in= 0; #20 key_in= 1; #80 key_in= 0; //一直抬起 key_in= 1; #200 key_in= 0; //抬起小于10拍 #400 key_in= 1; #10 key_in= 0; #20 key_in= 1; #80 key_in= 0; //一直抬起 key_in= 1; #200 key_in= 0; //抬起小于10拍 #400 key_in= 1; #10 key_in= 0; #20 key_in= 1; #80 key_in= 0; //一直抬起 key_in= 1; #200 key_in= 0; //抬起小于10拍 #400 key_in= 1; #10 key_in= 0; #20 key_in= 1; #80 key_in= 0; //一直抬起 key_in= 1; #200 key_in= 0; //抬起小于10拍 #400 key_in= 1; #10 key_in= 0; #20 key_in= 1; #80 key_in= 0; //一直抬起 key_in= 1; #200 key_in= 0; //抬起小于10拍 #400 key_in= 1; #10 key_in= 0; #20 key_in= 1; #80 key_in= 0; //一直抬起 key_in= 1; #200 key_in= 0; //抬起小于10拍 #400 key_in= 1; #10 key_in= 0; #20 key_in= 1; #80 key_in= 0; //一直抬起 key_in= 1; #200 key_in= 0; //抬起小于10拍 #400 key_in= 1; #10 key_in= 0; #20 key_in= 1; #80 key_in= 0; //一直抬起 key_in= 1; #200 key_in= 0; //抬起小于10拍 #400 key_in= 1; #10 key_in= 0; #20 key_in= 1; #80 key_in= 0; //一直抬起 key_in= 1; #200 key_in= 0; //抬起小于10拍 #400 key_in= 1; #10 key_in= 0; #20 key_in= 1; #80 key_in= 0; //一直抬起 key_in= 1; #200 key_in= 0; //抬起小于10拍 #400 key_in= 1; #10 key_in= 0; #20 key_in= 1; #80 key_in= 0; //一直抬起 key_in= 1; #200 key_in= 0; //抬起小于10拍 #400 key_in= 1; #10 key_in= 0; #20 key_in= 1; #80 key_in= 0; //一直抬起 key_in= 1; #200 key_in= 0; //抬起小于10拍 #400 key_in= 1; #10 key_in= 0; #20 key_in= 1; #80 key_in= 0; //一直抬起 key_in= 1; #200 key_in= 0; //抬起小于10拍 #400 key_in= 1; #10 key_in= 0; #20 key_in= 1; #80 key_in= 0; //一直抬起 key_in= 1; #200 key_in= 0; //抬起小于10拍 #400 key_in= 1; #10 key_in= 0; #20 key_in= 1; #80 key_in= 0; //一直抬起 key_in= 1; #200 key_in= 0; //抬起小于10拍 #400 key_in= 1; #10 key_in = 0; #20 key_in= 1; #80 key_in= 0; //一直抬起 key_in= 1; #200 key_in= 0; //抬起小于10拍 #400 key_in= 1; #10 key_in= 0; #20 key_in= 1; #80 key_in= 0; //一直抬起 key_in= 1; #200 key_in= 0; //抬起小于10拍 #400 key_in= 1; #10 key_in= 0; #20 key_in= 1; #80 key_in= 0; //一直抬起 key_in= 1; #200 key_in= 0; //抬起小于10拍 #400 key_in= 1; #10 key_in= 0; #20 key_in= 1; #80 key_in= 0; //一直抬起 key_in= 1; #200 key_in= 0; //抬起小于10拍 #400 key_in= 1; #10 key_in= 0; #20 key_in= 1; #80 key_in= 0; //一直抬起 key_in= 1; #200 key_in= 0; //抬起小于10拍 #400 key_in= 1; #10 key_in= 0; #20 key_in= 1; #80 key_in= 0; //一直抬起 key_in= 1; #200 key_in= 0; //抬起小于10拍 #400 key_in= 1; #10 key_in= 0; #20 key_in= 1; #80 key_in= 0; //一直抬起 key_in= 1; end always#10 clk = ~clk; endmodule
|
|
相关推荐
6个回答
|
|
对你的key_out信号表示很有兴趣,等着看看你是怎么处理我想象中的问题的
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@小梅哥, 给些意见和建议
|
|
|
|
|
|
|
|
你正在撰写答案
如果你是对答案或其他答案精选点评或询问,请使用“评论”功能。
707 浏览 0 评论
420 浏览 0 评论
求FPGA 驱动控制ltc2271 或者 ltc2180 或者 ltc2190或者 ltc2202 的代码
1795 浏览 0 评论
485 浏览 0 评论
求助:遇见诡异问题,FPGA模块A输出端口连接模块B输入后,模块A不能正常工作的
1912 浏览 1 评论
4647 浏览 104 评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-8-31 14:06 , Processed in 0.846470 second(s), Total 79, Slave 61 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191