数字频率计_数字频率计设计
数字频率计由刀豆文库小编整理,希望给你工作、学习、生活带来方便,猜你可能喜欢“数字频率计设计”。
//*********************************************************************
//* 标题: 简易数字频率计 //* 文件: topdesign.v
//* 作者: SJ&QJY
//* 日期: 2009.06.10 //* 修改: 2009.12.20
//* 软件: Xilinx ISE 7.1 SP4
//* 芯片: Xilinx Spartan2 FPGA(XC2S200-pq208)
//* 说明: 测频率并用LCD显示,从信号源接入一个信号(正弦波,三角波或者方波),经过AD1转换后,送入FPGA中。
//在FPGA中,使用双值法整形,得到标准的方波,然后测出频率,并送入1602中显示。经测试,其测频误差小于0.5%,其测频范围为10Hz-10MHz。
//********************************************************************* //* 注意: 输入信号电压峰峰值不要超过AD输入范围,即4V。
//*********************************************************************
//---------------module topdesign(clk, rst, lcd_rs, lcd_rw, lcd_en, lcd_d, ad1_clk, ad1_d);
input clk;
//时钟信号40MHz input rst;
//全局复位信号
output lcd_rs;//LCD数据/命令选择信号,'1'表示数据输入,'0'表示命令输入
output lcd_rw;
//LCD读/写信号,'1'表示读,'0'表示写
output reg lcd_en;
//LCD使能信号,'1'有效
output[7:0] lcd_d;
//LCD数据总线(8位)
output ad1_clk;
//AD时钟信号
input[11:0] ad1_d;
//AD9224,12位AD输入
//LCD时序常量信号
parameter[10:0] IDLE = 11'b00000000000;
//初始化
parameter[10:0] CLEAR = 11'b00000000001;
//清屏
parameter[10:0] RETURNCURSOR = 11'b00000000010;//归位
parameter[10:0] SETMODE = 11'b00000000100;
//设置输入模式。此状态为完成一个字符码传送后,AC自动减1,显示不发生移位
parameter[10:0] SWITCHMODE = 11'b00000001000;//显示开关控制
parameter[10:0] SHIFT = 11'b00000010000;//光标或显示移位
parameter[10:0] SETFUNCTION = 11'b00000100000;//功能设置:数据总线选8位还是4位
parameter[10:0] SETCGRAM = 11'b00001000000;//CGRAM的地址设置
parameter[10:0] SETDDRAM = 11'b00010000000;
//DDRAM地址设置
parameter[10:0] READFLAG = 11'b00100000000;//读忙标志BF和AC
parameter[10:0] WRITERAM = 11'b01000000000;
//写数据到CGRAM或DDRAM
parameter[10:0] READRAM = 11'b10000000000;
parameter cur_inc = 1'b1;
parameter cur_dec = 1'b0;
parameter cur_shift = 1'b1;
parameter cur_noshift = 1'b0;
parameter open_display = 1'b1;
parameter open_cur = 1'b0;
parameter blank_cur = 1'b0;
parameter shift_display = 1'b1;
parameter shift_cur = 1'b0;
parameter right_shift = 1'b1;
parameter left_shift = 1'b0;
parameter datawidth8 = 1'b1;
parameter datawidth4 = 1'b0;
parameter twoline = 1'b1;
parameter oneline = 1'b0;
parameter font5x10 = 1'b1;
parameter font5x7 = 1'b0;
reg[10:0] state;
//时序信号
reg[5:0] counter;
reg[3:0] div_counter;
reg flag;
//辅助时序信号
parameter DIVSS = 4'd15;
reg[5:0] char_addr;
reg[7:0] data_in;
//延迟参量信号
reg clk_int;
reg[19:0] clkcnt;
parameter[19:0] divcnt = 20'b***00000;
reg clkdiv;
wire tc_clkcnt;
//测频部分
parameter[15:0] ad_d_chankao1 = 16'b***1;
parameter[15:0] ad_d_chankao2 = 16'b***1;
reg[15:0] ad1_d_r;
//计数部分
reg[25:0] yimiao;
//用来计数
reg rukou;
//整形方波
reg[3:0] odata7;
//记录数据
reg[3:0] odata6;
reg[3:0] odata5;
reg[3:0] odata4;
reg[3:0] odata3;
reg[3:0] odata2;
//将近-25mV //将近25mV
reg[3:0] odata1;
reg[3:0] odata0;
reg[7:0] data7;
reg[7:0] data6;
reg[7:0] data5;
reg[7:0] data4;
reg[7:0] data3;
reg[7:0] data2;
reg[7:0] data1;
reg[7:0] data0;
reg yimiao_rst;
//将记录的数据转换成ASCII码,以便显示
//数据清零信号
//主程序
aign ad1_clk = clk;
always @(posedge clk)
begin
yimiao_rst =(yimiao == 26'b***00111111111)? 1'b0 : 1'b1;//一秒时清零信号有效
end //测频部分
always @(posedge clk)
begin
ad1_d_r
if(ad1_d_r > ad_d_chankao2)
rukou
if(ad1_d_r
rukou
end //1秒钟测频
always @(posedge clk)
//每1秒钟循环一次
begin
if(yimiao == 26'b***01000000000)
yimiao
else
yimiao
end
//计数部分
always @(posedge rukou or negedge yimiao_rst)
if(~yimiao_rst)
begin
odata0
odata1
odata2
odata3
odata4
odata5
odata6
odata7
end
else if(yimiao
begin
begin
if(odata0 == 4'b1001)
begin
odata0
if(odata1 == 4'b1001)
begin
odata1
if(odata2 == 4'b1001)
begin
odata2
if(odata3 == 4'b1001)
begin
odata3
if(odata4 == 4'b1001)
begin
odata4
if(odata5 == 4'b1001)
begin
odata5
if(odata6 == 4'b1001)
begin
odata6
if(odata7 == 4'b1001)
begin
odata7
end
else
begin
odata7
end
end
else
begin
odata6
end
end
else
begin
odata5
end
end
else
begin
odata4
end
end
else
begin
odata3
end
end
else
begin
odata2
end
end
else
begin
odata1
end
end
else
begin
odata0
end
end
end
//码制转换
always @(posedge clk)
begin
if(yimiao == 26'b***00111110110)
begin
data7
//将二进制BCD码转换成ASCII码,即1602可以显示的码值
data6
data5
data4
data3
data2
data1
data0
end
end
//时钟分频
always @(posedge clk)
begin
if(clkcnt == divcnt)
begin
clkcnt
end
else
begin
clkcnt
end
end
aign tc_clkcnt =(clkcnt == divcnt)? 1'b1 : 1'b0;//tc_clkcnt 0.016s产生一次脉冲
always @(posedge tc_clkcnt)
begin
clkdiv
0.032s
end
always @(posedge clkdiv)
begin
clk_int
end
//显示界面设置
always @(negedge clkdiv)
begin
lcd_en
end
always @(char_addr)
begin
case(char_addr)
6'b000000 : //I
//clkdiv 0.016s翻转一次,周期为
//clk_int 0.032s翻转一次,周期为0.064s
begin
data_in
end
6'b000001 ://n
begin
data_in
end
6'b000010 : //p
begin
data_in
end
6'b000011 :
//u
begin
data_in
end
6'b000100 :
//t
begin
data_in
end
6'b000101 : //空格
begin
data_in
end
6'b000110 :
//F
begin
data_in
end
6'b000111 :
//r
begin
data_in
end
6'b001000 :
//e
begin
data_in
end
6'b001001 :
//q
begin
data_in
end
6'b001010 :
//u
begin
data_in
end
6'b001011 : //e
begin
data_in
end
6'b001100 : //n
begin
data_in
end
6'b001101 : //c
begin
data_in
end
6'b001110 : //y
begin
data_in
end
6'b001111 :
//空格
begin
data_in
end
6'b101000 :
//“=”
begin
data_in
end
6'b101001 :
//若为零则显示空格
begin
if(data7 == 8'b00110000)
begin
data_in
end
else
begin
data_in
end
end
6'b101010 : //若为零则显示空格
begin
data_in
if(data6 == 8'b00110000 & data7 == 8'b00110000)
begin
data_in
end
else
begin
data_in
end
end
6'b101011 :
//若为零则显示空格
begin
data_in
if(data5 == 8'b00110000 & data6 == 8'b00110000 & data7 == 8'b00110000)
begin
data_in
end
else
begin
data_in
end
end
6'b101100 : //若为零则显示空格
begin
data_in
if(data4 == 8'b00110000 & data5 == 8'b00110000 & data6 == 8'b00110000 & data7 == 8'b00110000)
begin
data_in
end
else
begin
data_in
end
end
6'b101101 :
//若为零则显示空格
begin
data_in
if(data3 == 8'b00110000 & data4 == 8'b00110000 & data5 == 8'b00110000 & data6 == 8'b00110000 & data7 == 8'b00110000)
begin
data_in
end
else
begin
data_in
end
end
6'b101110 :
//若为零则显示空格
begin
data_in
if(data2 == 8'b00110000 & data3 == 8'b00110000 & data4 == 8'b00110000 & data5 == 8'b00110000 & data6 == 8'b00110000 & data7 == 8'b00110000)
begin
data_in
end
else
begin
data_in
end
end
6'b101111 :
//若为零则显示空格
begin
data_in
if(data1 == 8'b00110000 & data2 == 8'b00110000 & data3 == 8'b00110000 & data4 == 8'b00110000 & data5 == 8'b00110000 & data6 == 8'b00110000 & data7 == 8'b00110000)
begin
data_in
end
else
begin
data_in
end
end
6'b110000 :
begin
data_in
end
6'b110110 :
//H
begin
data_in
end
6'b110111 :
//z
begin
data_in
end
default :
begin
data_in
end
endcase
end
aign lcd_rs =(state == WRITERAM | state == READRAM)? 1'b1 : 1'b0;
aign lcd_rw =(state == CLEAR | state == RETURNCURSOR | state == SETMODE | state ==
SWITCHMODE | state == SHIFT | state == SETFUNCTION | state == SETCGRAM | state == SETDDRAM | state == WRITERAM)? 1'b0 : 1'b1;
aign lcd_d =(state == CLEAR)? 8'b00000001 :(state == RETURNCURSOR)? 8'b00000010 :(state == SETMODE)? {6'b000001, cur_inc, cur_noshift} :(state == SWITCHMODE)? {5'b00001, open_display, open_cur, blank_cur} :(state == SHIFT)? {4'b0001, shift_display, left_shift, 2'b00} :(state == SETFUNCTION)? {3'b001, datawidth8, twoline, font5x10, 2'b00} :(state == SETCGRAM)? 8'b01000000 :(state == SETDDRAM & counter == 0)? 8'b10000000 :(state == SETDDRAM & counter!= 0)? 8'b11000000 :(state == WRITERAM)? data_in : 8'bZZZZZZZZ;
//时序进程
always @(posedge clk_int or posedge rst)
begin
if(rst)
begin
state
counter
div_counter
flag
char_addr
end
else
case(state)
IDLE :
begin
if(flag == 1'b0)
begin
state
flag
counter
div_counter
end
else
begin
if(div_counter
begin
div_counter
state
end
else
begin
div_counter
state
end
end
end
CLEAR :
begin
state
end
SETMODE :
begin
state
end
RETURNCURSOR :
begin
state
end
SWITCHMODE :
begin
state
end
SHIFT :
begin
state
end
SETFUNCTION :
begin
state
end
SETCGRAM :
begin
state
end
SETDDRAM :
begin
state
end
READFLAG :
begin
state
end
WRITERAM :
//可用来修改,实现1602的输出显示
begin
if((counter >= 6'd0 & counter = 6'd40 & counter
begin
state
//一行同时只能显示16个字符,第二行的首地址为40
char_addr
counter
end
else if(counter > 6'd14)
//换到第二行显示
begin
state
counter
char_addr
end
else
begin
state
state
end
end
READRAM :
begin
state
end
default :
begin
state
end
endcase
end endmodule