10

FPGA中逻辑复制(转)

在FPGA设计中经常使用到逻辑复制,逻辑复制也用在很多场合。

1.    信号驱动级数非常大,扇出很大,需要增加驱动力

  逻辑复制最常使用的场合时调整信号的扇出。如果某个信号需要驱动后级很多单元,此时该信号的扇出非常大,那么为了增加这个信号的驱动能力,一种办法就是插入多级Buffer,但是这样虽然能增加驱动能力,但是也增加了这个信号的路径延时。

  为了避免这种情况这时可以复制生成这个信号的逻辑,用多路同频同相的信号驱动后续电路,使平均到每路的扇出变低,这样不需要插入Buffer就能满足驱动能力增加的要求,从而节约该信号的路径延时。如从图1.1到图1.2转变所示。    

                                                            

                                                      图   1.1  逻辑复制前

                    图1.2  逻辑复制后

  由于现在综合器都已经非常智能,此种场合的逻辑复制工作大多由综合器完成,不需要人手动调整。各大FPGA厂商的综合器以及第三方综合器都有这种功能。

2.    FPGA中需要做很多重复工作

  在某些FPGA设计中,需要很多重复设计的时候,这时候逻辑复制也就有用了。

  例如:在某个特殊应用场合需要设计方向可以任意改变的240位宽的三态IO管脚。我们先看看常用的一个位宽的三态管脚怎么设计。

复制代码

module inout_interface(
dat_in,
io_out,
io_dir,
dat_out
);
input dat_in;
input io_dir;
output dat_out;
inout io_out;

assign io_out = io_dir ? dat_in : 1'bz;
assign dat_out = io_out;

endmodule

复制代码

  如上述程序所示为单个双向IO口的典型设计代码,中间由IO输入方向控制数据和高阻之间的切换,难题出现了,怎么设计240位宽的双向IO口呢?难道如下列程序所示:

复制代码

module inout_interface(
dat_in,
io_out,
io_dir,
dat_out
);
input [239 : 0] dat_in;
input [239 : 0] io_dir;
output [239 : 0] dat_out;
inout [239 : 0] io_out;

assign io_out = io_dir ? dat_in : 240'bz;
assign dat_out = io_out;

endmodule

复制代码

  显然这样是不行的,因为当io_dir为240位的时候只有当全为0的时候此式才为假,其余时候都为真,显然达不到想要的每个IO都是双向口的设计。

修改代码如下:

复制代码

module inout_interface(

dat_in,

io_out,

io_dir,

dat_out

);

input [239 : 0] dat_in;

input [239 : 0] io_dir;

output [239 : 0] dat_out;

inout [239 : 0] io_out;



assign io_out[0] = io_dir[0] ? dat_in[0] : 1'bz;

assign dat_out[0] = io_out[0];



assign io_out[1] = io_dir[1] ? dat_in[1] : 1'bz;

assign dat_out[1] = io_out[1];



assign io_out[2] = io_dir[2] ? dat_in[2] : 1'bz;

assign dat_out[2] = io_out[2];



.

. // 此处略去1万行

.



assign io_out[239] = io_dir[239] ? dat_in[239] : 1'bz;

assign dat_out[239] = io_out[239];



endmodule

复制代码

  显然这种办法能实现240位宽的独立方向控制IO,但是估计写代码要累死人,有没得更好的办法呢?

  当然有,在verilog2001中有个逻辑复制语法——generate,可以对verilog模块进行无限复制。有了这个模块我们即可轻松通过逻辑复制来达到我们的要求了。

复制代码

// 单个双向IO实现模块

module pin_inout(

indat,

indir,

outdat,

outdatin

);



input indat;

input indir;

inout outdat;

output outdatin;



assign outdat = indir ? indat : 1'bz;

assign outdatin = outdat;



endmodule



module inout_interface(

dat_in,

io_out,

io_dir,

dat_out

);

input [239 : 0] dat_in;

input [239 : 0] io_dir;

output [239 : 0] dat_out;

inout [239 : 0] io_out;



// 逻辑复制240次

genvar i;

generate

for(i = 0; i < 240; i = i + 1)

begin : pin_loop

pin_inout pin_inout_inst(

.indat ( dat_in[i] ),

.indir ( io_dir[i] ),

.outdat ( io_out[i] ),

.outdatin ( dat_out[i] )

);

end

endgenerate



endmodule

复制代码

  由上面代码可看出,巧妙利用verilog语法能减少自身工作量。

3.    总结

  在FPGA设计中有些情况的逻辑复制不需要我们做,但是有些情况的逻辑复制不得不手工完成,因此,熟练掌握verilog语法是设计出好的模型、减少工作量的前提。

转自:http://www.cnblogs.com/linjie-swust/archive/2012/03/27/FPGA_verilog.html

posted on 2012-05-25 18:27  believe  阅读(409)  评论(1编辑  收藏  举报

导航

/* * Name: SyntaxHighlighter.brushes.Verilog * Author: Yuphone Chang * Email: yuphone@qq.com/ * Create Date: 5.18, 2010 */ SyntaxHighlighter.brushes.Verilog = function() { var datatypes = 'reg integar unsigned ' + 'wire tri wand triand tri0 tri1 supply0 supply1 trireg ' + 'parameter specparam defparam event '; var primitives = 'and nand or nor xor xnor ' + 'buf not ' + 'bufif0 bufif1 notif0 notif1 ' 'pullup pulldown ' + 'pmos rpmos nmos rnmos '; var keywords = 'module endmodule ' + 'input output inout ' + 'begin end ' + 'assign deassign always initial genvar ' + 'forever repeat disable wait ' + 'function endfunction' + 'task ' + 'endtask ' + 'generate endgenerate ' + 'specify endspecify ' + 'posedge negedge ' + 'if else for while ' + 'case casex casez endcase default ' + 'include timescale ' + 'ifdef endif ' + 'celldefine endcelldefine ' + 'attribute ' 'fork join '; var functions = 'display displayb displayo displayh ' + 'write writeb writeo writeh ' + 'strobe strobeb strobeh strobeo ' + 'monitor monitorb monitoro monitorh ' + 'fopen fclose ' + 'readmemb readmemh ' + 'finish stop ' + 'time stime realtime timeformat ' + 'printtimescale ' + 'setup hold setuphold skew recovery period width '; this.regexList = [ // one line comments { regex: SyntaxHighlighter.regexLib.singleLineCComments,css: 'comments' }, // multiline comments { regex: SyntaxHighlighter.regexLib.multiLineCComments, css: 'comments' }, // double quoted strings { regex: SyntaxHighlighter.regexLib.doubleQuotedString, css: 'string' }, // single quoted strings { regex: SyntaxHighlighter.regexLib.singleQuotedString, css: 'string' }, // constants { regex: new RegExp("[0-9]+['][bBoOdDhHeEfFtT][0-9a-fA-FzZxX_]+", 'g'), css: 'constants' }, // datatypes { regex: new RegExp(this.getKeywords(datatypes), 'gm'), css: 'color1 bold' }, // primitives { regex: new RegExp(this.getKeywords(primitives), 'gm'), css: 'color2 bold' }, // keywords { regex: new RegExp(this.getKeywords(keywords), 'gm'), css: 'keyword bold' }, // functions { regex: new RegExp(this.getKeywords(functions), 'gm'), css: 'functions bold' } ]; }; SyntaxHighlighter.brushes.Verilog.prototype = new SyntaxHighlighter.Highlighter(); SyntaxHighlighter.brushes.Verilog.aliases = ['verilog', 'v'];