SystemVerilog 实例化模块在不应该共享输入时共享输入(简单解决方案)?
SystemVerilog Instantiated Modules Share Inputs When They Shouldn't (Easy Solution)?
我在实例化我的模块时遇到了一个小问题。我正在使用生成循环来创建 2 个计数器(16 位和 32 位计数器)的 100 个实例。每个计数器都应该有自己独立的控件(UPDN 和 EN),但它们共享一个时钟和一个复位。
模块说明:
SAT_COUNTER.sv // 简单的计数器模块
TWO_SC.sv // 实例化两个 SAT_COUNTER 模块(16 位和 32 位
计数器)
GEN_SC.sv // 实例化 TWO_SC 个模块的 100 个模块
tb_GEN_SC.sv // 测试台
我确定我的问题出在 GEN_SC 模块中,我在其中实例化了所有 100..
感谢您的帮助!提前致谢!
module SAT_COUNTER(
COUNT, // SCALABLE COUNT OUTPUT
CLK, // CLOCK
al_RST, // ACTIVE LOW RESET
UPDN, // COUNTER WILL COUNT: UP = 1; DN = 0;
EN); // ENABLE
parameter WIDTH = 8;
input CLK, al_RST, UPDN, EN;
output reg [WIDTH-1:0] COUNT;
...
endmodule
//**********************
module TWO_SC(
COUNT1, // N-BIT COUNTER OUTPUT
COUNT2, // M-BIT COUNTER OUTPUT
CLK, // CLOCK
al_RST, // ACTIVE-LOW RESET
UPDN, // DIR. CONTROL
EN); // ENABLE
parameter WIDTH1 = 16;
parameter WIDTH2 = 32;
input CLK, al_RST;
input [1:0] UPDN, EN;
output [WIDTH1-1:0] COUNT1;
output [WIDTH2-1:0] COUNT2;
SAT_COUNTER #(WIDTH1) GSC1(.COUNT(COUNT1), .CLK(CLK), .al_RST(al_RST), .UPDN(UPDN[0]), .EN(EN[0]));
SAT_COUNTER #(WIDTH2) GSC2(.COUNT(COUNT2), .CLK(CLK), .al_RST(al_RST), .UPDN(UPDN[1]), .EN(EN[1]));
endmodule
//**********************
module GEN_SC(
COUNT1, // COUNT1
COUNT2, // COUNT2
CLK, // CLOCK
al_RST, // ACTIVE-LOW RESET
UPDN, // DIR. CONTROL
EN); // ENABLE
parameter MOD_COUNT = 100;
parameter WIDTH1 = 16;
parameter WIDTH2 = 32;
input CLK, al_RST;
input [1:0] UPDN [MOD_COUNT-1:0];
input [1:0] EN [MOD_COUNT-1:0];
output [WIDTH1-1:0] COUNT1;
output [WIDTH2-1:0] COUNT2;
genvar j;
generate
for(j = 0; j < MOD_COUNT; j++) begin: SC
TWO_SC #(.WIDTH1(WIDTH1), .WIDTH2(WIDTH2)) TWOCOUNTERS(.COUNT1(COUNT1), .COUNT2(COUNT2), .CLK(CLK), .al_RST(al_RST), .UPDN(UPDN[j]), .EN(EN[j]));
end
endgenerate
endmodule
//**********************
module tb_GEN_SC();
parameter MOD_COUNT = 100;
parameter WIDTH1 = 16;
parameter WIDTH2 = 32;
reg CLK, al_RST;
reg [1:0] UPDN [MOD_COUNT-1:0];
reg [1:0] EN [MOD_COUNT-1:0];
wire [WIDTH1-1:0] COUNT1;
wire [WIDTH2-1:0] COUNT2;
GEN_SC #(.WIDTH1(WIDTH1), .WIDTH2(WIDTH2)) UUT(COUNT1, COUNT2, CLK, al_RST, UPDN, EN);
initial begin
CLK = 1'b1;
forever
#5 CLK = ~CLK;
end
initial
$monitorb("%d COUNT = %b (%d) | UPDN = %b | EN = %b | COUNT = %b (%d) | UPDN = %b | EN = %b | al_RST = %b | CLK = %b", $time, UUT.SC[87].TWOCOUNTERS.COUNT1, UUT.SC[87].TWOCOUNTERS.COUNT1, UUT.SC[87].TWOCOUNTERS.UPDN[0], UUT.SC[87].TWOCOUNTERS.EN[0], UUT.SC[99].TWOCOUNTERS.COUNT1, UUT.SC[99].TWOCOUNTERS.COUNT1, UUT.SC[99].TWOCOUNTERS.UPDN[0], UUT.SC[99].TWOCOUNTERS.EN[0], al_RST, CLK);
initial begin
$vcdpluson;
UUT.SC[87].TWOCOUNTERS.GSC1.UPDN = 1; UUT.SC[99].TWOCOUNTERS.GSC1.UPDN = 1; EN = 0; al_RST = 1;
#10 UUT.SC[99].TWOCOUNTERS.GSC1.UPDN = 0; al_RST = 0; // RESET COUNTER
#10 EN = 1; al_RST = 1; // ENABLE COUNTER AND COUNT UP (HITS MAX)
#200 UUT.SC[87].TWOCOUNTERS.GSC1.UPDN = 0; UUT.SC[99].TWOCOUNTERS.GSC1.UPDN = 1; EN = 1; // BEGIN TO COUNT DOWN
#10 EN = 0;
#60 EN = 3;
// #230 UPDN = 1; UPDN = 0;
#3017 al_RST = 0;
#100 al_RST = 1;
#20 $finish;
end
/////////// 我得到的错误 ////////////////
错误-[IBLHS-NT] 非法行为左侧
tb_GEN_SC.sv, 34
不能在此分配的左侧使用网络类型。
违规的表达是:tb_GEN_SC.UUT.SC[87].TWOCOUNTERS.GSC1.UPDN
来源信息:tb_GEN_SC.UUT.SC[87].TWOCOUNTERS.GSC1.UPDN = 1;
错误-[IBLHS-NT] 非法行为左侧
tb_GEN_SC.sv, 34
不能在此分配的左侧使用网络类型。
违规的表达是:tb_GEN_SC.UUT.SC[99].TWOCOUNTERS.GSC1.UPDN
来源信息:tb_GEN_SC.UUT.SC[99].TWOCOUNTERS.GSC1.UPDN = 1;
错误-[IUDA] 尺寸不兼容
tb_GEN_SC.sv, 34
分配中不兼容的解压缩尺寸
具有不兼容的解压缩维度的数组不能用于赋值,
初始化和实例化。
错误-[ICTA] 不兼容的复杂类型
tb_GEN_SC.sv, 34
不兼容的复杂类型赋值
源表达式的类型与目标表达式的类型不兼容。
不匹配的类型不能用于赋值、初始化和
实例化。目标的类型是'reg[1:0]$[99:0]',而类型
来源是 'int'。
源表达式:0
您的端口列表中只有一个UPDB 和一个EN 端口。那么您如何将不同的 UPDN 和 EN 应用于实例?
一个想法是定义一个大小为MOD_COUNT的数组,这样每个元素都有自己的控制输入。然后在 genvar 循环中你可以使用索引。像这样:
input [1:0] UPDN [MOD_COUNT-1:0];
input [1:0] EN [MOD_COUNT-1:0];
...
generate
for(j = 0; j < MOD_COUNT; j++) begin: SC
TWO_SC #(.WIDTH1(WIDTH1), .WIDTH2(WIDTH2)) TWOCOUNTERS(.COUNT1(COUNT1),
.COUNT2(COUNT2), .CLK(CLK), .al_RST(al_RST), .UPDN(UPDN[j]), .EN(EN[j]));
end
endgenerate
我在实例化我的模块时遇到了一个小问题。我正在使用生成循环来创建 2 个计数器(16 位和 32 位计数器)的 100 个实例。每个计数器都应该有自己独立的控件(UPDN 和 EN),但它们共享一个时钟和一个复位。
模块说明:
SAT_COUNTER.sv // 简单的计数器模块
TWO_SC.sv // 实例化两个 SAT_COUNTER 模块(16 位和 32 位 计数器)
GEN_SC.sv // 实例化 TWO_SC 个模块的 100 个模块
tb_GEN_SC.sv // 测试台
我确定我的问题出在 GEN_SC 模块中,我在其中实例化了所有 100..
感谢您的帮助!提前致谢!
module SAT_COUNTER(
COUNT, // SCALABLE COUNT OUTPUT
CLK, // CLOCK
al_RST, // ACTIVE LOW RESET
UPDN, // COUNTER WILL COUNT: UP = 1; DN = 0;
EN); // ENABLE
parameter WIDTH = 8;
input CLK, al_RST, UPDN, EN;
output reg [WIDTH-1:0] COUNT;
...
endmodule
//**********************
module TWO_SC(
COUNT1, // N-BIT COUNTER OUTPUT
COUNT2, // M-BIT COUNTER OUTPUT
CLK, // CLOCK
al_RST, // ACTIVE-LOW RESET
UPDN, // DIR. CONTROL
EN); // ENABLE
parameter WIDTH1 = 16;
parameter WIDTH2 = 32;
input CLK, al_RST;
input [1:0] UPDN, EN;
output [WIDTH1-1:0] COUNT1;
output [WIDTH2-1:0] COUNT2;
SAT_COUNTER #(WIDTH1) GSC1(.COUNT(COUNT1), .CLK(CLK), .al_RST(al_RST), .UPDN(UPDN[0]), .EN(EN[0]));
SAT_COUNTER #(WIDTH2) GSC2(.COUNT(COUNT2), .CLK(CLK), .al_RST(al_RST), .UPDN(UPDN[1]), .EN(EN[1]));
endmodule
//**********************
module GEN_SC(
COUNT1, // COUNT1
COUNT2, // COUNT2
CLK, // CLOCK
al_RST, // ACTIVE-LOW RESET
UPDN, // DIR. CONTROL
EN); // ENABLE
parameter MOD_COUNT = 100;
parameter WIDTH1 = 16;
parameter WIDTH2 = 32;
input CLK, al_RST;
input [1:0] UPDN [MOD_COUNT-1:0];
input [1:0] EN [MOD_COUNT-1:0];
output [WIDTH1-1:0] COUNT1;
output [WIDTH2-1:0] COUNT2;
genvar j;
generate
for(j = 0; j < MOD_COUNT; j++) begin: SC
TWO_SC #(.WIDTH1(WIDTH1), .WIDTH2(WIDTH2)) TWOCOUNTERS(.COUNT1(COUNT1), .COUNT2(COUNT2), .CLK(CLK), .al_RST(al_RST), .UPDN(UPDN[j]), .EN(EN[j]));
end
endgenerate
endmodule
//**********************
module tb_GEN_SC();
parameter MOD_COUNT = 100;
parameter WIDTH1 = 16;
parameter WIDTH2 = 32;
reg CLK, al_RST;
reg [1:0] UPDN [MOD_COUNT-1:0];
reg [1:0] EN [MOD_COUNT-1:0];
wire [WIDTH1-1:0] COUNT1;
wire [WIDTH2-1:0] COUNT2;
GEN_SC #(.WIDTH1(WIDTH1), .WIDTH2(WIDTH2)) UUT(COUNT1, COUNT2, CLK, al_RST, UPDN, EN);
initial begin
CLK = 1'b1;
forever
#5 CLK = ~CLK;
end
initial
$monitorb("%d COUNT = %b (%d) | UPDN = %b | EN = %b | COUNT = %b (%d) | UPDN = %b | EN = %b | al_RST = %b | CLK = %b", $time, UUT.SC[87].TWOCOUNTERS.COUNT1, UUT.SC[87].TWOCOUNTERS.COUNT1, UUT.SC[87].TWOCOUNTERS.UPDN[0], UUT.SC[87].TWOCOUNTERS.EN[0], UUT.SC[99].TWOCOUNTERS.COUNT1, UUT.SC[99].TWOCOUNTERS.COUNT1, UUT.SC[99].TWOCOUNTERS.UPDN[0], UUT.SC[99].TWOCOUNTERS.EN[0], al_RST, CLK);
initial begin
$vcdpluson;
UUT.SC[87].TWOCOUNTERS.GSC1.UPDN = 1; UUT.SC[99].TWOCOUNTERS.GSC1.UPDN = 1; EN = 0; al_RST = 1;
#10 UUT.SC[99].TWOCOUNTERS.GSC1.UPDN = 0; al_RST = 0; // RESET COUNTER
#10 EN = 1; al_RST = 1; // ENABLE COUNTER AND COUNT UP (HITS MAX)
#200 UUT.SC[87].TWOCOUNTERS.GSC1.UPDN = 0; UUT.SC[99].TWOCOUNTERS.GSC1.UPDN = 1; EN = 1; // BEGIN TO COUNT DOWN
#10 EN = 0;
#60 EN = 3;
// #230 UPDN = 1; UPDN = 0;
#3017 al_RST = 0;
#100 al_RST = 1;
#20 $finish;
end
/////////// 我得到的错误 ////////////////
错误-[IBLHS-NT] 非法行为左侧 tb_GEN_SC.sv, 34 不能在此分配的左侧使用网络类型。 违规的表达是:tb_GEN_SC.UUT.SC[87].TWOCOUNTERS.GSC1.UPDN 来源信息:tb_GEN_SC.UUT.SC[87].TWOCOUNTERS.GSC1.UPDN = 1;
错误-[IBLHS-NT] 非法行为左侧 tb_GEN_SC.sv, 34 不能在此分配的左侧使用网络类型。 违规的表达是:tb_GEN_SC.UUT.SC[99].TWOCOUNTERS.GSC1.UPDN 来源信息:tb_GEN_SC.UUT.SC[99].TWOCOUNTERS.GSC1.UPDN = 1;
错误-[IUDA] 尺寸不兼容 tb_GEN_SC.sv, 34 分配中不兼容的解压缩尺寸 具有不兼容的解压缩维度的数组不能用于赋值, 初始化和实例化。
错误-[ICTA] 不兼容的复杂类型 tb_GEN_SC.sv, 34 不兼容的复杂类型赋值 源表达式的类型与目标表达式的类型不兼容。 不匹配的类型不能用于赋值、初始化和 实例化。目标的类型是'reg[1:0]$[99:0]',而类型 来源是 'int'。 源表达式:0
您的端口列表中只有一个UPDB 和一个EN 端口。那么您如何将不同的 UPDN 和 EN 应用于实例?
一个想法是定义一个大小为MOD_COUNT的数组,这样每个元素都有自己的控制输入。然后在 genvar 循环中你可以使用索引。像这样:
input [1:0] UPDN [MOD_COUNT-1:0];
input [1:0] EN [MOD_COUNT-1:0];
...
generate
for(j = 0; j < MOD_COUNT; j++) begin: SC
TWO_SC #(.WIDTH1(WIDTH1), .WIDTH2(WIDTH2)) TWOCOUNTERS(.COUNT1(COUNT1),
.COUNT2(COUNT2), .CLK(CLK), .al_RST(al_RST), .UPDN(UPDN[j]), .EN(EN[j]));
end
endgenerate