4.7 典型实例7:自动转换量程频率计控制器
4.7.1 实例内容及目标
1.实例内容
本实例使用Verilog HDL设计一个可自动转换量程的频率计控制器。在设计过程中,使用了状态机的设计方法,读者可根据综合实例6的流程将本实例的语言设计模块添加到自己的工程中。
2.实例目标
通过本实例,读者应达到下面的目的。
· 掌握使用Verilog设计状态机的方法。
· 掌握Verilog设计的一般方法。
4.7.2 原理简介
频率计是电路调试里面常常用到的一种仪器。本实例提到的自动转换量程频率计控制器并不是讲解如何设计一个频率计,而是讲解如何设计这个频率计的量程转换机制。通过Verilog语言设计将量程转换变成自动化,自适应地将输入反映至量程上。
此自动转换量程频率计需要外部提供一个超量程信号和一个欠量程信号,代表输入比当前量程的状态。这两个信号可以通过其他的模块或者装置获得,读者可自行分析。
同时,该频率计还向外部提供一个用于选择标准时基的信号。通过该信号,频率计可以完成量程的切换和显示。读者可根据频率计其他模块的需要调整输出信号的设计。
4.7.3 代码分析
下面给出自动转换量程频率计控制器的Verilog源代码,首先介绍端口信号的定义及说明,读者可以通过这些端口将此控制器模块实例化至自己的工程设计中。
· clk:输入时钟。
· clear:异步复位信号。
· reset:用来在量程转换开始时复位计数器。
· std_f_sel:用来选择标准时基。
· cntover:代表超量程。
· cntlow:代表欠量程。
module control(std_f_sel,reset,clk,clear,cntover,cntlow);
//端口说明
output[1:0] std_f_sel;
output reset;
input clk,clear,cntover,cntlow;
//内部信号说明
reg[1:0] std_f_sel;
reg reset;
reg[5:0] present,next; //用于保存当前状态和次态的中间变量
//状态编码,采用独热码
parameter start_fl00k = 6'b000001, //状态A
fl00k_cnt = 6'b000010, //状态B
start_fl0k = 6'b000100, //状态C
fl0k_cn = 6'b001000, //状态D
start_flk = 6'b010000, //状态E
flk_cnt = 6'b100000; //状态F
always @(posedge clk or posedge clear) begin
if(clear)
present<=start_fl0k; //异步复位至start_fl0k状态
else
present<=next; //状态转换
end
always @(present or cntover or cntlow) begin //状态转换的触发信号列表
case(present) //用case语句描述状态转换
start_fl00k: //100k量程状态
next<=fl00k_cnt;
fl00k_cnt: begin //100k量程控制状态
if(cntlow) //欠量程
next<=start_fl0k; //进入10k量程状态
else
next<=fl00k_cnt; //保持100k量程控制状态
end
start_fl0k: //10k量程状态
next<=fl0k_cnt;
fl0k_cnt: begin //10k量程控制状态
if(cntlow) //欠量程
next<=start_flk; //进入1k量程状态
else if(cntover) //过量程
next<=start_fl00k; //进入100k量程状态
else
next<=fl0k_cnt; //保持1k量程控制状态
end
start_flk: //1k量程状态
next<=flk_cnt;
flk_cnt: begin //1k量程控制状态
if(cntover) //过量程
next<=start_fl0k; //进入10k量程状态
else
next<=flk_cnt; //保持1k量程控制状态
end
default:
next<=start_fl0k; //缺省状态为10k量程状态
endcase
end
//各状态的输出控制模块
always @(present) begin
case(present)
start_fl00k: begin //100k量程状态输出控制
reset=1;
std_f_sel=2'b00;
end
fl00k_cnt: begin //100k量程控制状态输出控制
reset=0;
std_f_sel=2'b00;
end
start_fl0k: begin //10k量程状态输出控制
reset=1;
std_f_sel=2'b01;
end
fl0k_cnt: begin //10k量程控制状态输出控制
reset=0;
std_f_sel=2'b01;
end
start_flk: begin //1k量程状态输出控制
reset=1;
std_f_sel=2'b11;
end
flk_cnt: begin //1k量程控制状态输出控制
reset=0;
std_f_sel=2'b11;
end
default: begin //默认(10k量程)状态输出控制
reset=1;
std_f_sel=2'b01;
end
endcase
end
endmodule
在状态机设计中,常常将状态转换和状态输出控制分为两个部分进行设计,方便语言的编写修改和读写规则。在下面的源代码中读者应该注意这个设计的特点。
4.7.4 参考设计
本实例相关参考设计文件在本书实例代码的“典型实例7”文件夹。