建议使用浅色背景阅读
准备工作
使用环境
服务器:
DELL PowerEdge R740
2 CPUs @ 3.10GHz, 40 cores with 512GB of memory
操作系统:
Red Hat Enterprise Linux 7.9
使用工具
Candence Virtuoso IC618
Synopsys Design Compiler
Candence Innovus 15.2
设计流程
设计指标及完成情况
设计任务
设计一电路模块,实现函数
其中,
信号 | 类型 |
---|---|
clk | 250MHz时钟信号 |
a | 11位无符号整数 |
b | 11位无符号整数 |
c | 11位无符号整数 |
d | 10位无符号整数 |
e | 1位(异步输入) |
y | 12位有符号数(二进制补码) |
要求
输入端口有且仅有 a[10:0],b[10:0],c[10:0],e,clk,输出端口为 y[11:0];
y 的误差范围为±1/211
时钟 clk 频率为 250MHz,且 clock jitter 为 200ps, a,b,c 的数据变化速率与 clk 同步,d[9:0]作为可编程系数通过异步输入端口 e 写入(只写一次);
e 同步于另一时钟 clkb,与 clk 异步,Tclkb=3ns;
在满足条件的情况下,优化 latency;
在满足条件的情况下,优化功耗。
指标完成情况概述
Verilog 仿真、前仿真、门极仿真、后仿真中,在测试条件下 y 值均正确输出,因此达到设计指标。
测试时,在 392ns 输入信号,在 426ns 时输出结果,由于工作周期内时钟第一个上升沿在 394ns,因此认为模块的处理时间为 32.0264ns,即 4 个时钟周期。
功耗为 63.0833 mW。
经过测试,LVS 和 DRC 均通过。
由于在除法器设计中使用了查找表格式,面积与功耗均较表现良好,且满足要求时序。
核心模块Verilog设计
指标分析及方案预设
将
代码编写
(a+b) 计算
通过要输入 a[10:0]、b[10:0]来计算出 (a+b) 的值。经过验算,为防止溢出,将输出设置为 12 位。
xxxxxxxxxx
always @(posedge clk) begin
if (rst) begin
reg_a_plus_b_stage_0 < 0;
end else begin
reg_a_plus_b_stage_0 < reg_a reg_b;
end
end
1/(a+b) 计算
将上文计算出的 (a+b) 通过查除法表的形式得到1/(a+b),经过验算,为防止溢出与保证精度,将输出设置为 21 位。
xxxxxxxxxx
div div_inst(
.aplusb (reg_a_plus_b_stage_0),
.div_result (wire_div_result)
);
always @(posedge clk) begin
if (rst) begin
reg_div_result < 0;
end else begin
reg_div_result < wire_div_result;
end
end
计算
可以看作是将0~
xxxxxxxxxx
cos cos_inst(
.c (reg_c),
.cos_result (wire_cos_result)
);
always @(posedge clk) begin
if (rst) begin
reg_cos_result < 0;
end else begin
reg_cos_result < wire_cos_result;
end
end
d异步输入
指标要求 d[9:0] 必须由 e[0:0] 以串行异步输入的形式载入数据,并且 e 参考 Tclk2 为 3ns, d 参考 Tclk 为 4ns,同步器依赖 e 的上升沿进行触发(因此第一位数需要为 1),以 clk 上升沿 为触发将 e 从后往前存入 delay [2:0] 中,再以 delay 的最高位上升沿为触发,将此时的 e 按位 累加到 d[9:0] 中,实现两个时钟系统的衔接。
testbench端,信号异步输入:
xxxxxxxxxx
`define data_0 10'b1110000000
`define data_1 10'b1111110000
initial begin
#16;
repeat(10)begin
d_bit < (d[9]) `data_1 : `data_0;
d < d << 1;
repeat(10)@(posedge clk2)begin
e < d_bit[9];
d_bit < d_bit << 1;
end
end
#200;
end
function端,信号接收与处理:
xxxxxxxxxx
module asyn (
input wire clk,
input wire [0:0] e,
output reg [9:0] d
);
reg [2:0] delay;
always @(posedge clk)
delay < {delay[1:0],e};
always @(posedge delay[2])
d < {d[8:0],e};
endmodule
乘法计算
乘法的原理为移位相加,这里为了保证乘法运算中的延迟能符合 250MHz 要求,将每个乘数均拆分为 3 小段,单独相乘、积相加,以此来降低高位数乘法的运算时延。下列示例代码就将乘数 reg_div_result[20:0] 均分为 3 段,将乘数 reg_a_stage_1[10:0]拆分为两 段。彼此两两相乘后对齐相加,得到积 tol_div_a[31:0]。
xxxxxxxxxx
reg sign_stage_2;
reg [12:0] temp_ah0, temp_ah1, temp_ah2; //将积的高 39 位拆分成 ah0,ah1,ah2 三段进行计算
reg [11:0] temp_al0, temp_al1, temp_al2; //将积的低 36 位拆分成 al0,al1,al2 三段进行计算
reg [10:0] temp_dh0, temp_dh1; //将积的高 11 位拆分成 dh0,dh1 两段进行计算
reg [11:0] temp_dl0, temp_dl1; //将积的低 12 位拆分成 dl0,dl1 两段进行计算
reg sign_stage_3;
reg [31:0] tol_div_a;
reg [22:0] tol_cos_d;
always @(posedge clk) begin//第一级流水线
if (rst) begin
sign_stage_2 < 0; //初始化
temp_ah0 < 0;
temp_ah1 < 0;
temp_ah2 < 0;
temp_al0 < 0;
temp_al1 < 0;
temp_al2 < 0;
end else begin
sign_stage_2 < reg_cos_result_stage_1[12];//符号位隔离
//计算 a 乘以 1/(a+b)
temp_ah0 < reg_a_stage_1[10:5] reg_div_result[20:14];
temp_ah1 < reg_a_stage_1[10:5] reg_div_result[13:7];
temp_ah2 < reg_a_stage_1[10:5] reg_div_result[6:0];
temp_al0 < reg_a_stage_1[4:0] reg_div_result[20:14];
temp_al1 < reg_a_stage_1[4:0] reg_div_result[13:7];
temp_al2 < reg_a_stage_1[4:0] reg_div_result[6:0];
//计算 d 乘以 cos
temp_dh0 < reg_cos_result_stage_1_tem[12:7] reg_d[9:5];
temp_dh1 < reg_cos_result_stage_1_tem[12:7] reg_d[4:0];
temp_dl0 < reg_cos_result_stage_1_tem[6:0] reg_d[9:5];
temp_dl1 < reg_cos_result_stage_1_tem[6:0] reg_d[4:0];
end
end
always @(posedge clk) begin//第二级流水线
if (rst) begin
sign_stage_3 < 0; //初始化
tol_div_a < 0;
tol_cos_d < 0;
end else begin
sign_stage_3 < sign_stage_2;
tol_div_a < {temp_ah0, 19'b0} {temp_ah1, 12'b0} {temp_ah2, 5'b0} {temp_al0, 14'b0} {temp_al1, 7'b0} temp_al2;
tol_cos_d < {temp_dh0, 12'b0} {temp_dh1, 7'b0 } {temp_dl0, 5'b0} temp_dl1;
end
end
Testbench
xxxxxxxxxx
`timescale 1ns10ps
`define data_0 10'b1110000000
`define data_1 10'b1111110000
module tb_function_gen (
a,b,c,e,clk,rst
);
output reg clk;
output reg clk2;
output reg [10:0] a;
output reg [10:0] b;
output reg [10:0] c;
output reg [0:0] e 0;
output reg [0:0] rst;
reg [9:0] d 11'd870; //11'd1023
reg [9:0] d_bit;
wire[11:0] y;
initial
begin
#5 clk 1'b0;
#5 clk2 1'b0;
#20 rst 1; //reset
#5 rst 0;
end
initial begin //异步信号d输入
#16;
repeat(10)begin
d_bit < (d[9]) `data_1 : `data_0;
d < d << 1;
repeat(10)@(posedge clk2)begin
e < d_bit[9];
d_bit < d_bit << 1;
end
end
#200;
end
initial
begin
a < 0; //初始化
b < 0;
c < 0;
clk < 0;
clk2 < 0;
#42 rst 1; //reset信号
#50 rst 0;
#300
a < 11'd1145; //a数据输入 1145
b < 11'd0928; //b数据输入 928
c < 11'd2009; //c数据输入 2009
end
always #2 clk < clk;//时钟信号
always #1.5 clk2 < clk2;
function_gen function_gen_inst(
.clk (clk ),
.rst (rst ),
.a (a),
.b (b),
.c (c),
.e (e),
.y (y)
);
endmodule
RTL行为仿真
Cadence AMS配置
Design Compiler综合
综合优化脚本
时序约束分析
功耗与面积分析
门级网表仿真
Cadence AMS配置
Innovus自动布局布线
版图综合脚本
时钟树综合与优化
一些时序debug手段
Calibre版图验证
LVS与修正
DRC与修正
版图综合后仿真
时序检查与分析
Comments 3 条评论
博主 ATRI
单机贴吧?
博主 ATRI
打个胶先
博主 LJLsama