【前端验证】通关寄存器与ral_model —— 25种常用寄存器类型全览

寄存器的属性分类

本文档对于寄存器的属性以synopsys相关文档以及ral_model生成模型时的识别方式为基准。通常讲可以归纳为以下三个方面:读写属性read-write access、写后值modified write value、读后操作read action。注意,这里指的都是软件的操作,对于硬件侧而言,寄存器无法感知到读行为,对于写行为一般允许通过hw_wen和hw_wdata进行操作。

通过这三方面的属性,可以精准的描述一个寄存器的行为,比如:

在这里插入图片描述
在寄存器的xml描述中,采用如下的方式表示一个field的这三方面属性:

    <spirit:access>read-write</spirit:access>
    <spirit:modifiedWriteValue>oneToSet</spirit:modifiedWriteValue>
    <spirit:readAction>clear</spirit:readAction>

需要注意的是,access是必须要进行描述的,而modifiedWriteValue和readAction则不强制。modifiedWriteValue的缺省属性为总线数据写入,readAction的缺省属性为不改变寄存器值。

因此接下来先看一下这三个方面的属性都有哪些描述符。

Read-write Access

读写属性标记个某个寄存器(在此不区分寄存器reg和域field)是否可以被软件访问。

AccessReadWrite
read-write返回寄存器值参见Modified Write Value
read-only返回寄存器值总线返回error
write-only总线返回error,总线读取值不可预期参见 Modified Write Value
read-writeOnce返回寄存器值复位后只可写一次,写操作参见 Modified Write Value,后续写操作无效
writeOnce总线返回error,总线读取值不可预期复位后只可写一次,写操作参见 Modified Write Value,后续写操作无效

Modified Write Value

写后操作标记了某个寄存器在软件写操后数值的变化。

modifiedWriteValue对应bit写0对应bit写1
NA(缺省)清0置1
oneToClear无影响清0
oneToSet无影响置1
oneToToggle无影响翻转
zeroToClear清0无影响
zeroToSet置1无影响
zeroToToggle翻转无影响
clear清0清0
set置1置1

Read Action

读后行为标记了某个寄存器在软件读操后数值的变化。

readAction
NA(缺省)无影响
clear清0
set置1

寄存器类型与RAL支持情况

结合以上三方面属性以及相关文档和ral_model的实际情况,可以得到下面的25种寄存器行为汇总和ral_model支持情况表格。

属性行为accessmodifiedWriteValuereadActionral是否支持
rw软件可读可写read-writeNANA
ro软件可读,写返回总线报错read-onlyNANA
wo软件可写,读数据报错write-onlyNANA
w1仅复位后可写一次,读数据报错read-writeOnceNANA
w1c写1清0,软件可读read-writeoneToClearNA
rc软件读清零,写报错read-onlyNAclear
rs软件读置1,写报错read-onlyNAset
wrc软件可读写,读清零read-writeNAclear
wrs软件可读写,读置1read-writeNAset
wc软件可读写,写清零read-writeclearNA
ws软件可读写,写置1read-writesetNA
wsrc写置1,读清0read-writesetclear
wcrs写清0,读置1read-writeclearset
w1s写1置1,写0不变,软件可读read-writeoneToSetNA
w1t写1翻转,写0不变,软件可读read-writeoneToToggleNA
w0c写0清0,写1不变,软件可读read-writezeroToClearNA
w0s写0置1,写1不变,软件可读read-writezeroToSetNA
w0t写0翻转,软件可读read-writezeroToToggleNA
w1src写1置1,写0不变,读清0read-writeoneToSetclear
w1crs写1清0,写0不变,读置1read-writeoneToClearset
w0src写0置1,写1不变,读清0read-writezeroToSetclear
w0crs写0清0,写1不变,读置1read-writezeroToClearset
woc写清0,读错误write-onlyclearNA
wos写置1,读错误write-onlysetNA
wo1写置1,仅复位后第一次写有效,读错误writeOnceNANA

关键寄存器类型RTL实现

基于以上所有内容,对关键寄存器进行RTL实现。先确定一下寄存器的接口,个人是倾向于能够把寄存器的接口尽量的统一的,如有特殊情况再进行修改,因此规划的接口如下:

