Altifigence Academy

62 / 63 · 概念

寄存器接口与副作用发生时刻

规定地址、字节写入与响应暂停,使一个请求准确对应一次状态改变。

定义“写寄存器”这一行为

先修知识:地址译码器译码器 激活与二进制编码对应的输出线的电路。带 enable 时,可在禁用状态下将所有输出置 0。了解更多、ready/valid握手 发送端 valid 与接收端 ready 在同一边沿均为 1 时,确认传输的约定,也包括等待期间的数据保持规则。了解更多、enable 与状态更新优先级。

将配置寄存器寄存器 存储多位状态的电路。本课程中的同步寄存器在时钟边沿存储指定输入。了解更多连接到外部控制器时,只检查地址匹配并不够。还要定义请求接受时刻、响应等待期间的保持条件,以及写入只读地址时的行为。这里采用同一时钟下简单的单请求、单响应接口。

accept=req_valid∧req_ready\mathrm{accept}=\mathrm{req\_valid}\land\mathrm{req\_ready}

下列地址为按字节编址,并采用 32 位对齐。每个请求准确生成一个成功或错误响应。

地址名称行为
0x0CONFIG可读写,应用字节选通
0x4STATUS只读,返回接受请求时的值
0x8COMMAND读取为 0,写入 byte 0 的 bit 0 时产生 start 脉冲
其他未定义错误响应,不改变状态

响应槽为空或即将腾空的边沿才接受

SystemVerilog
module register_interface (
    input  logic        clk, rst,
    input  logic        req_valid, req_write,
    output logic        req_ready,
    input  logic [3:0]  req_addr,
    input  logic [31:0] req_wdata,
    input  logic [3:0]  req_wstrb,
    output logic        rsp_valid,
    input  logic        rsp_ready,
    output logic [31:0] rsp_rdata,
    output logic        rsp_error,
    input  logic [31:0] status_value,
    output logic [31:0] config_value,
    output logic        start_pulse
);
    assign req_ready = !rsp_valid || rsp_ready;
    always_ff @(posedge clk) begin
        if (rst) begin
            rsp_valid    <= 1'b0;
            config_value <= 32'd0;
            start_pulse  <= 1'b0;
        end else begin
            start_pulse <= 1'b0;
            if (req_ready) begin
                rsp_valid <= req_valid;
                if (req_valid) begin
                    rsp_rdata <= 32'd0;
                    rsp_error <= 1'b0;
                    case (req_addr)
                        4'h0: begin
                            if (req_write) begin
                                for (int i=0; i<4; i++)
                                    if (req_wstrb[i])
                                        config_value[8*i +: 8]
                                            <= req_wdata[8*i +: 8];
                            end else rsp_rdata <= config_value;
                        end
                        4'h4: begin
                            if (req_write) rsp_error <= 1'b1;
                            else rsp_rdata <= status_value;
                        end
                        4'h8: begin
                            if (req_write)
                                start_pulse <= req_wstrb[0] && req_wdata[0];
                        end
                        default: rsp_error <= 1'b1;
                    endcase
                end
            end
        end
    end
endmodule

响应受阻时 req_ready=0,因此配置写入和命令脉冲不会重复执行。已接受请求的副作用可能已经发生,只是响应仍在等待。若仅因响应延迟就无条件重发请求,命令可能重复执行。

计算字节选通的含义

CONFIG=32'h11223344 时,写入 req_wdata=32'hAABBCCDD、req_wstrb=4'b0101,只有 byte 0 与 byte 2 改变,结果为 32'h11BB33DD。应分别确认地址对齐、位位置与存储器字节顺序。wstrb=0000 的写入生成成功响应,但不改变数值。

从 MSBMSB 权重最高的比特。其索引取决于向量声明方向,不能总认为它是编号最大的位。了解更多 起依次为 byte3、2、1、0。strobe=0101 选择 byte2 与 byte0,因此只写入 BB 和 DD。strobe 的每一位控制一个字节写使能,而非只控制一个数据比特。

只修改字节选通选中的字节
  1. 旧 CONFIG: 11 | 22 | 33 | 44
  2. 写入数据: AA | BB | CC | DD
  3. strobe 0101: 保持 | 替换 | 保持 | 替换
  4. 新 CONFIG: 11 | BB | 33 | DD

状态值属于哪个时刻?

STATUS 读取响应保存请求被接受时的 status_value。此后即使响应暂停期间实际 status 改变,rsp_rdata 也必须保持。rsp_valid=1、rsp_ready=0 时,若将组合 status 直接连接到响应,响应内容会变化,违反协议。

连续两个边沿 req_valid 与 req_ready 都为 1,就表示两个不同请求。发送方在接受后应撤销 valid,或更新为下一个请求,不能持续保持同一请求却期待只处理一次。

验证的三个方面

  1. 地址与访问权限:检查有效地址、未对齐地址、STATUS 写入和未定义地址的错误响应与副作用。
  2. 数据选择:穷举四个 strobe 位,确认未使能字节得到保留。
  3. 流量控制:即使阻塞响应多个周期,响应与状态也应保持;响应消费与下一请求接受重叠时,事务计数仍须一致。

自己试试

接受 req_wstrb[0]=1、req_wdata[0]=1 的 COMMAND 写入后,rsp_ready=0 持续三个周期。start_pulse 是否应连续重复三个周期?写 STATUS 可以改变 config_value 吗?

阅读解释

start_pulse 只在接受请求后的一个周期为 1,随后归 0。响应暂停不是重复执行命令的条件。STATUS 写入生成错误响应,不改变 config_value 或其他状态。响应完成前的重试策略也必须由收发双方共同约定。

你的选择适用于此浏览器,可随时在页脚更改。