电子说
分if-else,case 的各种情况分开讨论,主要目的是将分支支路中 晚到的信号放到离输出最近的一级中.
代码
为下面代码为多if语句
module mult_if (a,b,c,d,sel,z)
input a,b,c,d;
input[3:0]sel;
output Z;
reg Z;
always@(*) begin
z=1'b0;
if (sel[o])z=a;
if (sel[1])z=b;
if (sel[2])z =c;
if (sel[3])z =d;
end
endmodule
对应的硬件结构为有优先级的级联多路选择器
如果有个别信号到来的比较晚。应该要尽可能把这个延迟较大的分支单独拿出来,放到离出口最近的选择器中。假设b信号的延迟较大,可以在不影响逻辑功能的前提下,将b往后拉,如:
always@(*) begin
z=1'b0;
if (sel[o])z=a;
if (sel[2])z =c;
if (sel[3])z =d;
// if (sel[1])z=b;
if(sel[1]& ~(sel[2]|sel[3]))
z = b_is_late;
end
此时如果仅将if (sel[1])z=b;直接放下会使原来的逻辑功能改变。修改后的电路:
代码:
module single_if_late (A,C,CTRL_is_late_arriving,Z):
input [6:1]A:
input [5:1]C;
input CTRL_is_late_arriving:
output Z;
reg Z;
always@(A or C or CTRL_is_late_arriving)begin
if(C[1]==1'b1)
Z=A[1];
else if (C[2]==1'b0)
Z=A[2];
else if (C[3]==1'b1)
Z=A[3];
else if (C[4]==1'b1&CTRL_is_late_arriving==1'b0)
Z=A[4];
else if (C[5]==1'b0)
Z=A[5];
else
Z=A[6];
end
endmodule
其中 CTRL_is_late_arriving 到来延迟较大,此时就会把这个延迟较大的分支单独拿出来,放到离出口最近的选择器中:
具体的修改代码是这样的,先将原来的if打散,再在后面出口做一个选择,单独处理A[4]:
module single_if_improved (A,C,CTRL_is_late_arriving,Z);
input [6:1]A;
input [5:1]C;
input CTRL_is_late_arriving;
output Z;
reg Z,Z1;
wire Z2,prev_cond;
always@(A or C)begin
if(C[1]==1'b1)
Z1=A[1];
else if (C[2]==1'b0)
Z1=A[2];
else if (C[3]==1'b1)
Z1=A[3];
else if (C[5]==1'b0)
Z1=A[5];
// removed the branch with the late_arriving control signal
// else if (C[4]==1'b1&CTRL_is_late_arriving==1'b0)
else
Z1=A[6];
end
assign Z2=A[4];
assign prev_cond=(C[1]=1'b1)l(C[2]==1'b0)||(C[3]==1'b1);
always @ (C or prev_cond or CTRL_is_late_arriving or Z1 or Z2) begin
if((C[4]==1'b1)&&(CTRL_is_late_arriving==1'b0))
if(prev_cond) Z=Z1:
else Z=Z2;
else Z=Z1 ;
end
endmodule
module case_in_if_01(A,DATA_is_late_arriving,C,sel,Z);
input[8:1] A;
input DATA_is_late_arriving;
input [2:0] sel;
input [5:!] C;
output Z;
reg Z;
always @ (sel or C or A or DATA_is_late_arriving) begin
if (C[1])
Z=A[5];
else if (C[2]==1'b0)
Z=A[4];
else if (C[3])
Z=A[1]:
else if (C[4])
case (sel)
3'b010:Z=A[8];
3'b011:Z=DATA_is_late_arriving;
3'b101:Z=A[7]:
3'b11O:Z=A[6];
default:Z=A[2];
endcse
else if (C[5]==1'b0)
Z=A[2];
else Z=A[3];
end
endmodule
假设case中有一个支路到达比较晚,其电路结构为:
此时与单if相似,将这条通路往外提:
代码与单if-else结构的相似,去掉了case分支,单独判断这个分支:
module case_in_if_01(A,DATA_is_late_arriving,C,sel,Z);
input[8:1] A;
input DATA_is_late_arriving;
input [2:0] sel;
input [5:!] C;
output Z;
reg Z,Z1;
reg FIRST_IF;
always @ (sel or C or A or DATA_is_late_arriving) begin
if (C[1])
Z1=A[5];
else if (C[2]==1'b0)
Z1=A[4];
else if (C[3])
1Z=A[1]:
else if (C[4])
case (sel)
3'b010:Z1=A[8];
// 3'b011:Z=DATA_is_late_arriving;
3'b101:Z1=A[7]:
3'b11O:Z1=A[6];
default:Z1=A[2];
endcse
else if (C[5]==1'b0)
Z1=A[2];
else Z=A[3];
FIRST_IF=(C[1]==1'b1) || (C[2]==1'b0) ||(C[0]==1'b1);
if(!FIRST_IF && C[4] &&(sel==3'b011))
Z=DATA_is_late_arriving;
else Z=Z1;
end
endmodule
注意“先加后选”和“先选后加”两种方法对数据通道延迟的影响,对以下代码:
module BEFORE(ADRESS, PTR1,PTR2, B,CONTROL,COUNT);
input [7:O] PTR1, PTR2;
input CONTROL: //CONTROL is late arriving
output [15:0] COUNT:
parameter [7:0] BASE=8'b1000000;
wire [7:O] PRT,OFFSET;
wire [15:0] ADDR;
assign PTR = (CONTROL ==1'b1)?PTR1:PTR2;
assign OFFSET=BASE-PTR:
assign ADDR = ADRESS-{8'h00-OFFSET};
assign COUNT=ADDR+B;
endmodule
这里是先选后加, 假设控制信号到达比较晚 ,则需要改为先加后选:
代码修改如下
assign OFFSET1 = BASE-PTR1;//could be T(BASE,PTR)
assign OFFSET2 = BASE-PTR2; //could be f(BASE,PTR)
assign ADDR1 = ADRESS-{8'h00-OFFSET1);
assign ADDR2 = ADRESS-{8'h00-OFFSET2};
assign COUNT1=ADDR1+B;
assign COUNT2=ADDR2+B;
assign COUNT=(CONTROL==1'b1)?COUNT1:COUNT2;
复制数据路径将CONTROL信号放到最后
在下例中,包含一个加法器和比较器:
module cond_oper(A,B,C,D,Z):
parameter N=8;
input [N-1:O] A,B,C,D; //A is late arriving
output [N-1:0] Z;
reg [N-1:O] Z;
always@(A,B,C,D) begin
if(A+B< 24)Z<=C;
else Z<=D;
end
endmodule
假设A信号到来较晚,此时调整A的计算路径,原来的计算顺序为:
通过调整代码:
always@(A,B,C,D) begin
if(A< 24-B)Z<=C;
else Z<=D;
end
A将少过一个减法器,此时电路结构变为:
所以优化目标大头放在 组合逻辑 中,其对应着RTL代码中的各种操作符 RTL代码屮的一个“+“可能对应着一个64位的加法器。以下这些操作符都可能产生较大的组合逻辑,使用时应加以重视,如“+”、“-”、“×”、“/”以及 条件语句的比较运算 。对于这些操作,首先应该 判断其必要性 ,是否能用更简单的运算代替。
比如考虑
if(A< 32)
可以将其修改为
if(A[5]==1'b1)
通过这种方式即可节省一个6bit的比较器
此处例子中,需要考虑A的自身位宽,未必适合于所有设计,对所有定值比较都可以这样考虑
如果,必须使用复杂的运算符,则应考虑是否可以 资源共享 。尽管电路逻辑综合工具也会在综合的过程中采用资源共享的方法进行优化,但是,综合器的策略是有限的,因此在编写RTL的时候,应该尽量考虑共享,而不是把这项工作完全留给综合工具。
比如对以下代码:
If(y1 >a+b+q)
statement1;
If(y2 >a+b+r)
statement2;
If(y3 >a+b+s)
可以修改为:
sum<=a+b;
If(yl >sum+q)
statement1;
If(y2 >sum+r)
statement2;
If(y3 >sum+s)
则可以减少两个不必要的加法器
多比特的信号也往往会占用较大的资源,因为使用这些信号的操作都是对所有的比特进行的,相当于成倍使用资源,因此,对这类信号的操作也应重视。
应该看一看这个信号的所有比特是否都需要参与操作,如果不是,则可以只对需要的部分比特进行操作。
假设:
访问—RAM的地址有8比特,而写入操作时从0开始,每隔32个地址写入一个值,地址的产生可以有两种写法。
addr <= addr + 32;
和
addr[7:5] <= addr[7:5] + 1;
addr[4:0] <= addr[4:0] + 0;
针对不同的设计,还有可能有各种各样的优化和改进的方法,但是,归结到一点,就是编写代码时,应对操作符有足够的重视,对有可能简化的地方尽量简化。 逻辑简化往往在减少面积的同时也减少了延迟 ,因此,是值得花费一些时间的。
考虑电路割点的功耗:
在RTL设计中无法改变负载电容和 工作电压 ,所以在RTL级主要考虑尽量降低电路的翻转频率
主要措施包括如下:
更改状态编码后:
总的来说,使用这些技术时,应首先
布线(routing)是芯片设计中 最后的流程 ,其功能是根据门级网表的描述实现各个单元的连接
布局(placement)是芯片设计中 最关键的因素 ,但即使使用最好的布局工具,还是可能出现无法布通的情况
-> 如果可以在RTL编码阶段考虑代码可能对布线产生的影响,就可能避免最后出现无法布通的情况。
布线阶段,通常热点是一个影响布线质量的问题。
热点是指设计的功能需要在一个面积内占用大量的布线资源:
热点产生原因:RTL编码时使用了特定的结构,如很大的MUX:
全部0条评论
快来发表一下你的评论吧 !