热度 25
2014-8-23 21:47
3024 次阅读|
1 个评论
最近在北京至芯科技参加20140712届的FPGA培训,其中夏老师课程的第一个项目就是设计一个基于FPGA的简易计算器,要求能够实现0—999999以内的整数+、-、*、/运算,并支持连续运算(连加、连减、连乘、连除)。接到题目后,我首先对设计需要的硬件进行了初步划分,初步确定了如图(1)所示的板级硬件结构。 图(1)板级硬件结构 当板级硬件结构确定之后,就该设计具体的计算器架构了。这里有两种观点,观点一是由顶自下的设计方式,即先设计顶层模块,然后再一级一级的往下设计。这种设计观念是有着多年丰富工程实践经验的李凡老师所推荐的,另一种观点是我自己的观点,也是结合本设计题目的实际情况,因为系统中涉及到了5个外设硬件模块的驱动,虽然此前还在大学里时已经都做过这些模块的驱动设计,但此次来到至芯科技,我决定还是依照夏老师讲的规范科学的设计方法,重新来设计所有的模块驱动。因为以前自己做的时候,模块设计意识不是很强,设计出来的模块不便于移植,因此,此番重做也是理所应当,既然要设计,就要设计一系列通用性强,便于移植的模块,方便以后使用。于是,接下来的任务,首先就是设计5个硬件模块的驱动。 关于驱动设计的先后顺序,是一个值得思考的地方。数码管设计可以采用仿真加板级验证的方式来设计,数码管模块的仿真比较容易做,也容易验证,led、蜂鸣器的验证就更简单,难点在于按键驱动的验证。因为按键在按下的过程中必然存在抖动,要想能够确保设计的正确性,除了仿真外,实际观察按键效果会是一个更加有效的验证方式。而观察按键效果,可以采用将按键检测模块检测到的按键信息显示在数码管或led上来实现。因此,我在设计的时候,首先设计的是数码管模块。(led模块由于过于简单,实在没必要单独为其建一个模型) 数码管的硬件电路目前在实验室的机器上,暂时没工夫再去绘制一份,所以今天先把代码贴上来,等明天把图弄来了再补上。 以下是代码片段: //数码管扫描模块 module shumaguan(data,i_clk,rst_n,o_seg,o_sel); input data; input i_clk; input rst_n; output o_seg; output o_sel; parameter cnt1_WIDTH = 15; parameter cnt1_MAX = 24999; reg cnt1; reg clk_1K;//扫描时钟,1KHz reg sel_r;//数码管位选 reg seg_r;//数码管段选 reg disp_data;//单位显示数据缓存 //1KHz时钟分频计数器 always@(posedge i_clk) begin if(!rst_n)cnt1=0; else if(cnt1==cnt1_MAX)cnt1=0; else cnt1=cnt1+1'b1; end //得到1KHz时钟 always@(posedge i_clk) begin if(!rst_n)clk_1K=0; else if(cnt1==cnt1_MAX) clk_1K=~clk_1K; else ; end //位选信号控制 always@(posedge clk_1K) begin if(!rst_n)sel_r=3'd0; else if(sel_r == 3'd6) sel_r=3'd0; else sel_r=sel_r+1'b1; end //根据不同的数码管位选择不同的待显示数据 always@(*) begin case(sel_r) 0:disp_data=data ; 1:disp_data=data ; 2:disp_data=data ; 3:disp_data=data ; 4:disp_data=data ; 5:disp_data=data ; default :disp_data=4'd0; endcase end //数据译码,将待显示数据翻译为符合数码管显示的编码 always@(disp_data) begin case(disp_data) 4'd0: seg_r=8'hc0; 4'd1: seg_r=8'hf9; 4'd2: seg_r=8'ha4; 4'd3: seg_r=8'hb0; 4'd4: seg_r=8'h99; 4'd5: seg_r=8'h92; 4'd6: seg_r=8'h82; 4'd7: seg_r=8'hf8; 4'd8: seg_r=8'h80; 4'd9: seg_r=8'h90; 4'd10: seg_r=8'h88; 4'd11: seg_r=8'h83; 4'd12: seg_r=8'hc6; 4'd13: seg_r=8'ha1; 4'd14: seg_r=8'h86; 4'd15: seg_r=8'h8e; default : seg_r=8'hff; endcase end assign o_seg = seg_r; assign o_sel = sel_r; endmodule 因为今天准备比较仓促,到时很多仿真文件都不在手头,等明天去教室把需要的资料弄好之后再来系统的写。 初次写博客,确实感觉准备不足,不过初稿写了,总会有这样那样的不足,于是就非得去丰富去改正所以,这样下去,我相信,我会很快习惯并爱上写博客的。