方法一
直接使用宏定义切换异步/同步寄存器两种写法;
简单明了,但是,很闹心;两部分代码容易不一样,导致出错
// 在顶层文件或头文件中定义
`define ASYNC_RESET // 注释掉则使用同步复位
module simple_ff(
input wire clk,
input wire rst_n,
input wire d,
output reg q
);
`ifdef ASYNC_RESET
// 异步复位
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
q <= 1'b0;
end else begin
q <= d;
end
end
`else
// 同步复位
always @(posedge clk) begin
if (!rst_n) begin
q <= 1'b0;
end else begin
q <= d;
end
end
`endif
endmodule
方法二
只用宏切换寄存器的always头;
相对方法一,更加简洁,也更加不容易出错;
但是,代码里寄存器很多,看着还是有点闹心;
// 在编译时通过命令行定义:+define+ASYNC_RST
// 或者在文件开头定义:`define ASYNC_RST
module simple_ff(
input wire clk,
input wire rst_n,
input wire d,
output reg q
);
// 只用一行宏定义切换
`ifdef ASYNC_RST
always @(posedge clk or negedge rst_n)
`else
always @(posedge clk)
`endif
begin
if (!rst_n) begin
q <= 1'b0;
end else begin
q <= d;
end
end
endmodule
方法三
宏只控制敏感信号列表的negedge rst_n部份,更加简洁明了一些:
/* 项目中复位信号名字很多时,推荐这种写法 */
module simple_ff(
input wire clk,
input wire rst_n,
input wire d,
output reg q
);
always @(posedge clk `ifdef ASYNC_RST or negedge rst_n `endif ) begin
if (!rst_n) begin
q <= 1'b0;
end else begin
q <= d;
end
end
endmodule
方法四
直接将复位的敏感信号列表定义成宏;
这种写法比较简洁明了,就看个人喜好了,是否能接受这种写法;
另外就是宏里面带了rst_n的复位信号名字,项目里有多少个复位信号名字时,就需要多少个宏定义
/* 项目代码风格比较统一,复位信号名字只有一两个时,推荐这种写法 */
// 异步复位
// `define ASYNC_RST ornegedgerst_n
// 同步复位
// `define ASYNC_RST
module simple_ff(
input wire clk,
input wire rst_n,
input wire d,
output reg q
);
always @(posedge clk `ASYNC_RST ) begin
if (!rst_n) begin
q <= 1'b0;
end else begin
q <= d;
end
end
endmodule
方法五
使用一个接口信号use_async来控制;use_async接常数1时,是异步复位;接0时是同步复位;
这种方法,逻辑上OK,但是总感觉依赖综合工具,不太推荐这种写法;
module simple_ff(
input wire clk,
input wire rst_n,
input wire use_async, // 控制信号
input wire d,
output reg q
);
// 关键:根据use_async决定敏感列表
always @(posedge clk or negedge (rst_n & use_async)) begin
if (!rst_n) begin
q <= 1'b0;
end else begin
q <= d;
end
end
endmodule
方法六
直接拉两个复位接口,一个同步复位,一个异步复位;同步复位本质上就是一个普通的信号;不用的那个信号接常数;
这种写法也很OK,但是有点繁琐,需要拉多个信号,而且代码多2行复位,收代码覆盖率时比较麻烦;
但是对于一个独立对外交付的IP时,使用这种方法比较简洁,对外只呈现2个接口,不依赖宏定义等;
/* 独立IP开发时,推荐这种写法 */
module simple_ff(
input wire clk,
input wire sync_rst_n, // 1:同步复位,高复位 input wire async_rst_en, // 1:异步复位,低复位
input wire d,
output reg q
);
// 统一写法:异步复位事件 + 同步复位逻辑
// 这种写法有点依赖综合工具,不符合习惯,建议使用后面的写法
always @(posedge clk or negedge async_rst_n) begin
if (~sync_rst_n & ~async_rst_en) begin
q <= 1'b0;
end else begin
q <= d;
end
end// 这种写法更加不依赖综合工具,推荐这样写
always @(posedge clk or negedge async_rst_n) begin
if (~async_rst_en) begin
q <= 1'b0;
end else if(~sync_rst_n)begin
q<=1'b0;
endelsebegin
q<=d;
end
end
endmodule