From two tools I get an 1800 restriction for this code: int k; if (v[k:0] > 3) … Expected a constant as index: k." “testbench.sv” 10 16
Range must be bounded by constant expressions.
Question: What is the rationale behind this?
Seems like a useful operation.
module m;
int k;
bit clk;
bit [15:0] v=16'HAA71;
bit [15:0] temp, vect;
initial forever #10 clk = !clk;
always @(posedge clk) begin
k = 4;
// ** Error: .\testr.sv(9): Range must be bounded by constant expressions.
if (v[k:0] > 3) $display("i= %d, v=%b", k, v); // line 9
// workaround
for (int i=15; i>k; i--) temp[i]=0;
for (int i=k; i>=0; i--) temp[i]=1;
vect=v & temp;
if (vect > 3) $display("i\k= %d, vect=%b", k, vect);
end
endmodule
SystemVerilog is statically typed meaning the compiler must determine all expression type at compile/elaboration. The width of a variable/operand is part of the type. An operand can be buried deep inside the context of an expression. The compiler has to determine the widths of all operands and propagate them through the entire expression through a complex set of rules. Doing this at runtime would have a significant impact on performance.
There is a simpler way of creating the mask in a single expression.
let range(val, width) = ( val & (2<<width)-1 )
if ( range(v,k) ) > 3)
library IEEE, OSVVM ;
use ieee.std_logic_1164.all ;
use ieee.numeric_std.all ;
use ieee.numeric_std_unsigned.all;
context osvvm.OsvvmContext ;
entity TestDynamicRange is
end entity TestDynamicRange ;
architecture t1 of TestDynamicRange is
signal k : integer := 0 ;
signal v : std_logic_vector(15 downto 0) := X"AA71" ;
begin
k <= k + 1 after 10 ns;
AffirmIf(v(k downto 0) > 3, "k = " & to_string(k) & ", v=" & to_hstring(v(k downto 0)) ) ;
process
begin
SetAlertLogName("TestDynamicRange") ;
SetLogEnable(PASSED, TRUE) ;
wait until k = 15 for 1 ms ;
wait for 5 ns ;
EndOfTestReports (ExternalErrors => (0, -4, 0)) ; -- expecting 4 errors
std.env.stop ;
end process ;
end architecture t1 ;