位置:51电子网 » 技术资料 » EDA/PLD

基于Verilog语言的可维护性设计技术

发布时间:2008/8/12 0:00:00 访问次数:688

  随着集成电路制造技术的发展,对设计提出了更多的挑战,随着设计复杂度的增加,又提出了片上系统(soc)的概念。为了加速设计收敛,设计重用、可测性设计、可验证性设计和可维护性设计得到了更多重视。本文以veriloghdl为例,对可维护性设计进行了初步探讨。

1、设计重用与可维护性设计

  设计重用是一个很大的概念,严格来讲,可验证性设计和可维护性设计都在设计重用之列。可维护性设计的目的本身就是便于设计重用,便于让后来人读懂前人所写的代码,但设计重用包括的内容更广泛。

  设计重用讲的是设计总体风格而不是设计的细节,“it is about forests, rather than trees”。最重要的概念:本地化(locality)――一定要尽量使问题本地化,这样有利于问题的排除。对于大的设计尤为重要。

三条基本原则

  尽量采用全同步设计,将输入和输出寄存,这样有利于将时序优化本地化

  采用bottom-up验证方法,保证每个子模块的功能是正确的,然后再进行整体验证。

  花时间设计一个好的设计规范,力图使这样的规范具有好的体系结构和模块划分,这样有利于本地化的有效实现。

  一个好的设计应该包括:完备的文档、好风格的代码、详尽的注释、良好易用的验证环境和鲁棒的脚本。

  影响设计重用的障碍本质上说是管理和企业文化;开发和管理内部ip资源是最大的重用挑战。

  关于设计重用这里不再讨论,否则就有喧宾夺主之嫌了。

2、关于代码可扩展性的一点讨论

  代码可扩展性实际上也包括在设计重用之内。代码可扩展性或称可扩展性设计要求便于向将来新的设计过渡。比如64位的pci标准出来的时候,现行的32位pci接口设计模块可以通过比较简单的改动而变为64位,而不需要一切从头再来。一般设计中通过定义参数和宏来便于修改。典型例子就是总线:

`define word 16
`define dword 32
reg [`word-1:0] intruction
reg [`dword-1:0] data_bus,addr_bus;
当然代码可扩展性不仅仅包括参数和宏的使用,如下例:
module tri_buf(in,out, ena);
parameter width=8;
input [width-1:0] in;
output[width-1:0] out;
input ena;
assign out= ena?in:’bz;
endmodule

  这是一段有潜在问题的代码,verilog将高位扩展为0来匹配输出,所以当width>32时,上述代码是有问题的,仿真的时候甚至都看不出来,因此不利于可扩展性。象这样的问题可以用verilog lint等工具来检查。

3、可读性最重要

  可读性最重要。许多设计者有个习惯:追求尽量用短的代码来完成同样的功能,国内许多考试中也要求用少于多少行的代码完成某某功能(很不好的倾向)。对于hdl,我不推荐这样的风格,因为综合工具会帮助你完成优化工作。我的建议是:同样的代码可长可短,不要为了减少行数而影响可读性。如下例:

module rrarb(request,grant,reset,clk);
input [1:0] request;
output[1:0]grant;
input reset;
input clk;
wire winner;
reg last_winner;
reg [1:0] grant;
wire[1:0] next_grant;

assign next_grant[0]=~reset&(request[0] & (~request[1]|last_winner));
assugn next_grant[1]=~reset& (request[1] &(~request[0]| ~last_winner));
assign winner=~reset & ~next_grant[0] &(last_winner | next_grant[1]);
always @(posedge clk)
begin
last_winner=winner;
grant=next_grant;
end
当request[1:0]=2’b00,时,last_winner会发生什么变化?上面的代码可读性较之下面的代码差很多。
module rrarb(request,grant,reset,clk);
input [1:0] request;
output[1:0]grant;
input reset;
input clk;
wire winner;
reg last_winner;
reg [1:0] grant;
always @(posedge clk)
begin
if(reset) begin
grant<=2’b00;
last_winner<=0;
end
else begin
grant<=2’b00;
if(request!=2’b00) begin:find_winner
reg winner;
case(request)
2’b01:winner<=0;
2’b10:winner<=1;
2’b11:if (last_winner==1’b0) winner<=1;
else winner<=0;
default:winner<=0;
endcase
grant[winner] <=1’b1;
last_winner<=winner;
end
end
end
endmodule

  上述两个代码的综合结果差不多。而且上面第一段代码在always块内采用阻塞赋值的方法也存在潜在问题。

4、要有好的注释风格

  要有好的注释风格。减少注释的行数跟节约代码的行数一样,我不推荐。像代码有好坏一样,注释也有好坏之分。比如:

//increment addr
addr<=addr+1;

  上例中的注释就是一句废话,因为地址加1是不言自明的

  随着集成电路制造技术的发展,对设计提出了更多的挑战,随着设计复杂度的增加,又提出了片上系统(soc)的概念。为了加速设计收敛,设计重用、可测性设计、可验证性设计和可维护性设计得到了更多重视。本文以veriloghdl为例,对可维护性设计进行了初步探讨。

