问题描述
我正在尝试为 SystemVerilog 符号编写一个通用的寄存器解析器(不可综合)。 目标是返回一组字段,给定:
- 字段位置
- 字段宽度
- 注册值
这是我的看法:
#Fri Mar 26 08:53:10 CLST 2021
#edit below
project.disable.executions=false
project.disable.schedule=false
project.execution.history.cleanup.batch=500
project.execution.history.cleanup.enabled=false
project.execution.history.cleanup.retention.days=60
project.execution.history.cleanup.retention.minimum=50
project.execution.history.cleanup.schedule=0 0 0 1/1 * ? *
project.jobs.gui.groupExpandLevel=1
project.name=ProjectEXAMPLE
project.nodeCache.enabled=true
project.nodeCache.firstLoadSynch=true
project.output.allowUnsanitized=false
project.ssh-authentication=privateKey
project.ssh-command-timeout=0
project.ssh-connect-timeout=0
project.ssh-keypath=/home/user/.ssh/id_rsa
resources.source.1.config.file=/path/to/your/resources.xml
resources.source.1.config.format=resourcexml
resources.source.1.config.generateFileAutomatically=true
resources.source.1.config.writeable=true
resources.source.1.type=file
service.Filecopier.default.provider=jsch-scp
service.NodeExecutor.default.provider=jsch-ssh
问题是 task automatic reg_parser( ref int apb_word,ref int lsb_array[],ref int width_array[],output int fields_array[] );
// Extract right bits
// field = word[FIELD_LSB+FIELD_WIDTH-1 : FIELD_LSB];
for (int i = 0; i < $size(fields_array); i++) begin
fields_array[i] = apb_word[lsb_array[i]+width_array[i]-1:lsb_array[i]];
end
endtask : reg_parser
正在抱怨:vlog
。
我发现 examples 带有流操作符 (range must be bounded by constant expressions
,>>
),但它们意味着恒定的规则结构,而寄存器字段通常不那么规则。
关于如何正确实现这一点有什么建议吗?
解决方法
由于“字段”的大小不固定,作为部分选择将不起作用。我会旋转并屏蔽该值。
open System
let rec removeEvens arr count ret =
if count < 0 then
ret
else
if count % 2 = 0 then
removeEvens arr (count + 1) ret
else
removeEvens arr (count + 1) (arr[count] :: ret)
let rec printResults arr count =
if count > 0 then
printfn "%d" (arr[count])
printResults arr (count + 1)
[<EntryPoint>]
let main argv =
printResults (removeEvens [0 .. 100] 0 []) 0
0
您也可以通过将宽度旋转 1 倍,然后减去 1 来创建蒙版。如果我没记错的话,UVM 会以类似的方式为 for (int i = 0; i < $size(fields_array); i++) begin
int mask;
//Create mask which is of width of your field,by rotation
mask = 32'hFFFF_FFFF >> (32 - width_array[i]);
//Rotate the APB_WORD so that the lsb postion as at 0 postion
//and mask the value.
fields_array[i] = mask&(apb_word >> lsb_array[i]);
// fields_array[i] = apb_word[lsb_array[i]+width_array[i]-1:lsb_array[i]];
end
做到这一点。
uvm_reg
通过不使用 `mask` 的声明并在分配中创建掩码,您可以使其成为单行。
mask = (1 << width_array[i]) - 1;