上一篇文章介绍了有关分频器的RTL设计,有细心的读者可以发现RTL代码并不完善,如何对RTL改进,优雅的写出RTL,让面试官对你的coding style有深刻的印象,并认为你的基础扎实;
下面先看这个例子:
使用Verilog语言编写7分频的RTL设计:
module div_old_7( //define div = N
input clk,
input rstn,
output o_clk
);
parameter N = 7;
reg [2:0] clk_cnt_pos, clk_cnt_neg;
reg pos_clk, neg_clk;
//pos_edge clk cnt
always @(posedge clk ) begin
if (!rstn)
clk_cnt_pos <= 3'b0;
else if (clk_cnt_pos == N-1)
clk_cnt_pos <= 3'b0;
else
clk_cnt_pos <= clk_cnt_pos + 1'b1;
end
//pos clk flag
always @(posedge clk ) begin
if (!rstn)
pos_clk <= 1'b0;
else if (clk_cnt_pos == N-1 )
pos_clk <= ~pos_clk;
else if (clk_cnt_pos == (N-1)/2 - 1)
pos_clk <= ~pos_clk;
end
//neg_edge clk
always @(negedge clk ) begin
if (!rstn)
clk_cnt_neg <= 3'b0;
else if (clk_cnt_neg == N-1)
clk_cnt_neg <= 3'b0;
else
clk_cnt_neg <= clk_cnt_neg + 1'b1;
end
//neg clk flag
always @(negedge clk ) begin
if (!rstn)
neg_clk <= 1'b0;
else if (clk_cnt_neg == N-1 )
neg_clk <= ~pos_clk;
else if (clk_cnt_neg == (N-1)/2 - 1)
neg_clk <= ~neg_clk;
end
assign o_clk = neg_clk | pos_clk;
endmodule
上述RTL设计有如下问题:
采用同步复位带来的问题,虽然采用同步设计的思路,可以有效避免亚稳态,但是在FPGA或ASIC设计中,标准单元库中的寄存器一般均带有异步复位端的寄存器,如果大量采用这种设计,会带来额外的逻辑来确保功能正确;
采用两个上升沿always语句块与采用两个下降沿always语句块,其实在综合过程中也会在面积上有一定的增加;可以考虑将相同的功能块尽量放在一个always语句块中;
采用(N-1)/2的设计方法,也会带来面积上的增加的问题;
最后采用将时钟直接或逻辑的操作,虽然在功能上并不会带来问题,但是对于敏感时钟来说,毛刺可能会发生,因此,在实际设计应用中,需要确保产生的高质量的时钟;
优雅的写出7分频RTL设计:
module div_old_7( //define div = N
input clk,
input rstn,
output reg o_clk
);
parameter N = 7;
reg rstn_sync0,rstn_sync1;
always @(posedge clk or negedge rstn) begin
if (!rstn)
{rstn_sync1,rstn_sync0} <= 2'b00;
else
{rstn_sync1,rstn_sync0} <={rstn_sync0,1'b1,};
end
reg [2:0] clk_cnt_pos, clk_cnt_neg;
reg pos_clk, neg_clk;
always @(posedge clk or negedge rstn_sync1) begin
if (!rstn_sync1) begin
clk_cnt_pos <= 0;
pos_clk <= 1'b0;
end
else if (clk_cnt_pos == N-1) begin
clk_cnt_pos <= 0;‘’
pos_clk <= ~pos_clk;
end
else if (clk_cnt_pos == (N-1) >> 1 - 1 ) begin
clk_cnt_pos <= clk_cnt_pos + 1'b1;
pos_clk <= ~pos_clk;
end
else
clk_cnt_pos <= clk_cnt_pos + 1'b1;
end
always @(negedge clk or negedge rstn_sync1) begin
if (!rstn_sync1) begin
clk_cnt_neg <= 0;
neg_clk <= 1'b0;
end
else if (clk_cnt_neg == N-1) beign
clk_cnt_neg <= 0
neg_clk <= ~neg_clk;
end
else if (clk_cnt_neg == (N-1)>>1 - 1 ) begin
clk_cnt_neg <= clk_cnt_neg + 1'b1;
neg_clk <= ~neg_clk;
end
else
clk_cnt_neg <= clk_cnt_neg +1'b1;
end
always @(negedge clk or negedge rstn_sync1) begin
if (!rstn_sync1)
o_clk <= 1'b0;
else
o_clk <= neg_clk | pos_clk;
end
endmodule
喜欢作者的朋友们欢迎关注B站: 摆渡沧桑