IC设计笔记|论RTL中always语法的消失术
发布时间:2023-11-07来源:芯学长
这篇文章来整体的聊一下个人理解的例化寄存器型的RTL编码风格。在脱离实验室氛围开始在公司写芯片设计代码的时候,就发现公司里代码规范里明确表明:
1.避免always @*语句;
2.避免always时序语句;
这让我幼小的心灵备受打击,不用always怎么怎么写RTL呢?当然了写着写着也就习惯了。避免always @*这个咱们已经理解用意了,主要是避免X态问题被掩盖。那么避免always时序语句是为什么?又应该如何实操呢?
要避免always时序语句其实也很简单,自然就是例化dff了呀,根据接口和特性可以划分归类一下有哪几种dff我们可能会用得到:
1.是否需要复位
2.是否需要使能
3.是否需要校验
暂时排除第三种校验情况稍后再聊,根据前两个分类我们会得到以下的dff模块:1.moon_dffre
2.moon_dffr
3.moon_dffe
4.moon_dff
这个前缀就是做一下标志随便加就可以。dff例化的风格怎么取代always时序呢,以下面这段代码为例:
以dff风格写的话就是下面这样:
//信号声明
wire [7:0]power_d;
wire [7:0]power_q;
wire power_en;
//组合逻辑
assign power_en = case0 || case1 || case2;
assign power_d = case0 ? case0_data :
case1 ? case1_data :
power_q + 1'b1;
//时序逻辑
moon_dffre #(.WD(8))
u_power_dff(.clk(clk), .rst_n(rst_n), .d(power_d), .en(power_en), .q(power_q));
这两种代码风格哪种好呢?对于优秀的编码者这两种是没有优劣之分的。不过对于我这种入门级选手以及交付来说,选用dff例化风格的代码还是有收益的:
也可以很轻易的把三个区域分开:
那么这个收益是什么呢?这样编码形式和风格容易写出美感,毕竟好看才是编码第一要务!
好的,dff编码风格的收益部分就写完了,接下来进行实操部分,各种dff模块应该怎么写呢?从最典型的moon_dffre写起吧。dffre顾名思义就是有复位有使能,内部根据使能进行赋值:
两个参数分别是寄存器的位宽和复位值。那么如果在模块内加入关于X态的校验,可以增加如下的代码(示意):
`ifdef ASSERT_ON
property chk_en_xz();
@(posedge clk) disable iff(~rst_n)
~$isunknown(en);
endproperty
property chk_d_xz();
@(posedge clk) disable iff(~rst_n)
en |-> ~$isunknown(d);
endproperty
assert_chk_en_xz: assert property(chk_en_xz()) else $assertoff(0, assert_chk_en_xz);
assert_chk_d_xz: assert property(chk_d_xz()) else $assertoff(0, assert_chk_d_xz);
`endif
module moon_dffe #(
parameter WD = 1)
(
input clk,
input [DW -1:0]d,
input en,
output reg[DW -1:0]q
);
always @(posedge clk)begin
if(en) q <= d;
end
`ifdef ASSERT_ON
property chk_en_xz();
@(posedge clk) disable iff(~rst_n)
~$isunknown(en);
endproperty
property chk_d_xz();
@(posedge clk) disable iff(~rst_n)
en |-> ~$isunknown(d);
endproperty
assert_chk_en_xz: assert property(chk_en_xz()) else $assertoff(0, assert_chk_en_xz);
assert_chk_d_xz: assert property(chk_d_xz()) else $assertoff(0, assert_chk_d_xz);
`endif
endmodule
module moon_dffr #(
parameter WD = 1,
parameter VE = {WD{1'b0}})
(
input clk,
input rst_n,
input [DW -1:0]d,
output reg[DW -1:0]q
);
always @(posedge clk or negedge rst_n)begin
q <= d;
end
endmodule
module moon_dffr #(
parameter WD = 1,
parameter VE = {WD{1'b0}})
(
input clk,
input rst_n,
input [DW -1:0]d,
output reg[DW -1:0]q
);
always @(posedge clk)begin
q <= d;
end
endmodule
module moon_dffre_chk #(
parameter WD = 1,
parameter VE = {WD{1'b0}})
(
input clk,
input rst_n,
input [DW -1:0]d,
input en,
output reg[DW -1:0]q,
output e
);
always @(posedge clk or negedge rst_n)begin
if(!rst_n) q <= VE;
else if(en) q <= d;
end
reg err_q;
wire err_d = ^d;
always @(posedge clk or negedge rst_n)begin
if(!rst_n) err_q <= ^VE;
else if(en) err_q <= err_d;
end
assign e = (err_q != ^q);
`ifdef ASSERT_ON
property chk_en_xz();
@(posedge clk) disable iff(~rst_n)
~$isunknown(en);
endproperty
property chk_d_xz();
@(posedge clk) disable iff(~rst_n)
en |-> ~$isunknown(d);
endproperty
assert_chk_en_xz: assert property(chk_en_xz()) else $assertoff(0, assert_chk_en_xz);
assert_chk_d_xz: assert property(chk_d_xz()) else $assertoff(0, assert_chk_d_xz);
`endif
endmodule
【免责声明】:本站部分文章为转载或网友发布,目的在于传递和分享信息,并不代表本网赞同其观点和对其真实性负责;文章版权归原作者及原出处所有,如涉及作品内容、版权和其它问题,我们将根据著作权人的要求,第一时间更正或删除。