最近在北京至芯科技参加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
因为今天准备比较仓促,到时很多仿真文件都不在手头,等明天去教室把需要的资料弄好之后再来系统的写。
初次写博客,确实感觉准备不足,不过初稿写了,总会有这样那样的不足,于是就非得去丰富去改正所以,这样下去,我相信,我会很快习惯并爱上写博客的。
文章评论(0条评论)
登录后参与讨论