1.课程设计目的
全面熟悉、掌握Verilog HDL语言基本知识,掌握利用verilog HDL语言对常用的组合逻辑电路和时序逻辑电路编程,把编程和实际结合起来,熟悉编制和调试程序的技巧,掌握分析结果的若干有效方法,进一步提高上机动手能力,培养使用设计综合电路的能力,养成提供文档资料的习惯和规范编程的思想。
2.课程设计题目描述和要求
本课程设计完成的计费器应具有如下功能。
(1)实现计费功能,计费标准为:按行驶里程计费,起步价为7元,并在车行3km后按2元/km计费,当计费器达到或超过20元时,每千米加收50%的车费,车停止不计费。(2)现场模拟功能:以开关按键模拟千米计数,能模拟汽车启动、停止、暂停等状态。(3)将车费和路程分别以十进制形式显示出来。
3.设计思想和过程
本次出租车计费器的设计主要是基于FPGA芯片,使用硬件描述语言Verilog HDL,采用“自顶向下”的设计方法,编写-一个出租车计费器芯片,并使用quatus 软件和Modelsim软件进行编程,同时用软件进行功能和时序的仿真。把出租车计费器划分为端口定义部分、计费部分、里程部分、数码管显示部分,共同实现出租车计费以及预置和模拟汽车启动、停止、暂停等功能,并动态扫描显示车费数目和里程数。最后使用quartus 进行编译和布局布线,还可以使用时序仿真验证实际电路功能的正确性。由于本课程设计电路规模较小;调用时序仿真步骤可以省略,直接使用硬件开发板DE2-115 就可以完成整个设计的验证,同时验证的结果更加直接,所以在操作步骤中省略了时序仿真步骤,只保留功能仿真,最后的结果可以由硬件电路来完成验证。由于无法实际使用车轮来进行公里数的统计,可采用信号模拟的方式来进行代替。以使用一个输入信号,当输入信号出现一次上升沿时表示车轮运转了一次然后按照一定的数量如200次累计完成1km。 由于是近似代替,所以直接使用信号上升沿表示1km, 这样方便设计和仿真,如果需要其他的数量可以使用分频器来进行处理。在设计过程中,首先进行端口定义,money 和kilometer 分别是记录车费数和公里数,start、stop、 suspend 分别是控制开始、停止、暂停的功能按钮,a是输入信号,当其为高电平时,则认为汽车已经走了1km,相应的kilometer 加1。Money 根据题目要求随着不同的计费方式而相应的钱数,m1, m2,k1, k2分别是用数码管显示的译码数据、动态显示数据,在计算money和kilometer时分别用到两个always模块处理这两个输出信号,这样程序的大体结构就完成了,然后就是具体的部分涉及一些细节,如语法方面,注意要在一些地方加入begin...end,避免出现一些简单的语法错误。
整个计费器的设计模块代码如下:
module driver(kilometer,money,a,
stop,start,suspend,m1,m0,k1,k0,b1,b2,b3,b4);
input stop,start,suspend;
input a;
output [6:0] kilometer,money;
output [3:0] m1,m0,k1,k0;
output [6:0] b1,b2,b3,b4;
reg [6:0] kilometer,money;
reg [3:0] m1,m0,k1,k0;
reg [6:0] b1,b2,b3,b4;
reg [6:0] money_reg,kilometer_reg;
always@(posedge a ) //公里数的累计
begin
if(stop)
begin
kilometer<=0;
end
else if(start)
begin
kilometer<=0;
end
else
begin
if(suspend)
kilometer<=kilometer+1;
else
kilometer<=kilometer;
end
end
always@( kilometer) //钱数的处理
begin
if(kilometer>9)
begin
money=money+3;
end
else if(kilometer>3)
begin
money=money+2;
end
else money=7;
m1=money/10;
m0=money%10;
k1=kilometer/10;
k0=kilometer%10;
end
always@(m1) //驱动七段数码管
begin
case(m1)
4'b0000:begin b1<=7'b1000000;end
4'b0001:begin b1<=7'b1111001;end
4'b0010:begin b1<=7'b0100100;end
4'b0011:begin b1<=7'b0110000;end
4'b0100:begin b1<=7'b0011001;end
4'b0101:begin b1<=7'b0010010;end
4'b0110:begin b1<=7'b0000010;end
4'b0111:begin b1<=7'b1111000;end
4'b1000:begin b1<=7'b0000000;end
4'b1001:begin b1<=7'b0010000;end
endcase
end
always@(m0)
begin
case(m0)
4'b0000:begin b2<=7'b1000000;end
4'b0001:begin b2<=7'b1111001;end
4'b0010:begin b2<=7'b0100100;end
4'b0011:begin b2<=7'b0110000;end
4'b0100:begin b2<=7'b0011001;end
4'b0101:begin b2<=7'b0010010;end
4'b0110:begin b2<=7'b0000010;end
4'b0111:begin b2<=7'b1111000;end
4'b1000:begin b2<=7'b0000000;end
4'b1001:begin b2<=7'b0010000;end
endcase
end
always@(k1)
begin
case(k1)
4'b0000:begin b3<=7'b1000000;end
4'b0001:begin b3<=7'b1111001;end
4'b0010:begin b3<=7'b0100100;end
4'b0011:begin b3<=7'b0110000;end
4'b0100:begin b3<=7'b0011001;end
4'b0101:begin b3<=7'b0010010;end
4'b0110:begin b3<=7'b0000010;end
4'b0111:begin b3<=7'b1111000;end
4'b1000:begin b3<=7'b0000000;end
4'b1001:begin b3<=7'b0010000;end
endcase
end
always@(k0)
begin
case(k0)
4'b0000:begin b4<=7'b1000000;end
4'b0001:begin b4<=7'b1111001;end
4'b0010:begin b4<=7'b0100100;end
4'b0011:begin b4<=7'b0110000;end
4'b0100:begin b4<=7'b0011001;end
4'b0101:begin b4<=7'b0010010;end
4'b0110:begin b4<=7'b0000010;end
4'b0111:begin b4<=7'b1111000;end
4'b1000:begin b4<=7'b0000000;end
4'b1001:begin b4<=7'b0010000;end
endcase
end
endmodule
此设计模块中主要的部分有三个,第一段always 结构中计算所运行的里程数,按照之前假设的条件,以输入信号a的上升沿作为1km的计时,然后按照控制信号暂停、开始、停止等信号的不同变化来改变里程数的计数情况。设计中使用开始和停止信号的功能是为了截取旅客行驶过程中的有效距离,而暂停信号的目的是为了留待扩展,可以加入堵车时的计价功能。第二段always 结构按照里程数来统计价格,并完成了价格和里程数的个位和十位划分,产生输出信号。此段采用的是组合逻辑电路,敏感列表是第一段always中的里程数,所以要使用阻塞赋值语句,否则得到的结果就是错误的。第三部分是剩下的四个case语句,产生了价格和公里数的显示驱动。
测试所写模块的正确性,编写测试平台,代码如下:
module check;
reg A,Stop,Suspend,Start;
wire [6:0]Kilometer,Money;
wire [3:0]M1,M0,K1,K0;
wire [6:0]B1,B2,B3,B4;
initial
begin
A=1;Stop=0;Start=1;Suspend=0;
#20 A=0;Stop=0;Start=0;Suspend=0;
#20 A=1;Stop=0;Start=0;Suspend=0;
#20 A=0;Stop=0;Start=0;Suspend=1;
#20 A=1;Stop=0;Start=0;Suspend=1;
#20 A=0;Stop=0;Start=0;Suspend=0;
#20 A=1;Stop=0;Start=0;Suspend=0;
#20 A=0;Stop=0;Start=0;Suspend=0;
#20 A=1;Stop=0;Start=0;Suspend=0;
#20 A=1;Stop=0;Start=0;Suspend=0;
#20 A=0;Stop=0;Start=0;Suspend=0;
#20 A=1;Stop=0;Start=0;Suspend=0;
#20 A=0;Stop=0;Start=0;Suspend=0;
#20 A=1;Stop=0;Start=0;Suspend=0;
#20 A=0;Stop=0;Start=0;Suspend=0;
#20 A=1;Stop=0;Start=0;Suspend=0;
#20 A=0;Stop=0;Start=0;Suspend=0;
#20 A=1;Stop=0;Start=0;Suspend=0;
#20 A=1;Stop=0;Start=0;Suspend=0;
#20 A=0;Stop=0;Start=0;Suspend=0;
#20 A=1;Stop=1;Start=0;Suspend=0;
#20 A=0;Stop=0;Start=0;Suspend=0;
#50 $stop;
end
driver dr(Kilometer,Money,A,Stop,Start,Suspend,M1,M0,K1,K0,B1,B2,B3,B4);
endmodule
在测试平台中没有采用复杂的信号,直接以延迟信号输出作为各个信号的产生手段,这样整体信号容易掌握,但是编写比较麻烦。运行仿真可得图12-1 所示的功能仿真波形图,在仿真波形图中可以看到最初的star 信号开始里程数完成0的初始数值:在暂停信号suspend为高电平区间中不计数:同时不考虑a的变化快慢情况,只观察上升沿,这可以从a的高电平宽度的变化来看出:在停止信号为高电平时停止计数并得到最后的钱数。
将此设计代码放入Quartus中进行处理,可得图12-2所示的RTL结构图。通过布局布线后可以设置芯片引脚完成设计,引脚的参考配置见图12-3, 此引脚配置结果并不唯一一,可以根据设计者自已不同的选择来改变引脚的配置信号。同时要注意在设计模块中的k1、k0、ml、m0四个信号其实不需要作为输出,因为在输出的四个七段数码管中已经能够显示这四个数值了,之所以在设计模块中保留着四个信号是为了仿真时能够从波形图中看到结果并判断正确性,所以可以在最后的综合和布局布线的代码中去除这四个信号,或者不给这四个信号配备引脚,作悬空处理也可。 按照图12-3 中所示的配置完成编译下载即可在开发板上验证实际结果。
RTL
视频链接:
密码:12345678A
实验结束