原创 模块化设计之基于FPGA的简易计算器设计

2017-1-10 15:23 3239 11 11

最近在北京至芯科技参加20140712届的FPGA培训,其中夏老师课程的第一个项目就是设计一个基于FPGA的简易计算器,要求能够实现0—999999以内的整数+、-、*、/运算,并支持连续运算(连加、连减、连乘、连除)。接到题目后,我首先对设计需要的硬件进行了初步划分,初步确定了如图(1)所示的板级硬件结构。




图(1)板级硬件结构


当板级硬件结构确定之后,就该设计具体的计算器架构了。这里有两种观点,观点一是由顶自下的设计方式,即先设计顶层模块,然后再一级一级的往下设计。这种设计观念是有着多年丰富工程实践经验的李凡老师所推荐的,另一种观点是我自己的观点,也是结合本设计题目的实际情况,因为系统中涉及到了5个外设硬件模块的驱动,虽然此前还在大学里时已经都做过这些模块的驱动设计,但此次来到至芯科技,我决定还是依照夏老师讲的规范科学的设计方法,重新来设计所有的模块驱动。因为以前自己做的时候,模块设计意识不是很强,设计出来的模块不便于移植,因此,此番重做也是理所应当,既然要设计,就要设计一系列通用性强,便于移植的模块,方便以后使用。于是,接下来的任务,首先就是设计5个硬件模块的驱动。


关于驱动设计的先后顺序,是一个值得思考的地方。数码管设计可以采用仿真加板级验证的方式来设计,数码管模块的仿真比较容易做,也容易验证,led、蜂鸣器的验证就更简单,难点在于按键驱动的验证。因为按键在按下的过程中必然存在抖动,要想能够确保设计的正确性,除了仿真外,实际观察按键效果会是一个更加有效的验证方式。而观察按键效果,可以采用将按键检测模块检测到的按键信息显示在数码管或led上来实现。因此,我在设计的时候,首先设计的是数码管模块。(led模块由于过于简单,实在没必要单独为其建一个模型)


数码管的硬件电路目前在实验室的机器上,暂时没工夫再去绘制一份,所以今天先把代码贴上来,等明天把图弄来了再补上。

以下是代码片段:


//数码管扫描模块


module shumaguan(data,i_clk,rst_n,o_seg,o_sel);


input [23:0]data;

input i_clk;

input rst_n;

output [7:0]o_seg;

output [2:0]o_sel;


parameter cnt1_WIDTH = 15;

parameter cnt1_MAX = 24999;


reg [cnt1_WIDTH-1 :0] cnt1;

reg clk_1K;//扫描时钟,1KHz

reg [2:0]sel_r;//数码管位选

reg [7:0]seg_r;//数码管段选

reg [3:0]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[23:20];

1:disp_data<=data[19:16];

2:disp_data<=data[15:12];

3:disp_data<=data[11:8];

4:disp_data<=data[7:4];

5:disp_data<=data[3:0];

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


因为今天准备比较仓促,到时很多仿真文件都不在手头,等明天去教室把需要的资料弄好之后再来系统的写。


初次写博客,确实感觉准备不足,不过初稿写了,总会有这样那样的不足,于是就非得去丰富去改正所以,这样下去,我相信,我会很快习惯并爱上写博客的。


PARTNER CONTENT

文章评论0条评论)

登录后参与讨论
EE直播间
更多
我要评论
0
11
关闭 站长推荐上一条 /3 下一条