当前位置:   article > 正文

出现时序违例怎么解决-VIVADO_vivado时序不满足怎么办

vivado时序不满足怎么办

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


在工程应用中,经常会使用不同频率的时钟。
在不同条件下,出现时序违例。
在出现时序违例时,导致编译时间过长。

一、出现时序违例?

时序分析的测试程序:

`timescale 1ns/1ps
module test_top_1 (
 	input pri_clock,    // 50M主时钟
 	input sec_clk,
 	input	A1,
 	output	A2
 );
 

//MMCM生成20M、30M、50M、100M、200M的衍生时钟
wire clk20m,clk30m,clk50m,clk100m,clk200m;
wire locked;

  clk_wiz_0 gen_clk
   (
    // Clock out ports
    .clk20m(clk20m),     // output clk20m
    .clk30m(clk30m),     // output clk30m
    .clk50m(clk50m),     // output clk50m
    .clk100m(clk100m),     // output clk100m
    .clk200m(clk200m),     // output clk200m
    // Status and control signals
    .reset(1'b0), // input reset
    .locked(locked),       // output locked
   // Clock in ports
    .clk_in1(pri_clock));      // input clk_in1


//使用50M的时钟生成逻辑复位信号
reg rst_n;
reg [15:0] rstn_cnt=0;
always @(posedge clk50m) begin : proc_logic_rst
	if(~locked) begin
		rst_n <= 0;
		rstn_cnt<=0;
	end else if(rstn_cnt>=1000)begin
		rst_n <= 1;
		rstn_cnt<=rstn_cnt;
	end	else begin
		rst_n<=0;
		rstn_cnt<=rstn_cnt+1;
	end
end

reg [31:0] cnt_1;
reg [31:0] cnt_2;
reg [31:0] cnt_3;
reg [31:0] cnt_4;
reg [31:0] cnt_5;

//在20M的时钟域下,异步复位同步释放,计数器1增加
always @(posedge clk20m or negedge rst_n) begin : proc_cnt_1
	if(~rst_n) begin
		cnt_1 <= 0;
	end else if(A1)begin
		
		if(cnt_5>=50000)
			cnt_1<=0;
		else cnt_1 <= cnt_1+1;
	end
end


//在30M的时钟域下,异步复位同步释放,计数器2增加
always @(posedge clk30m or negedge rst_n) begin : proc_cnt_2
	if(~rst_n) begin
		cnt_2 <= 0;
	end else if(cnt_1>31'hff)begin
		cnt_2 <= cnt_2+1;
	end else 
		cnt_2<=0;	
end


//在50M的时钟域下,异步复位同步释放,计数器3增加
always @(posedge clk50m or negedge rst_n) begin : proc_cnt_3
	if(~rst_n) begin
		cnt_3 <= 0;
	end else if(cnt_5>31'hffff)begin
		cnt_3 <= cnt_3+1;
	end
end


//在100M的时钟域下,异步复位同步释放,计数器4增加
always @(posedge clk100m or negedge rst_n) begin : proc_cnt_4
	if(~rst_n) begin
		cnt_4 <= 0;
	end else if(cnt_3>32'hffffff)begin
		cnt_4 <= cnt_4+1;
	end
end



//在200M的时钟域下,异步复位同步释放,计数器5增加
always @(posedge clk200m or negedge rst_n) begin : proc_cnt_5
	if(~rst_n) begin
		cnt_5 <= 0;
	end else if(cnt_1>=8933)begin
		cnt_5 <= cnt_5+1;
	end
end

//使用clk200m分频,得出40m时钟
localparam priod_cnt_40=200/40;
reg [7:0] div_cnt;
reg clk40m;
always @(posedge clk200m or negedge rst_n) begin : proc_div_cnt
	if(~rst_n) begin
		div_cnt <= 0;
		clk40m<=0;
	end else if(div_cnt>=(priod_cnt_40>>1)-1)begin
		div_cnt<=0;
		clk40m<=~clk40m;	
	end else begin 	
		div_cnt <= div_cnt+1;
		clk40m<=clk40m;
	end 
end

reg [15:0] cnt_6;
always @(posedge clk40m or negedge rst_n) begin : proc_cnt_6
	if(~rst_n) begin
		cnt_6 <= 0;
	end else if(cnt_5==199)begin
		cnt_6 <= 0;
	end else cnt_6<=cnt_6+1;
end

//另一路输入时钟
//sec_clk
reg [15:0] cntx_1;
always @(posedge sec_clk or negedge rst_n) begin : proc_cntx_1
	if(~rst_n) begin
		 cntx_1<= 0;
	end else begin
		 cntx_1<= cntx_1+1;
	end
end

assign A2=cnt_1[31]&cnt_2[31]&cnt_3[31]&cnt_4[31]&cnt_5[31]&cnt_6[15]&cntx_1[15];
 endmodule : test_top_1 

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144

1.1编译过程中2.4节(布线初始化后)更新时序信息
图1:编译过程
1.2编译过程中2.4节中间时序总结
图2:编译过程
1.3编译过程中第5节更新时序
图3:编译过程
编译完成后时序总结
图4:总结
导致时序违例的原因
图5:警告
![图6:时序违例](https://img-blog.csdnimg.cn/d3eeab60f94549afa29da883f41bd84b.png细节

注:工程编译时间过长,也没有提示错误,可以看一下编译过程中的时序信息。如果负的太多,先分析一下,等的话不知道要等到什么时候…(千年等一回,啊 。 。 。。)

二、解决方法

1.编译过程中

如图1-图3所示,在编译过程中,出现负时序。
修改组合逻辑减小逻辑级数与扇出。
编译结果如图:
修改逻辑后

2.编译完

查看vavido工具罗列的时钟。
下图显示的时钟是由MMCM分频倍频得出(自动生成时序约束),没有给出程序中105行200M分频的40M。
时钟树
对生成的时钟重新命名,并对40M时钟进行约束。

#create_clock -name pri_clock -period 20 -waveform {0 10} [get_ports pri_clock]

create_generated_clock -name clk20m [get_pins gen_clk/inst/mmcm_adv_inst/CLKOUT0] 
create_generated_clock -name clk30m [get_pins gen_clk/inst/mmcm_adv_inst/CLKOUT1]
create_generated_clock -name clk50m [get_pins gen_clk/inst/mmcm_adv_inst/CLKOUT2]
create_generated_clock -name clk100m [get_pins gen_clk/inst/mmcm_adv_inst/CLKOUT3]
create_generated_clock -name clk200m [get_pins gen_clk/inst/mmcm_adv_inst/CLKOUT4]

create_generated_clock -name clk40m -source [get_pins gen_clk/inst/mmcm_adv_inst/CLKOUT4] -divide_by 5 [get_pins clk40m_reg/Q]
                              
create_clock -name sec_clk -period 100 -waveform {0 50} [get_ports sec_clk]
set_clock_groups -asynchronous -group [get_clocks clk200m] -group [get_clocks sec_clk]

#min = -(保持时间)
#max = 建立时间 
set_input_delay -clock clk20m -max 2.0  [get_ports A1]
set_input_delay -clock clk20m -min -1.5  [get_ports A1]
set_output_delay -clock clk200m -max -4.167   [get_ports A2]
set_output_delay -clock clk200m -min -0.0  [get_ports A2]
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

重新编译后:
时钟约束
上图包括程序中出现的所有时钟。
时序总结如下图。
修改后总结

总结

从发现问题,到解决问题;
从vivado工具的警告和报错,提示需要关注时序分析;
从小工程发展成大工程,时序分析还是挺重要的一个环节。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/羊村懒王/article/detail/95255
推荐阅读
相关标签
  

闽ICP备14008679号