如何编写参数化延迟寄存器?
How do you write a parameterized delay register?
我正在尝试编写具有宽度和延迟参数的通用 Verilog 锁存器模块(延迟用于 synchronization/CDC 目的)。起初我想根据延迟参数生成多个延迟寄存器,但我决定只使用一个移位寄存器,根据延迟调整大小,因为我认为它更简洁。代码如下:
module latch # (
parameter WIDTH = 32,
parameter DELAY = 0
)
(
input clk,
input resetn,
input [WIDTH-1:0] din,
output reg [WIDTH-1:0] dout
);
reg [(WIDTH*(DELAY))-1:0] dly;
always @ (posedge clk)
begin
if (!resetn)
begin
dly <= 0;
dout <= 0;
end
else
begin
if (DELAY == 0)
begin
dout <= din;
end
else
begin
dly <= {dly[(WIDTH*(DELAY-1))-1:0], din};
dout <= dly[(WIDTH*(DELAY))-1 -: WIDTH];
end
end
end
endmodule
xvlog
对此没有问题,即使使用 DELAY = 0
实例化也是如此。然而,Vivado 综合 returns:
ERROR: [Synth 8-524] part-select [-1:0] out of range of prefix 'dly'
当此模块用 DELAY = 0
实例化时。你会如何解决这个问题?我以为我可以定义一个最大宏并将寄存器的顶部索引设置为 max(0, (WIDTH*(DELAY-1))-1)
,但当然这会被拒绝为可变宽度寄存器。是否可以根据参数有条件地声明寄存器?
您可以尝试使用 generate
if
语句来有条件地声明寄存器:
module latch # (
parameter WIDTH = 32,
parameter DELAY = 0
)
(
input clk,
input resetn,
input [WIDTH-1:0] din,
output reg [WIDTH-1:0] dout
);
if (DELAY == 0)
begin
always @ (posedge clk)
begin
if (!resetn)
begin
dout <= 0;
end
else
begin
dout <= din;
end
end
end
else if (DELAY == 1)
begin
reg [WIDTH-1:0] dly;
always @ (posedge clk)
begin
if (!resetn)
begin
dly <= 0;
dout <= 0;
end
else
begin
dly <= din;
dout <= dly;
end
end
end
else
begin
reg [(WIDTH*(DELAY))-1:0] dly;
always @ (posedge clk)
begin
if (!resetn)
begin
dly <= 0;
dout <= 0;
end
else
begin
dly <= {dly[(WIDTH*(DELAY-1))-1:0], din};
dout <= dly[(WIDTH*DELAY)-1 -: WIDTH];
end
end
end
endmodule
generate
关键字是可选的。请参阅 IEEE 标准 1800-2017,第 27 节。生成构造
是的,您可以使用生成 if
构造有条件地声明寄存器。
module latch # (
parameter WIDTH = 32,
parameter DELAY = 0
)
(
input clk,
input resetn,
input [WIDTH-1:0] din,
output reg [WIDTH-1:0] dout
);
if (DELAY==0) begin
dout <= din;
end else begin
reg [(WIDTH*(DELAY))-1:0] dly;
always @ (posedge clk)
begin
if (!resetn)
begin
dly <= 0;
dout <= 0;
end
else
begin
if (DELAY == 0)
begin
dout <= din;
end
else
begin
dly <= {dly[(WIDTH*(DELAY-1))-1:0], din};
dout <= dly[(WIDTH*(DELAY))-1 -: WIDTH];
end
end
end
end
endmodule
我正在尝试编写具有宽度和延迟参数的通用 Verilog 锁存器模块(延迟用于 synchronization/CDC 目的)。起初我想根据延迟参数生成多个延迟寄存器,但我决定只使用一个移位寄存器,根据延迟调整大小,因为我认为它更简洁。代码如下:
module latch # (
parameter WIDTH = 32,
parameter DELAY = 0
)
(
input clk,
input resetn,
input [WIDTH-1:0] din,
output reg [WIDTH-1:0] dout
);
reg [(WIDTH*(DELAY))-1:0] dly;
always @ (posedge clk)
begin
if (!resetn)
begin
dly <= 0;
dout <= 0;
end
else
begin
if (DELAY == 0)
begin
dout <= din;
end
else
begin
dly <= {dly[(WIDTH*(DELAY-1))-1:0], din};
dout <= dly[(WIDTH*(DELAY))-1 -: WIDTH];
end
end
end
endmodule
xvlog
对此没有问题,即使使用 DELAY = 0
实例化也是如此。然而,Vivado 综合 returns:
ERROR: [Synth 8-524] part-select [-1:0] out of range of prefix 'dly'
当此模块用 DELAY = 0
实例化时。你会如何解决这个问题?我以为我可以定义一个最大宏并将寄存器的顶部索引设置为 max(0, (WIDTH*(DELAY-1))-1)
,但当然这会被拒绝为可变宽度寄存器。是否可以根据参数有条件地声明寄存器?
您可以尝试使用 generate
if
语句来有条件地声明寄存器:
module latch # (
parameter WIDTH = 32,
parameter DELAY = 0
)
(
input clk,
input resetn,
input [WIDTH-1:0] din,
output reg [WIDTH-1:0] dout
);
if (DELAY == 0)
begin
always @ (posedge clk)
begin
if (!resetn)
begin
dout <= 0;
end
else
begin
dout <= din;
end
end
end
else if (DELAY == 1)
begin
reg [WIDTH-1:0] dly;
always @ (posedge clk)
begin
if (!resetn)
begin
dly <= 0;
dout <= 0;
end
else
begin
dly <= din;
dout <= dly;
end
end
end
else
begin
reg [(WIDTH*(DELAY))-1:0] dly;
always @ (posedge clk)
begin
if (!resetn)
begin
dly <= 0;
dout <= 0;
end
else
begin
dly <= {dly[(WIDTH*(DELAY-1))-1:0], din};
dout <= dly[(WIDTH*DELAY)-1 -: WIDTH];
end
end
end
endmodule
generate
关键字是可选的。请参阅 IEEE 标准 1800-2017,第 27 节。生成构造
是的,您可以使用生成 if
构造有条件地声明寄存器。
module latch # (
parameter WIDTH = 32,
parameter DELAY = 0
)
(
input clk,
input resetn,
input [WIDTH-1:0] din,
output reg [WIDTH-1:0] dout
);
if (DELAY==0) begin
dout <= din;
end else begin
reg [(WIDTH*(DELAY))-1:0] dly;
always @ (posedge clk)
begin
if (!resetn)
begin
dly <= 0;
dout <= 0;
end
else
begin
if (DELAY == 0)
begin
dout <= din;
end
else
begin
dly <= {dly[(WIDTH*(DELAY-1))-1:0], din};
dout <= dly[(WIDTH*(DELAY))-1 -: WIDTH];
end
end
end
end
endmodule