FPGA 课程设计
题目:基于 FPGA 的计数显示控制设计
班级: 微电子 1001
姓名:
学号: 1006080114
设计任务
1. 基于 Quartus II 软件完成十进制加法计数器、分频器、数码管动态扫描显示设计;
2. 采用 Modelsim 仿真软件对上述设计进行仿真验证;
3. 将上述各模块按照一定的连接关系连接,使其实现功能。
一、 总体设计方案
设计一个 led 秒钟系统,8 位数码管同时显示秒数,秒数一秒一动,可通过开关控制开始,
暂停,置零。
二、 各功能模块设计
1. 十进制加法计数器的设计
if(!rst_n) data_out_r <= 4'd0;
else if(EN) begin
1.1 代码
module adder (clk,rst_n,EN,clr,data_out);
input clk,rst_n,EN,clr;
output data_out;
wire[3:0] data_out;
reg[3:0] data_out_r;
always @ (posedge clk or negedge rst_n) begin
end
assign data_out = data_out_r;
endmodule
1.2 测试文件(Test Bench)
`timescale 1 ns/ 1 ps
module adder_vlg_tst();
reg EN;
if(clr) data_out_r <= 4'd0;
else begin
end
end
data_out_r = data_out_r + 1'b1;
if(data_out_r == 4'd10) data_out_r = 4'd0;
.EN(EN),
.clk(clk),
.clr(clr),
.data_out(data_out),
.rst_n(rst_n)
clk = 0;
forever #10 clk = ~clk;
reg clk;
reg clr;
reg rst_n;
wire [3:0] data_out;
adder i1 (
);
initial
begin
end
initial
begin
end
endmodule
1.3 仿真波形
rst_n = 0;
EN = 0;
clr = 0;
#20 rst_n = 1;
#10 EN = 1;
#20 clr = 1;
#20 clr = 0;
#200 $stop;
2. 分频器的设计
2.1 源代码
module clkdiv
#(parameter M = 100) //参数定义,默认为 100
(input wire clk,
output wire clk_div_M);
cnt <= 0;
clk_div_r = ~clk_div_r;
if(cnt == (M/2-1) )
begin
end
else cnt <= cnt + 1'b1;
localparam N = log2(M/2);//M/2 值所需位数
reg clk_div_r = 0;
assign clk_div_M = clk_div_r;
reg[N-1:0] cnt = 0; //分频计数器
always @ (posedge clk)
begin
end
//log2 constant function
function integer log2(input integer n);
begin
end
endfunction
endmodule
2.1 测试文件(Test Bench)
integer i;
log2 = 1;
for(i=0; 2**i
3. 数码管动态扫描显示设计
if(count == 3'b111) count <= 3'b000;
else count <= count + 1'b1;
3.2 源代码
module SMG (clk,data_in,wei,duan);
input wire clk;
input wire[3:0] data_in;
output wire[7:0] wei;
output wire[7:0] duan;
reg[7:0] wei_r = 8'hff;
reg[7:0] duan_r = 8'hff;
assign wei = wei_r;
assign duan=duan_r;
reg[2:0] count = 3'd0; //位选扫描信号
reg[7:0] temp = 8'hff; //显示编码
always @ (posedge clk) begin //位选扫描信号自加
end
always @ (posedge clk) begin
end
always @ (posedge clk) begin
3'd1: begin wei_r <= 8'h01; duan_r <= temp;end
3'd2: begin wei_r <= 8'h02; duan_r <= temp;end
3'd3: begin wei_r <= 8'h04; duan_r <= temp;end
3'd4: begin wei_r <= 8'h08; duan_r <= temp;end
3'd5: begin wei_r <= 8'h10; duan_r <= temp;end
3'd6: begin wei_r <= 8'h20; duan_r <= temp;end
3'd7: begin wei_r <= 8'h40; duan_r <= temp;end
3'd8: begin wei_r <= 8'h80; duan_r <= temp;end
default:begin wei_r <= 8'bx;duan_r <= 8'bx;end
case(count)
endcase
case(data_in)
4'b0000: temp=8'b11000000; //共阳数码管显示 0 的段码
4'b0001: temp=8'b11111001; //共阳数码管显示 1 的段码
4'b0010: temp=8'b10100100; //
4'b0011: temp=8'b10110000; //
4'b0100: temp=8'b10011001; //
endcase
clk = 0;
forever #10 clk = ~clk;
4'b0101: temp=8'b10010010; //
4'b0110: temp=8'b10000010; //
4'b0111: temp=8'b11111000; //
4'b1000: temp=8'b10000000; //
4'b1001: temp=8'b10010000; //共阳数码管显示 9 的段码
4'b1010: temp=8'b10001000; //共阳数码管显示 A 的段码
4'b1011: temp=8'b10000011; //共阳数码管显示 B 的段码
4'b1100: temp=8'b11000110; //共阳数码管显示 C 的段码
4'b1101: temp=8'b10100001; //共阳数码管显示 D 的段码
4'b1110: temp=8'b10000110; //共阳数码管显示 E 的段码
4'b1111: temp=8'b10001110; //共阳数码管显示 F 的段码
default: temp=8'hFF;
end
endmodule
3.2 测试文件(Test Bench)
`timescale 1 ns/ 1 ps
module SMG_vlg_tst();
reg clk;
reg [3:0] data_in;
wire [7:0] duan;
wire [7:0] wei;
SMG i1 (
.clk(clk),
.data_in(data_in),
.duan(duan),
.wei(wei)
);
initial begin
end
initial begin
end
endmodule
3.3 仿真波形
data_in = 0;
forever #40 data_in = data_in + 1'b1;
#1000 $stop;
三、 设计实现
clk_50M;
rst_n;
EN;
clr;
1.1 顶层代码
module add_ten(clk_50M,rst_n,EN,clr,wei,duan);
input wire
input wire
input wire
input wire
output wire[7:0] wei;
output wire[7:0] duan;
wire[3:0] data_r; // data 为中间变量,用于加法器-->数码管传递
/***** 分频器设计例化 *********/
wire clk_1M,clk_1K,clk_1HZ;
clkdiv #(.M(50))
clkdiv_1M (.clk(clk_50M),.clk_div_M(clk_1M));
//50 分频--->1MHZ
//1000 分频--->1KHZ,给数码管扫描
//1000 分频--->1HZ,给加法计数器
inst(.clk(clk_1HZ),.rst_n(rst_n),.EN(EN),.clr(clr),.data_out(data_r));
clkdiv_1HZ (.clk(clk_1K),.clk_div_M(clk_1HZ));
clkdiv_1000 (.clk(clk_1M),.clk_div_M(clk_1K));
clkdiv #(.M(1000))
clkdiv #(.M(1000))
/***** 加法计数器设计例化 *********/
adder
/***** 数码管设计例化 *********/
SMG SMG_1 (.clk(clk_1K), .data_in(data_r),.wei(wei),.duan(duan));
endmodule
1.2 RTL 视图
四、 心得体会
为期一周的 FPGA 课程设计结束了,自己感觉不是很顺利的完成课设。老师出的题看似
很简单,但还是让我花了很多时间使其接近完美。我自学 FPGA 已有一年时间,期间也写过
不少 verilog 代码,当我看到课设题目时,心想这个题我一个早上就可以实现。可能是有点
心急吧,就开始上手了,但后来发现有点不对劲。因为我以前的代码都是在一个 module 里
面实现的,没有分模块,这块涉及到模块的例化问题。
最后仔细思考后,开始自底向上分模块设计,依次设计分频器、加法计数器、数码管模
块。最终通过综合编译后下载到硬件上,各个功能看似正常。于是拿给老师检查,老师看后
对我的分频模块不满意,因为我是把 50MHZ 的频率直接分到 1HZ,中间用到的计数器很大,
可重用性差。后来我把分频通过几个分频模块级联来实现,但之后感觉很麻烦,每用一个分
频模块都要重新建文件且对代码做好多修改。在老师的提示下我只做了一个带参数的分频器
模块,只要修改一个参数就可以实现一种分频功能。这样大大的提高了代码的利用率,可重
用行强。
通过这次课设,让我对 Modelsim 仿真的使用更加熟练。有时候遇到这样的问题:我的
Test Bench 文件是正确的,但在 Wave 页面只出现信号名字而没有波形。这个问题困扰了我
好长时间,于是我请教我的网友“北方佳人”,他很热情,跟他的同学一块为我找问题,后
来发现是我的代码里面没有给信号赋初值,如果没有处置 Modelsim 是不会工作的。这下领
教了,细节啊,这样的细节困扰我这么长时间。
总结:这次课设看似功能简单,但它包含了 FPGA 设计中最核心、最重要的问题,很有
深度。今后学习还是要扎实点,把简单的东西在深度上多挖掘,只要基础打好了,开发大的
项目就不会在犯低级错误了。