我现在正在尝试强制一个位数组中的一个位。被“强制”的位的位置取决于变量 i,而其他位保持 0。 例如,如果我有数组位
[2:0] A
当 i=0
时,我希望 A
成为 3'b001
当 i=1
时,A
应该是 3'b010
当 i=2
时,A
应该是 3'b100
但我必须使用强制语句,因为我正在编写测试平台来测试信号路径。
有谁知道我该怎么做?
更新1:@Serge我必须使用它声明如下的force语句:bit [31:0] A 我尝试了这个:force A[31:0] = 32'd0;对于 (int i=0;i<=31;i++) begin force A[i]=1; end Obviously it doesn't work. Actually I was testing different scearios to see if the path of the signal is properly done or not
update2:我现在已经生成了一个脚本来一一强制信号 不过,我不确定是否遇到错误 当这条语句被执行时 a[31:0] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,`TOP_TB.clk_1T,0}; a[1]保持为0。相反,1T clk出现在a[0]处。有谁知道发生什么事吗?
update3:感谢您的帮助!!我实际上认为0是用32位解释的,但我真的不知道为什么1T clk出现在位0而不是位1(我正在使用questasim)。顺便说一句,我已经通过生成脚本并将内容复制并粘贴到脚本生成的文本文件中来解决这个问题。
您可以在verilog中使用位索引来完成您想要的操作。 这就像在 C 中对数组进行索引。例如:
array_a[i] <= new_value;
在上面的代码中,如果 i 为 0,则会将 new_value 赋给 bit 0,其余保持不变。
来自语言参考手册 (IEEE Std 1800-2017),第 10.6.2 节(“强制和释放程序语句”):
赋值的左侧可以是对奇异变量、网络、向量网络的常量位选择、向量网络的常量部分选择或这些的串联的引用。它不应是变量或具有用户定义网络类型的网络的位选择或部分选择。
看来不可能直接做你想做的事。
我最好的选择是做或多或少你想做的事情(我只是强制单个位并让其他位正常发展),记住力分配的 LHS 应该是恒定的,是这样的:
module dut (
input logic [31:0] a,
input logic [31:0] b,
output logic [31:0] z
);
always_comb z = a & b;
endmodule: dut
module tb;
logic [31:0] a;
logic [31:0] b;
logic [31:0] z;
dut dut (.*);
logic clk = 0;
initial forever
#(5ns) clk = !clk;
logic [5:0] sel;
initial forever begin
case (sel)
6'd0: force z[0] = clk;
6'd1: force z[1] = clk;
6'd2: force z[2] = clk;
6'd3: force z[3] = clk;
6'd4: force z[4] = clk;
6'd5: force z[5] = clk;
6'd6: force z[6] = clk;
6'd7: force z[7] = clk;
6'd8: force z[8] = clk;
6'd9: force z[9] = clk;
6'd10: force z[10] = clk;
6'd11: force z[11] = clk;
6'd12: force z[12] = clk;
6'd13: force z[13] = clk;
6'd14: force z[14] = clk;
6'd15: force z[15] = clk;
6'd16: force z[16] = clk;
6'd17: force z[17] = clk;
6'd18: force z[18] = clk;
6'd19: force z[19] = clk;
6'd20: force z[20] = clk;
6'd21: force z[21] = clk;
6'd22: force z[22] = clk;
6'd23: force z[23] = clk;
6'd24: force z[24] = clk;
6'd25: force z[25] = clk;
6'd26: force z[26] = clk;
6'd27: force z[27] = clk;
6'd28: force z[28] = clk;
6'd29: force z[29] = clk;
6'd30: force z[30] = clk;
6'd31: force z[31] = clk;
endcase
@(clk or sel);
release z[0];
release z[1];
release z[2];
release z[3];
release z[4];
release z[5];
release z[6];
release z[7];
release z[8];
release z[9];
release z[10];
release z[11];
release z[12];
release z[13];
release z[14];
release z[15];
release z[16];
release z[17];
release z[18];
release z[19];
release z[20];
release z[21];
release z[22];
release z[23];
release z[24];
release z[25];
release z[26];
release z[27];
release z[28];
release z[29];
release z[30];
release z[31];
end
initial begin
a = 32'h0055aaffaa55ff00;
b = 32'habcdef0123456789;
sel = 6'd0;
#(98ns);
sel = 6'd6;
end
endmodule: tb
这适用于我的 ModelSim 版本(INTEL FPGA 入门版 10.6c)。
至于为什么你的代码:
a[31:0] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,`TOP_TB.clk_1T,0};
不起作用,我最好的猜测是每个“0”都被解释为integer0,即32'd0。然后你就有效地得到了一些东西:
a[31:0] = {960'd0, `TOP_TB.clk_1T, 32'd0};
RHS 被截断为仅 32 位。当然,截断意味着“32'd0”剩下的任何内容都会被丢弃,但您的编译器确实应该对此发出警告。比如:
a[31:0] = {30'b0,`TOP_TB.clk_1T,1'b0};
对我有用。当然,您也可以将该构造插入我在示例中使用的“案例”中。
Systemverilog 不允许您强制矢量的位片,因此您必须强制整个网络。这里一个好的策略是强制网络:
force A = A ^ my_force_vector;
并将 my_force_vector 设置为您想要强制的位。