具体这篇文章分为两个相对前文复杂一点的实验,均与板载Led、Rst复位按键和key0-key3四个电键的操作有关。其一为按键对应流水灯点亮的一种模式设计,其二是简易自动售货机的设计。此外本章结合了Altera公司的CycloneⅣ FPGA芯片、正点原子公司设计的新起点开发板和QuartusⅡ设计综合软件与Robei的协同使用。个人认为Robei在代码与testbench的验证方面比较好用,而管脚约束、综合、生成电路图、下载验证方面还是需要依靠QuartusⅡ来玩。
一、流水灯设计:
依照以下步骤进行操作,即可完成流水灯设计的全过程,详细的代码内容依惯例贴在文章最后。
以上1-9的九个步骤即是用最浅显简单的描述方式讲明了【CPLD(大规模集成电路)/FPGA芯片硬件设计】从设计师的脑海里初想法或者工程师们的手稿到最终拿出成品的步骤。虽然实例再简单不过,但是化繁为简也是我们一直需要追求的东西。例如笔者最近有在接触学习的Python AI(人脸识别等)硬件设计和信号处理系统硬件设计,其本质过程也无非上面9点,如果能将代码、电路、板级的编写、修改、验证变得和流水灯设计一样简单,那是一件多么振奋人心的事情!
二、自动售货机设计:
1、原理和思路分析:
自动售货机的信号定义:clk:时钟输入;reset:系统复位信号;half_dollar:代表投入5角硬币;one_dollar:代表投入1元硬币;half_out:表示找零信号;dispense:表示机器售出一瓶饮料。当reset=0时,售货机处于工作状态,此时连续往售货机中投硬币(可以是5角也可以是一元),投入最后一枚硬币时,如果之前投入的硬币总和为2.5元,则可以取走一瓶饮料,如果少于2.5元则继续投币,如果为3元则显示可以取出一瓶饮料,而且找零显示信号为高电平。具体的if语句思路参照表格如下,这里需要感谢@FPGA攻城狮的表格绘制
2、实际操作过程的九个步骤图例:
具体操作步骤都已经在上述流水灯中进行详解详细,以下模仿这个九步法,同时依据上述的自动售货机原理,实现这个设计。此程序的设计仍然是遵从Robei和QuartusⅡ结合的开发方式。
事实上我们点按了key1交钱之后,L1和L4强光量起,L2和L3由于没有控制弱光量起,这正是我们需要的结果。
以下是我们这次用到的两个实验的相关代码,由于Robei的存在,实际编写的时候关于模块变量声明的部分代码会被软件自动给出,仅需写核心操作部分的代码,这是我们不选择完全用QuartusⅡ设计到底的原因。
//流水灯
module light(
swt,
led);
//---Ports declearation: generated by Robei---
input [3:0] swt;
output [3:0] led;
wire [3:0] swt;
wire [3:0] led;
//----Code starts here: integrated by Robei-----
assign led[0]=~swt[0];
assign led[1]=swt[1]&~swt[2];
assign led[3]=swt[2]&swt[3];
assign led[2]=(swt[1]&~swt[2])|(swt[2]&swt[3]);
endmodule //light
//自动售货机
module sell(
clk,
rst,
one_dollar,
half_dollar,
half_out,
dispense);
//---Ports declearation: generated by Robei---
input clk;
input rst;
input one_dollar;
input half_dollar;
output half_out;
output dispense;
wire clk;
wire rst;
wire one_dollar;
wire half_dollar;
reg half_out;
reg dispense;
//----Code starts here: integrated by Robei-----
parameter idle=0,half=1,one=2,one_half=3,two=4;
reg[2:0] D;
always @(posedge clk)
begin
if(!rst)
begin
dispense=0;
half_out=0;
D=idle;
end
case(D)
idle:
if(!half_dollar)
D=half;
else if(!one_dollar)
D=one;
half:
if(!half_dollar)
D=one;
else if(!one_dollar)
D=one_half;
one:
if(!half_dollar)
D=one_half;
else if(!one_dollar)
D=two;
one_half:
if(!half_dollar)
D=two;
else if(!one_dollar)
begin
dispense=1;
D=idle;
end
two:
if(!half_dollar)
begin
dispense=1;
D=idle;
end
else if(!one_dollar)
begin
dispense=1;
half_out=1;
D=idle;
end
endcase
end
endmodule //sell
//流水灯testbench
module light_tb();
reg [3:0] switches;
wire [3:0] leds;
//----Code starts here: integrated by Robei-----
initial
begin
#5 switches=4'b1111;
#5 switches=4'b1110;
#5 switches=4'b1101;
#5 switches=4'b1010;
#5 switches=4'b1011;
#5 switches=4'b0110;
#5 switches=4'b0101;
#5 switches=4'b0110;
#10 $finish;
end
initial begin
$dumpfile ("D:/Robei/RobeiJoey_Project/light/light_tb.vcd");
$dumpvars;
end
//---Module instantiation---
light light1(
.swt(switches),
.led(leds));
endmodule //light_tb
//自动售货机testbench
module sell_tb();
reg clk;
reg rst;
reg one_dollar;
reg half_dollar;
wire half_out;
wire dispense;
//----Code starts here: integrated by Robei-----
initial begin
one_dollar=0;
half_dollar=0;
rst=0;
clk=0;
#100 rst=1;
repeat(2)@(posedge clk);
#2 one_dollar=1;
repeat(1)@(posedge clk);
#2 one_dollar=0;
repeat(2)@(posedge clk);
#2 one_dollar=1;
repeat(1)@(posedge clk);
#2 one_dollar=0;
repeat(2)@(posedge clk);
#2 one_dollar=1;
repeat(1)@(posedge clk);
#2 one_dollar=0;
#20 rst=0;
#100 rst=1;
repeat(2)@(posedge clk);
#2 one_dollar=1;
repeat(1)@(posedge clk);
#2 one_dollar=0;
repeat(2)@(posedge clk);
#2 one_dollar=1;
repeat(1)@(posedge clk);
#2 one_dollar=0;
repeat(2)@(posedge clk);
#2 half_dollar=1;
repeat(1)@(posedge clk);
#2 half_dollar=0;
#20 rst=0;
#5 $finish;
end
always #10 clk=~clk;
initial begin
$dumpfile ("D:/Robei/RobeiJoey_Project/sell/sell_tb.vcd");
$dumpvars;
end
//---Module instantiation---
sell sell1(
.clk(clk),
.rst(rst),
.one_dollar(one_dollar),
.half_dollar(half_dollar),
.half_out(half_out),
.dispense(dispense));
endmodule //sell_tb