在 SystemVerilog 中解压自定义数据字段

问题描述

我正在尝试为 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;