module reg_field #(
    parameter WD  = 32,
    parameter RST = {WD{1'b0}})
(
    input          clk,
    input          rst_n,

    input          st_wen,
    input          st_ren,
    input [WD -1:0]st_wdata,

    input          hw_wen,
    input [WD -1:0]hw_wdata,

    output[WD -1:0]rdata
);

endmodule

st代表软件操作,hw代表硬件操作。当然了软件操作更常见的信号是sel/en加wen的表示,不过我自己更喜欢wen和ren的方式所以就选了这样的接口规划。

而后需要说明的是,对于软件不可写或软件不可读的寄存器,个人倾向于在寄存器的上层进行控制。若一个寄存器不可写,那么st_wen不应该被上层调度模块拉起,且上层调度模块需要返回一个error状态给到总线。若一个寄存器不可读,那么st_ren同样不应该被拉起,且上层调度模块不应驱动总线上的读数据(使其保持旧值或高阻)同时返回error状态。基于这种思路,那么rw和wo就可以共用代码了,因为软件读的行为由上层处理。

RW/WO

//both for rw/wo
module reg_rw_field #(
    parameter WD  = 32,
    parameter RST = {WD{1'b0}})
(
    input          clk,
    input          rst_n,

    input          st_wen,
    input          st_ren,
    input [WD -1:0]st_wdata,

    input          hw_wen,
    input [WD -1:0]hw_wdata,

    output[WD -1:0]rdata
);
reg [WD -1:0]data_ff;

always @(posedge clk or negedge rst_n)begin
    if(!rst_n)
        data_ff <= RST;
    else if(st_wen)
        data_ff <= st_wdata;
    else if(hw_wen)
        data_ff <= hw_wdata;
end

assign rdata = data_ff;

endmodule

RO

只读型寄存器是唯一没有寄存器实体的,直接将内部寄存器的值拉出来即可。

module reg_ro_field #(
    parameter WD  = 32,
    parameter RST = {WD{1'b0}})
(
    input          clk,
    input          rst_n,

    input [WD -1:0]hw_wdata,
    output[WD -1:0]rdata
);

assign rdata = hw_wdata;

endmodule

W1

module reg_w1_field #(
    parameter WD  = 32,
    parameter RST = {WD{1'b0}})
(
    input          clk,
    input          rst_n,

    input          st_wen,
    input          st_ren,
    input [WD -1:0]st_wdata,

    output[WD -1:0]rdata
);
reg [WD -1:0]data_ff;
reg lock_en;

always @(posedge clk or negedge rst_n)begin
    if(!rst_n)
        data_ff <= RST;
    else if(!lock_en && st_wen)
        data_ff <= st_wdata;
end

always @(posedge clk or negedge rst_n)begin
    if(!rst_n)
        lock_en <= 1'b0;
    else if(st_wen)
        lock_en <= 1'b1;
end

assign rdata = data_ff;

endmodule

W1C

module reg_w1c_field #(
    parameter WD  = 32,
    parameter RST = {WD{1'b0}})
(
    input          clk,
    input          rst_n,

    input          st_wen,
    input          st_ren,
    input [WD -1:0]st_wdata,

    input          hw_wen,
    input [WD -1:0]hw_wdata,

    output[WD -1:0]rdata
);
reg [WD -1:0]data_ff;

always @(posedge clk or negedge rst_n)begin
    if(!rst_n)
        data_ff <= RST;
    else if(hw_wen)
        data_ff <= hw_wdata;
    else if(st_wen)
        data_ff <= (~st_wdata & data_ff);
end

assign rdata = data_ff;

endmodule

RC

注意,读清寄存器软件读后必须清零,而不是清为复位值。

module reg_rc_field #(
    parameter WD  = 32,
    parameter RST = {WD{1'b0}})
(
    input          clk,
    input          rst_n,

    input          st_wen,
    input          st_ren,
    input [WD -1:0]st_wdata,

    input          hw_wen,
    input [WD -1:0]hw_wdata,

    output[WD -1:0]rdata
);
reg [WD -1:0]data_ff;

always @(posedge clk or negedge rst_n)begin
    if(!rst_n)
        data_ff <= RST;
    else if(hw_wen)
        data_ff <= hw_wdata;
    else if(st_ren)
        data_ff <= {WD{1'b0}};
end

assign rdata = data_ff;

endmodule

RS

module reg_rs_field #(
    parameter WD  = 32,
    parameter RST = {WD{1'b0}})
(
    input          clk,
    input          rst_n,

    input          st_wen,
    input          st_ren,
    input [WD -1:0]st_wdata,

    input          hw_wen,
    input [WD -1:0]hw_wdata,

    output[WD -1:0]rdata
);
reg [WD -1:0]data_ff;

always @(posedge clk or negedge rst_n)begin
    if(!rst_n)
        data_ff <= RST;
    else if(hw_wen)
        data_ff <= hw_wdata;
    else if(st_ren)
        data_ff <= {WD{1'b1}};
end

assign rdata = data_ff;

endmodule

WRC

module reg_wrc_field #(
    parameter WD  = 32,
    parameter RST = {WD{1'b0}})
(
    input          clk,
    input          rst_n,

    input          st_wen,
    input          st_ren,
    input [WD -1:0]st_wdata,

    input          hw_wen,
    input [WD -1:0]hw_wdata,

    output[WD -1:0]rdata
);
reg [WD -1:0]data_ff;

always @(posedge clk or negedge rst_n)begin
    if(!rst_n)
        data_ff <= RST;
    else if(hw_wen)
        data_ff <= hw_wdata;
    else if(st_wen)
        data_ff <= st_wdata;
    else if(st_ren)
        data_ff <=  {WD{1'b0}};
end

assign rdata = data_ff;

endmodule

WRS

module reg_wrs_field #(
    parameter WD  = 32,
    parameter RST = {WD{1'b0}})
(
    input          clk,
    input          rst_n,

    input          st_wen,
    input          st_ren,
    input [WD -1:0]st_wdata,

    input          hw_wen,
    input [WD -1:0]hw_wdata,

    output[WD -1:0]rdata
);
reg [WD -1:0]data_ff;

always @(posedge clk or negedge rst_n)begin
    if(!rst_n)
        data_ff <= RST;
    else if(hw_wen)
        data_ff <= hw_wdata;
    else if(st_wen)
        data_ff <= st_wdata;
    else if(st_ren)
        data_ff <= {WD{1'b1}};
end

assign rdata = data_ff;

endmodule

WC

module reg_wc_field #(
    parameter WD  = 32,
    parameter RST = {WD{1'b0}})
(
    input          clk,
    input          rst_n,

    input          st_wen,
    input          st_ren,
    input [WD -1:0]st_wdata,

    input          hw_wen,
    input [WD -1:0]hw_wdata,

    output[WD -1:0]rdata
);
reg [WD -1:0]data_ff;

always @(posedge clk or negedge rst_n)begin
    if(!rst_n)
        data_ff <= RST;
    else if(hw_wen)
        data_ff <= hw_wdata;
    else if(st_wen)
        data_ff <= {WD{1'b0}};
end

assign rdata = data_ff;

endmodule

WS

module reg_wc_field #(
    parameter WD  = 32,
    parameter RST = {WD{1'b0}})
(
    input          clk,
    input          rst_n,

    input          st_wen,
    input          st_ren,
    input [WD -1:0]st_wdata,

    input          hw_wen,
    input [WD -1:0]hw_wdata,

    output[WD -1:0]rdata
);
reg [WD -1:0]data_ff;

always @(posedge clk or negedge rst_n)begin
    if(!rst_n)
        data_ff <= RST;
    else if(hw_wen)
        data_ff <= hw_wdata;
    else if(st_wen)
        data_ff <= {WD{1'b1}};
end

assign rdata = data_ff;

endmodule

WSRC

module reg_wsrc_field #(
    parameter WD  = 32,
    parameter RST = {WD{1'b0}})
(
    input          clk,
    input          rst_n,

    input          st_wen,
    input          st_ren,
    input [WD -1:0]st_wdata,

    input          hw_wen,
    input [WD -1:0]hw_wdata,

    output[WD -1:0]rdata
);
reg [WD -1:0]data_ff;

always @(posedge clk or negedge rst_n)begin
    if(!rst_n)
        data_ff <= RST;
    else if(hw_wen)
        data_ff <= hw_wdata;
    else if(st_wen)
        data_ff <= {WD{1'b1}};
    else if(st_ren)
        data_ff <= {WD{1'b0}};
end

assign rdata = data_ff;

endmodule

WCRS

module reg_wcrs_field #(
    parameter WD  = 32,
    parameter RST = {WD{1'b0}})
(
    input          clk,
    input          rst_n,

    input          st_wen,
    input          st_ren,
    input [WD -1:0]st_wdata,

    input          hw_wen,
    input [WD -1:0]hw_wdata,

    output[WD -1:0]rdata
);
reg [WD -1:0]data_ff;

always @(posedge clk or negedge rst_n)begin
    if(!rst_n)
        data_ff <= RST;
    else if(hw_wen)
        data_ff <= hw_wdata;
    else if(st_wen)
        data_ff <= {WD{1'b0}};
    else if(st_ren)
        data_ff <= {WD{1'b1}};
end

assign rdata = data_ff;

endmodule

W1S

module reg_field #(
    parameter WD  = 32,
    parameter RST = {WD{1'b0}})
(
    input          clk,
    input          rst_n,

    input          st_wen,
    input          st_ren,
    input [WD -1:0]st_wdata,

    input          hw_wen,
    input [WD -1:0]hw_wdata,

    output[WD -1:0]rdata
);
reg [WD -1:0]data_ff;

always @(posedge clk or negedge rst_n)begin
    if(!rst_n)
        data_ff <= RST;
    else if(hw_wen)
        data_ff <= hw_wdata;
    else if(st_wen)
        data_ff <= data_ff | st_wdata;
end

assign rdata = data_ff;

endmodule

W1T

软件写1翻转,实际对应的就是原有值与写入值的亦或。

module reg_w1t_field #(
    parameter WD  = 32,
    parameter RST = {WD{1'b0}})
(
    input          clk,
    input          rst_n,

    input          st_wen,
    input          st_ren,
    input [WD -1:0]st_wdata,

    input          hw_wen,
    input [WD -1:0]hw_wdata,

    output[WD -1:0]rdata
);
reg [WD -1:0]data_ff;

always @(posedge clk or negedge rst_n)begin
    if(!rst_n)
        data_ff <= RST;
    else if(hw_wen)
        data_ff <= hw_wdata;
    else if(st_wen)
        data_ff <= st_wdata ^ data_ff;
end

assign rdata = data_ff;

endmodule

其他ral_model不支持的类型我就没有都写完了,仅供参考吧。

  • 1
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

尼德兰的喵

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值