FPGA Verilog写的一个数字频率计有一点问题
时间:10-02
整理:3721RD
点击:
大二在读学生,在准备电赛,最近在做15年的数字频率计题目,遇到了一点问题
用的是黑金的Cyclone IV开发板
一共有两个功能,频率测量和占空比测量,频率测量的部分很奇怪,计数部分记到的数字正好是频率的两倍(应该正好等于频率的)。 占空比测量部分返回值直接就是乱的。
`timescale 1ns / 1ps
module measure_f (
clk, // 开发板上输入时钟: 50Mhz
rst_n, // 开发板上输入复位按键
SI_OUT, // 数据输出
SI_IN, // 信号输入
GO, // 单片机通信信号
counter, // 闸门信号
clk_200 //倍频后200M时钟
//clk_400 //倍频后400M时钟
);
//=====================================================
// 引脚声明
//=====================================================
input clk;
input rst_n;
input SI_IN;
input GO;
output clk_200;
//output clk_400;
output counter;
output [63:0] SI_OUT;
//寄存器定义
reg [31:0] timer = 0;//计时寄存器
reg [31:0] timer_T = 0;//占空比计时寄存器
reg [31:0] T = 0;//记录占空比
reg [63:0] SI_OUT = 0;//信号输出寄存器
reg [31:0] measure_1 = 0;//计数寄存器
reg [31:0] measure_2 = 0;//中转用寄存器
reg[2:0] delay1;//抓边沿用
reg[2:0] delay2;//抓边沿用
reg counter = 0;//闸门
//===================================================
// 抓取边沿
//===================================================
always @ ( posedge clk_200 or negedge rst_n )
if( !rst_n )
delay1 <= 0;
else
delay1 <= { delay1[1:0], SI_IN};
// SI_IN是原信号
wire pos_SI = delay1[1] && ( ~delay1[2] ); // 原信号上升沿位置处产生的pulse信号
wire neg_SI = ( ~delay1[1] ) && delay1[2]; // 原信号下降沿位置处产生的pulse信号
always @ ( posedge clk_200 or negedge rst_n )
if( !rst_n )
delay2 <= 0;
else
delay2 <= { delay2[1:0], GO} ;
// GO是原信号
wire pos_GO = delay2[1] && ( ~delay2[2] ); // 原信号上升沿位置处产生的pulse信号
wire neg_GO = ( ~delay2[1] ) && delay2[2]; // 原信号下降沿位置处产生的pulse信号
//===================================================
// 闸门时间:1S
//===================================================
always @(posedge clk_200 or negedge rst_n)
begin
if (~rst_n) //复位信号低有效
begin
timer <= 0; //计数器清零
counter <= 0;
end
else if (timer == 32'd199_999_999) //200MHz,1 秒计数(200M-1=399_999_999)
begin
measure_2 <= measure_1;//将计数值装入中转用寄存器
T <= timer_T;//将占空比数据装入占空比中转用寄存器
timer <= 0; //计数器计到 1 秒,计数器清零
counter <= ~counter; //闸门取反
end
else
timer <= timer + 1'b1; //计数器加 1
end
//=====================================================
// 计数器_1 记录脉冲
//=====================================================
always @(posedge clk_200 or negedge rst_n)
begin
if (~rst_n) //复位信号低有效
measure_1 <= 0;
else if (counter == 1 && pos_SI)
measure_1 <= measure_1 + 1'b1;//闸门为开启时计数
else if(counter == 0)
measure_1 <=0;
end
//=====================================================
// 计数器_2 通信调整
//=====================================================
always @(posedge clk_200 or negedge rst_n)
begin
if (~rst_n) //赋初值
SI_OUT <= 0;
else if(counter == 0)
begin
SI_OUT[31:0] <= measure_2;
SI_OUT[63:32] <= T;
end
else if (counter == 1 && pos_GO)//匝门开启时发送数据
begin
SI_OUT <= SI_OUT << 1;
end
end
//=====================================================
// 占空比测量
//=====================================================
always @(posedge clk_200 or negedge rst_n)
begin
if (~rst_n) //赋初值
timer_T <= 0;
else if(SI_IN && counter == 1)
timer_T <= timer_T + 1'b1;
else if (counter == 0)
timer_T <= 0;
end
//=====================================================
// 例化PLL
//=====================================================
pll pll_inst
(// Clock in ports
.inclk0(clk), // IN 50Mhz
// Clock out ports
.c0(clk_200), // OUT200Mhz
//.c1(clk_400),
// Status and control signals
.areset(~rst_n),// IN
.locked(locked)
);
endmodule
用的是黑金的Cyclone IV开发板
一共有两个功能,频率测量和占空比测量,频率测量的部分很奇怪,计数部分记到的数字正好是频率的两倍(应该正好等于频率的)。 占空比测量部分返回值直接就是乱的。
`timescale 1ns / 1ps
module measure_f (
clk, // 开发板上输入时钟: 50Mhz
rst_n, // 开发板上输入复位按键
SI_OUT, // 数据输出
SI_IN, // 信号输入
GO, // 单片机通信信号
counter, // 闸门信号
clk_200 //倍频后200M时钟
//clk_400 //倍频后400M时钟
);
//=====================================================
// 引脚声明
//=====================================================
input clk;
input rst_n;
input SI_IN;
input GO;
output clk_200;
//output clk_400;
output counter;
output [63:0] SI_OUT;
//寄存器定义
reg [31:0] timer = 0;//计时寄存器
reg [31:0] timer_T = 0;//占空比计时寄存器
reg [31:0] T = 0;//记录占空比
reg [63:0] SI_OUT = 0;//信号输出寄存器
reg [31:0] measure_1 = 0;//计数寄存器
reg [31:0] measure_2 = 0;//中转用寄存器
reg[2:0] delay1;//抓边沿用
reg[2:0] delay2;//抓边沿用
reg counter = 0;//闸门
//===================================================
// 抓取边沿
//===================================================
always @ ( posedge clk_200 or negedge rst_n )
if( !rst_n )
delay1 <= 0;
else
delay1 <= { delay1[1:0], SI_IN};
// SI_IN是原信号
wire pos_SI = delay1[1] && ( ~delay1[2] ); // 原信号上升沿位置处产生的pulse信号
wire neg_SI = ( ~delay1[1] ) && delay1[2]; // 原信号下降沿位置处产生的pulse信号
always @ ( posedge clk_200 or negedge rst_n )
if( !rst_n )
delay2 <= 0;
else
delay2 <= { delay2[1:0], GO} ;
// GO是原信号
wire pos_GO = delay2[1] && ( ~delay2[2] ); // 原信号上升沿位置处产生的pulse信号
wire neg_GO = ( ~delay2[1] ) && delay2[2]; // 原信号下降沿位置处产生的pulse信号
//===================================================
// 闸门时间:1S
//===================================================
always @(posedge clk_200 or negedge rst_n)
begin
if (~rst_n) //复位信号低有效
begin
timer <= 0; //计数器清零
counter <= 0;
end
else if (timer == 32'd199_999_999) //200MHz,1 秒计数(200M-1=399_999_999)
begin
measure_2 <= measure_1;//将计数值装入中转用寄存器
T <= timer_T;//将占空比数据装入占空比中转用寄存器
timer <= 0; //计数器计到 1 秒,计数器清零
counter <= ~counter; //闸门取反
end
else
timer <= timer + 1'b1; //计数器加 1
end
//=====================================================
// 计数器_1 记录脉冲
//=====================================================
always @(posedge clk_200 or negedge rst_n)
begin
if (~rst_n) //复位信号低有效
measure_1 <= 0;
else if (counter == 1 && pos_SI)
measure_1 <= measure_1 + 1'b1;//闸门为开启时计数
else if(counter == 0)
measure_1 <=0;
end
//=====================================================
// 计数器_2 通信调整
//=====================================================
always @(posedge clk_200 or negedge rst_n)
begin
if (~rst_n) //赋初值
SI_OUT <= 0;
else if(counter == 0)
begin
SI_OUT[31:0] <= measure_2;
SI_OUT[63:32] <= T;
end
else if (counter == 1 && pos_GO)//匝门开启时发送数据
begin
SI_OUT <= SI_OUT << 1;
end
end
//=====================================================
// 占空比测量
//=====================================================
always @(posedge clk_200 or negedge rst_n)
begin
if (~rst_n) //赋初值
timer_T <= 0;
else if(SI_IN && counter == 1)
timer_T <= timer_T + 1'b1;
else if (counter == 0)
timer_T <= 0;
end
//=====================================================
// 例化PLL
//=====================================================
pll pll_inst
(// Clock in ports
.inclk0(clk), // IN 50Mhz
// Clock out ports
.c0(clk_200), // OUT200Mhz
//.c1(clk_400),
// Status and control signals
.areset(~rst_n),// IN
.locked(locked)
);
endmodule
学习FPGA方面的东西才一周,可能有一些对于它的理解有些问题的地方,希望各位大手发现问题能够麻烦指出一下,非常感谢
always @(posedge clk_200 or negedge rst_n)
begin
if (~rst_n) //赋初值
timer_T <= 0;
else if(SI_IN && counter == 1)
timer_T <= timer_T + 1'b1;
else if (counter == 0)
timer_T <= 0;
end、
像是有问题;从你的代码上看,在某1秒内,counter为高电平,输入信号高电平时,timer_T 计数,那如果输入信号低电平counter为高电平呢?if else 没有写全