问题来源
当时我在设计FPGA简易频率计的时候,当编写完等精度测量的频率计算模块的时候,编译综合并没有出现错误,然后将我之前编写的Seg数码管驱动模块导入到项目里面,单独编译综合也是没有问题。但是,当我设计顶层模块并实例化频率计算模块和Seg驱动模块的时候,报错显示逻辑资源不够用!
那么就奇了怪了,在野火视频教程里面freq_meter_calc模块的资源使用情况并没有这么多,视频显示为2606,而我的使用情况是4436,这个模块的使用量就占据我开发板总资源量的**69%**!!
并没有解决。不是知道是什么原因,不管怎么样,我要让代码能成功运行的话只能降低寄存器的位宽了,这样会导致测量的频率范围降低。
资源使用情况
代码
顶层模块
module freq_meter
(
input wire sys_clk , //系统时钟,频率50MHz
input wire sys_rst_n , //复位信号,低电平有效
input wire clk_test,
output wire [7:0]segdata,
output wire [2:0]segcs
);
//wire define
wire [33:0] freq ; //计算得到的待检测信号时钟频率
//------------- freq_meter_calc_inst --------------
freq_meter_calc freq_meter_calc_inst
(
.sys_clk (sys_clk ), //系统时钟,频率50MHz
.sys_rst_n (sys_rst_n ), //复位信号,低电平有效
.clk_test (clk_test ), //待检测时钟
.freq (freq ) //待检测时钟频率
);
//------------- seg_595_dynamic_inst --------------
seg seg_inst (
.clk(sys_clk),
.rst_n(sys_rst_n),
.tenvalue(freq), // 这里连接没有问题
.segdata(segdata),
.segcs(segcs)
);
endmodule
数码管驱动模块
/*
数码管显示驱动,目前是直接设置固定数据
通过将tenvalue设置到输入端口,可以作为子模块,通过传入数据显示在数码管上面
*/
module seg(
input clk,
input rst_n,
input [33:0]tenvalue,
output reg [7:0]segdata,
output reg [2:0]segcs
);
reg[31:0] count;
reg[24:0]count1ms;
reg[2:0]number;
reg clk1ms;
parameter sample=2'b00,
display=2'b01;
//-----------数码管驱动时钟-----------
always@(posedge clk or negedge rst_n)
begin
if (!rst_n)begin
count1ms <= 1'd0;
clk1ms <= 1'd0;
end else if(count1ms >= 25'd50000) // 1ms的计数器
begin
clk1ms <= ~clk1ms;
count1ms <= 1'd0;
end
else
count1ms <= count1ms + 1'd1;
end
//-----------数码管译码-----------
function [7:0] leddata;
input [3:0] datain;
begin
case(datain)
4'd0: leddata = 8'b11000000; // 0
4'd1: leddata = 8'b11111001; // 1
4'd2: leddata = 8'b10100100; // 2
4'd3: leddata = 8'b10110000; // 3
4'd4: leddata = 8'b10011001; // 4
4'd5: leddata = 8'b10010010; // 5
4'd6: leddata = 8'b10000010; // 6
4'd7: leddata = 8'b11111000; // 7
4'd8: leddata = 8'b10000000; // 8
4'd9: leddata = 8'b10010000; // 9
4'd11: leddata = 8'b01111111; // .
default: leddata = 8'b11111111;
endcase
end
endfunction
//-----------数码管扫描-----------
always@(posedge clk1ms or negedge rst_n)
begin
if(!rst_n)
number <= 3'd0;
else if(number == 3'd3)
number <= 3'd0;
else
number <= number + 1;
case(number)
3'd0:
begin
segdata <= leddata(tenvalue % 10); // 个位
segcs <= 3'b101;
end
3'd1:
begin
segdata <= leddata((tenvalue / 10) % 10); // 十位
segcs <= 3'b100;
end
3'd2:
begin
segdata <= leddata((tenvalue / 100) % 10); // 百位
segcs <= 3'b011;
end
3'd3:
begin
segdata<=leddata((tenvalue/1000)%10);//千位
segcs<=3'b010;
end
default:
begin
segdata <= 8'b11111111; // 或者其他默认值
segcs <= 3'b111; // 或者其他默认值
end
endcase
end
endmodule
等精度测量法频率测量模块
`timescale 1ns/1ns
////////////////////////////////////////////////////////////////////////
// Author : EmbedFire
// Create Date : 2019/07/10
// Module Name : freq_meter_calc
// Project Name : freq_meter
// Target Devices: Altera EP4CE10F17C8N
// Tool Versions : Quartus 13.0
// Description : 频率计算模块
//
// Revision : V1.0
// Additional Comments:
//
// 实验平台: 野火_征途Pro_FPGA开发板
// 公司 : http://www.embedfire.com
// 论坛 : http://www.firebbs.cn
// 淘宝 : https://fire-stm32.taobao.com
////////////////////////////////////////////////////////////////////////
module freq_meter_calc
(
input wire sys_clk , //系统时钟,频率50MHz
input wire sys_rst_n , //复位信号,低电平有效
input wire clk_test , //待检测时钟
output reg [33:0] freq //待检测时钟频率
);
//********************************************************************//
//****************** Parameter And Internal Signal *******************//
//********************************************************************//
//parameter define
parameter CNT_GATE_S_MAX = 28'd74_999_999 , //软件闸门计数器计数最大值
CNT_RISE_MAX = 28'd12_500_000 ; //软件闸门拉高计数值
parameter CLK_STAND_FREQ = 28'd100_000_000 ; //标准时钟时钟频率
//wire define
wire clk_stand ; //标准时钟,频率100MHz
wire gate_a_fall_s ; //实际闸门下降沿(标准时钟下)
wire gate_a_fall_t ; //实际闸门下降沿(待检测时钟下)
//reg define
reg [27:0] cnt_gate_s ; //软件闸门计数器
reg gate_s ; //软件闸门
reg gate_a ; //实际闸门
reg gate_a_stand ; //实际闸门打一拍(标准时钟下)
reg gate_a_test ; //实际闸门打一拍(待检测时钟下)
reg [47:0] cnt_clk_stand ; //标准时钟周期计数器
reg [47:0] cnt_clk_stand_reg ; //实际闸门下标志时钟周期数
reg [47:0] cnt_clk_test ; //待检测时钟周期计数器
reg [47:0] cnt_clk_test_reg ; //实际闸门下待检测时钟周期数
reg calc_flag ; //待检测时钟时钟频率计算标志信号
reg [63:0] freq_reg ; //待检测时钟频率寄存
reg calc_flag_reg ; //待检测时钟频率输出标志信号
//********************************************************************//
//***************************** Main Code ****************************//
//********************************************************************//
//cnt_gate_s:软件闸门计数器
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
cnt_gate_s <= 28'd0;
else if(cnt_gate_s == CNT_GATE_S_MAX)
cnt_gate_s <= 28'd0;
else
cnt_gate_s <= cnt_gate_s + 1'b1;
//gate_s:软件闸门
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
gate_s <= 1'b0;
else if((cnt_gate_s>= CNT_RISE_MAX)
&& (cnt_gate_s <= (CNT_GATE_S_MAX - CNT_RISE_MAX)))
gate_s <= 1'b1;
else
gate_s <= 1'b0;
//gate_a:实际闸门
always@(posedge clk_test or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
gate_a <= 1'b0;
else
gate_a <= gate_s;
//cnt_clk_stand:标准时钟周期计数器,计数实际闸门下标准时钟周期数
always@(posedge clk_stand or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
cnt_clk_stand <= 48'd0;
else if(gate_a == 1'b0)
cnt_clk_stand <= 48'd0;
else if(gate_a == 1'b1)
cnt_clk_stand <= cnt_clk_stand + 1'b1;
//cnt_clk_test:待检测时钟周期计数器,计数实际闸门下待检测时钟周期数
always@(posedge clk_test or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
cnt_clk_test <= 48'd0;
else if(gate_a == 1'b0)
cnt_clk_test <= 48'd0;
else if(gate_a == 1'b1)
cnt_clk_test <= cnt_clk_test + 1'b1;
//gate_a_stand:实际闸门打一拍(标准时钟下)
always@(posedge clk_stand or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
gate_a_stand <= 1'b0;
else
gate_a_stand <= gate_a;
//gate_a_fall_s:实际闸门下降沿(标准时钟下)
assign gate_a_fall_s = ((gate_a_stand == 1'b1) && (gate_a == 1'b0))
? 1'b1 : 1'b0;
//cnt_clk_stand_reg:实际闸门下标志时钟周期数
always@(posedge clk_stand or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
cnt_clk_stand_reg <= 32'd0;
else if(gate_a_fall_s == 1'b1)
cnt_clk_stand_reg <= cnt_clk_stand;
//gate_a_test:实际闸门打一拍(待检测时钟下)
always@(posedge clk_test or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
gate_a_test <= 1'b0;
else
gate_a_test <= gate_a;
//gate_a_fall_t:实际闸门下降沿(待检测时钟下)
assign gate_a_fall_t = ((gate_a_test == 1'b1) && (gate_a == 1'b0))
? 1'b1 : 1'b0;
//cnt_clk_test_reg:实际闸门下待检测时钟周期数
always@(posedge clk_test or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
cnt_clk_test_reg <= 32'd0;
else if(gate_a_fall_t == 1'b1)
cnt_clk_test_reg <= cnt_clk_test;
//calc_flag:待检测时钟时钟频率计算标志信号
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
calc_flag <= 1'b0;
else if(cnt_gate_s == (CNT_GATE_S_MAX - 1'b1))
calc_flag <= 1'b1;
else
calc_flag <= 1'b0;
//freq_reg:待检测时钟信号时钟频率寄存
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
freq_reg <= 64'd0;
else if(calc_flag == 1'b1)
freq_reg <= (CLK_STAND_FREQ * cnt_clk_test_reg / cnt_clk_stand_reg);
//calc_flag_reg:待检测时钟频率输出标志信号
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
calc_flag_reg <= 1'b0;
else
calc_flag_reg <= calc_flag;
//freq:待检测时钟信号时钟频率
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
freq <= 34'd0;
else if(calc_flag_reg == 1'b1)
freq <= freq_reg[33:0];
//********************************************************************//
//*************************** Instantiation **************************//
//********************************************************************//
//---------- clk_gen_inst ----------
clk_gen clk_gen_inst
(
.areset (~sys_rst_n ),
.inclk0 (sys_clk ),
.c0 (clk_stand )
);
endmodule