1、设计重用与可维护性设计

  设计重用是一个很大的概念,严格来讲,可验证性设计和可维护性设计都在设计重用之列。可维护性设计的目的本身就是便于设计重用,便于让后来人读懂前人所写的代码,但设计重用包括的内容更广泛。

  设计重用讲的是设计总体风格而不是设计的细节,“it is about forests, rather than trees”。最重要的概念:本地化(locality)――一定要尽量使问题本地化,这样有利于问题的排除。对于大的设计尤为重要。

三条基本原则

  尽量采用全同步设计,将输入和输出寄存,这样有利于将时序优化本地化

  采用bottom-up验证方法,保证每个子模块的功能是正确的,然后再进行整体验证。

  花时间设计一个好的设计规范,力图使这样的规范具有好的体系结构和模块划分,这样有利于本地化的有效实现。

  一个好的设计应该包括:完备的文档、好风格的代码、详尽的注释、良好易用的验证环境和鲁棒的脚本。

  影响设计重用的障碍本质上说是管理和企业文化;开发和管理内部ip资源是最大的重用挑战。

  关于设计重用这里不再讨论,否则就有喧宾夺主之嫌了。

2、关于代码可扩展性的一点讨论

  代码可扩展性实际上也包括在设计重用之内。代码可扩展性或称可扩展性设计要求便于向将来新的设计过渡。比如64位的pci标准出来的时候,现行的32位pci接口设计模块可以通过比较简单的改动而变为64位,而不需要一切从头再来。一般设计中通过定义参数和宏来便于修改。典型例子就是总线:

`define word 16
`define dword 32
reg [`word-1:0] intruction
reg [`dword-1:0] data_bus,addr_bus;
当然代码可扩展性不仅仅包括参数和宏的使用,如下例:
module tri_buf(in,out, ena);
parameter width=8;
input [width-1:0] in;
output[width-1:0] out;
input ena;
assign out= ena?in:’bz;
endmodule

  这是一段有潜在问题的代码,verilog将高位扩展为0来匹配输出,所以当width>32时,上述代码是有问题的,仿真的时候甚至都看不出来,因此不利于可扩展性。象这样的问题可以用verilog lint等工具来检查。

3、可读性最重要

  可读性最重要。许多设计者有个习惯:追求尽量用短的代码来完成同样的功能,国内许多考试中也要求用少于多少行的代码完成某某功能(很不好的倾向)。对于hdl,我不推荐这样的风格,因为综合工具会帮助你完成优化工作。我的建议是:同样的代码可长可短,不要为了减少行数而影响可读性。如下例:

module rrarb(request,grant,reset,clk);
input [1:0] request;
output[1:0]grant;
input reset;
input clk;
wire winner;
reg last_winner;
reg [1:0] grant;
wire[1:0] next_grant;

assign next_grant[0]=~reset&(request[0] & (~request[1]|last_winner));
assugn next_grant[1]=~reset& (request[1] &(~request[0]| ~last_winner));
assign winner=~reset & ~next_grant[0] &(last_winner | next_grant[1]);
always @(posedge clk)
begin
last_winner=winner;
grant=next_grant;
end
当request[1:0]=2’b00,时,last_winner会发生什么变化?上面的代码可读性较之下面的代码差很多。
module rrarb(request,grant,reset,clk);
input [1:0] request;
output[1:0]grant;
input reset;
input clk;
wire winner;
reg last_winner;
reg [1:0] grant;
always @(posedge clk)
begin
if(reset) begin
grant<=2’b00;
last_winner<=0;
end
else begin
grant<=2’b00;
if(request!=2’b00) begin:find_winner
reg winner;
case(request)
2’b01:winner<=0;
2’b10:winner<=1;
2’b11:if (last_winner==1’b0) winner<=1;
else winner<=0;
default:winner<=0;
endcase
grant[winner] <=1’b1;
last_winner<=winner;
end
end
end
endmodule

  上述两个代码的综合结果差不多。而且上面第一段代码在always块内采用阻塞赋值的方法也存在潜在问题。

4、要有好的注释风格

  要有好的注释风格。减少注释的行数跟节约代码的行数一样,我不推荐。像代码有好坏一样,注释也有好坏之分。比如:

//increment addr
addr<=addr+1;

  上例中的注释就是一句废话,因为地址加1是不言自明的

相关IC型号

热门点击

 

推荐技术资料

声道前级设计特点
    与通常的Hi-Fi前级不同,EP9307-CRZ这台分... [详细]
版权所有:51dzw.COM
深圳服务热线:13751165337  13692101218
粤ICP备09112631号-6(miitbeian.gov.cn)
公网安备44030402000607
深圳市碧威特网络技术有限公司
付款方式


 复制成功!