当前位置: 首页 > ai >正文

Avalon-MM协议

在 Intel(原 Altera)FPGA 的设计流程中,如果使用 Qsys / Platform Designer 搭建系统,模块之间的互连往往会通过 Avalon-MM(Avalon Memory-Mapped) 协议完成。它类似于 Xilinx 的 AXI-Lite 协议,用于内存映射(Memory-Mapped)方式访问外设寄存器或存储器。

接口

信号名方向(主机视角)作用
addressO访问的目标地址
readO读请求信号(1 表示发起一次读)
writeO写请求信号(1 表示发起一次写)
writedataO写数据
readdataI从机返回的读数据
waitrequestI从机忙信号(1 表示不能接收新请求)
readdatavalidI从机读数据有效标志(1 表示 readdata 有效)

时序流程

写操作(Write)

  1. Master 拉高 write 并提供 addresswritedata
    主机在总线上给出目标地址和写入数据,同时拉高 write 信号。
  2. 等待从机 waitrequest=0 表示接受
    从机通过 waitrequest 信号告诉主机当前是否能接受请求,只有当该信号为 0 时,请求才会被采纳。
  3. 可选:无返回数据,只有写完成确认
    Avalon-MM 的写操作通常没有返回数据,只是确认事务完成。
    注:你给的例子中,写完成后直接进入读流程。

读操作(Read)

  1. Master 拉高 read 并提供 address
    主机在总线上给出目标地址,同时拉高 read 信号。
  2. 等待 waitrequest=0 表示接受请求
    当从机将 waitrequest 拉低时,表示读请求已被采纳。
  3. 如果 USE_RDDV=1,等待 readdatavalid=1 再取 readdata
    表示从机需要额外的周期准备数据,数据有效时 readdatavalid 会拉高。
  4. 如果 USE_RDDV=0,在 waitrequest=0 的同一拍直接取 readdata
    表示数据在接受请求的同时就已经准备好,可以直接读取。

avalon_mm_master.v

// =====================================================
// Avalon-MM 主机(演示)
// - start=1 触发:先写 address_w <- data_w
//   再读 address_r,等待数据返回(支持有/无 readdatavalid 模式)
// - done=1 完成;error=1 表示读回值 != 期望
// - 可综合(演示控制用)
// =====================================================
module avalon_mm_master #(parameter integer ADDR_WIDTH = 8,parameter integer DATA_WIDTH = 32,parameter integer USE_RDDV   = 1   // 与从机保持一致
)(input  wire                       clk,input  wire                       reset_n,// 控制/配置input  wire                       start,input  wire [ADDR_WIDTH-1:0]      address_w,input  wire [ADDR_WIDTH-1:0]      address_r,input  wire [DATA_WIDTH-1:0]      data_w,input  wire [(DATA_WIDTH/8)-1:0]  byteenable,// 结果output reg                        done,output reg                        error,output reg  [DATA_WIDTH-1:0]      read_data_out,// Avalon-MM Master 端口(官方命名)output reg  [ADDR_WIDTH-1:0]      address,output reg                        read,output reg                        write,output reg  [DATA_WIDTH-1:0]      writedata,input  wire [DATA_WIDTH-1:0]      readdata,input  wire                       waitrequest,input  wire                       readdatavalid
);// 状态机(Verilog-2001 风格)localparam S_IDLE            = 3'd0;localparam S_WRITE_ADDR      = 3'd1;localparam S_WRITE_WAIT      = 3'd2;localparam S_READ_ADDR       = 3'd3;localparam S_READ_WAIT_ACC   = 3'd4;localparam S_READ_WAIT_DATA  = 3'd5;localparam S_DONE            = 3'd6;reg [2:0] state, nxt;// 输出默认组合逻辑always @(*) begin// 默认拉低read      = 1'b0;write     = 1'b0;address   = '0;writedata = '0;case (state)S_WRITE_ADDR: beginaddress   = address_w;writedata = data_w;write     = 1'b1; // 等待 waitrequest=0 接受endS_READ_ADDR: beginaddress = address_r;read    = 1'b1;   // 等待 waitrequest=0 接受enddefault: ;endcaseend// 状态转移always @(*) beginnxt = state;case (state)S_IDLE:          nxt = (start ? S_WRITE_ADDR : S_IDLE);S_WRITE_ADDR:    nxt = (waitrequest ? S_WRITE_ADDR : S_WRITE_WAIT);S_WRITE_WAIT:    nxt = S_READ_ADDR;S_READ_ADDR:     nxt = (waitrequest ? S_READ_ADDR : S_READ_WAIT_ACC);S_READ_WAIT_ACC: nxt = (USE_RDDV!=0) ? S_READ_WAIT_DATA : S_DONE; // 无RDDV则接受拍即得数据S_READ_WAIT_DATA:nxt = (readdatavalid ? S_DONE : S_READ_WAIT_DATA);S_DONE:          nxt = S_IDLE;default:         nxt = S_IDLE;endcaseend// 时序寄存reg [DATA_WIDTH-1:0] expect;  // 期望读回always @(posedge clk) beginif (!reset_n) beginstate         <= S_IDLE;done          <= 1'b0;error         <= 1'b0;read_data_out <= '0;expect        <= '0;end else beginstate <= nxt;if (state == S_IDLE && start) beginexpect <= data_w;done   <= 1'b0;error  <= 1'b0;end// 无 readdatavalid 模式:在接受拍读取if ((state == S_READ_ADDR) && !waitrequest && (USE_RDDV==0)) beginread_data_out <= readdata;done          <= 1'b1;error         <= (readdata != expect);end// 有 readdatavalid 模式:在 rddv 上升拍读取if ((state == S_READ_WAIT_DATA) && readdatavalid) beginread_data_out <= readdata;done          <= 1'b1;error         <= (readdata != expect);endendend
endmodule

avalon_mm_slavev.v

// =====================================================
// Avalon-MM 从机(内存映射 RAM 示例)
// - 可综合
// - 支持 byteenable 局部写
// - 可配置读延迟 LATENCY (0=零延迟)
// - USE_RDDV=1 时输出 readdatavalid;=0 时在接受读的同拍给数据
// - waitrequest:只在读延迟期间拉高(写不阻塞)
// =====================================================
module avalon_mm_slave #(parameter integer ADDR_WIDTH  = 8,    // 字地址(每地址一字)parameter integer DATA_WIDTH  = 32,parameter integer DEPTH_WORDS = 256,parameter integer LATENCY     = 2,    // 读延迟拍数parameter integer USE_RDDV    = 1     // 1: 使能 readdatavalid
)(input  wire                       clk,input  wire                       reset_n,       // 低有效复位(常见用法)// Avalon-MM 接口(官方命名)input  wire [ADDR_WIDTH-1:0]      address,input  wire                       read,input  wire                       write,input  wire [DATA_WIDTH-1:0]      writedata,input  wire [(DATA_WIDTH/8)-1:0]  byteenable,output reg  [DATA_WIDTH-1:0]      readdata,output wire                       waitrequest,output reg                        readdatavalid
);localparam integer BE_W = (DATA_WIDTH/8);reg [DATA_WIDTH-1:0] mem [0:DEPTH_WORDS-1];// 读延迟计数器localparam CNT_W = (LATENCY==0) ? 1 : $clog2(LATENCY+1);reg [CNT_W-1:0] rd_cnt;wire rd_inflight = (LATENCY != 0) ? (rd_cnt != 0) : 1'b0;// 只有读延迟期间阻塞;接受读地址后才进入延迟阶段assign waitrequest = (read && rd_inflight);// 写:byteenable 局部写(不阻塞)integer b;always @(posedge clk) beginif (!reset_n) begin// 不清 RAM,保持综合可用end else if (write && !waitrequest) beginfor (b = 0; b < BE_W; b = b + 1) beginif (byteenable[b]) beginmem[address][8*b +: 8] <= writedata[8*b +: 8];endendendend// 读:可配置延迟/是否使用 readdatavalidreg [ADDR_WIDTH-1:0] r_addr;always @(posedge clk) beginif (!reset_n) beginrd_cnt        <= '0;readdata      <= '0;readdatavalid <= 1'b0;end else beginreaddatavalid <= 1'b0;// 地址被接受(!waitrequest)时启动读if (read && !waitrequest) beginr_addr <= address;if (LATENCY == 0) beginreaddata      <= mem[address];readdatavalid <= (USE_RDDV != 0) ? 1'b1 : 1'b0;end else beginrd_cnt <= LATENCY[CNT_W-1:0];endend else if (rd_inflight) beginrd_cnt <= rd_cnt - 1'b1;if (rd_cnt == 1) beginreaddata      <= mem[r_addr];readdatavalid <= (USE_RDDV != 0) ? 1'b1 : 1'b0;endendendend
endmodule

tb.sv

// =====================================================
// Testbench:Avalon-MM 主从互连仿真
// - 从机:LATENCY=2,USE_RDDV=1(输出 readdatavalid)
// - 主机:写0x12_34_56_78到地址0x10,再从地址0x10读回并校验
// =====================================================
`timescale 1ns/1psmodule tb;localparam ADDR_W   = 8;localparam DATA_W   = 32;localparam CLK_T    = 10; // 100MHz// 时钟/复位reg clk = 0;always #(CLK_T/2) clk = ~clk;reg reset_n;initial beginreset_n = 0;repeat(5) @(posedge clk);reset_n = 1;end// 主机配置/控制reg                      start;reg [ADDR_W-1:0]         address_w;reg [ADDR_W-1:0]         address_r;reg [DATA_W-1:0]         data_w;reg [(DATA_W/8)-1:0]     byteenable;wire                     done, error;wire [DATA_W-1:0]        read_data_out;// 互连总线wire [ADDR_W-1:0]        address;wire                     read, write;wire [DATA_W-1:0]        writedata;wire [DATA_W-1:0]        readdata;wire                     waitrequest;wire                     readdatavalid;// DUTsavalon_mm_master #(.ADDR_WIDTH (ADDR_W),.DATA_WIDTH (DATA_W),.USE_RDDV   (1)) u_master (.clk           (clk),.reset_n       (reset_n),.start         (start),.address_w     (address_w),.address_r     (address_r),.data_w        (data_w),.byteenable    (byteenable),.done          (done),.error         (error),.read_data_out (read_data_out),// Avalon-MM.address       (address),.read          (read),.write         (write),.writedata     (writedata),.readdata      (readdata),.waitrequest   (waitrequest),.readdatavalid (readdatavalid));avalon_mm_slave #(.ADDR_WIDTH  (ADDR_W),.DATA_WIDTH  (DATA_W),.DEPTH_WORDS (256),.LATENCY     (2),   // 读延迟2拍.USE_RDDV    (1)    // 输出 readdatavalid) u_slave (.clk           (clk),.reset_n       (reset_n),.address       (address),.read          (read),.write         (write),.writedata     (writedata),.byteenable    (byteenable),.readdata      (readdata),.waitrequest   (waitrequest),.readdatavalid (readdatavalid));// 激励initial beginstart      = 0;address_w  = '0;address_r  = '0;data_w     = '0;byteenable = {DATA_W/8{1'b1}}; // 全字节有效@(posedge reset_n);@(posedge clk);// 写→读回一组address_w = 8'h10;address_r = 8'h10;data_w    = 32'h12_34_56_78;$display("[%0t] TB: kick", $time);start = 1;@(posedge clk);start = 0;// 等完成wait(done);$display("[%0t] TB: done=1, read=0x%08x, error=%0d",$time, read_data_out, error);// 再来一组(验证 byteenable 半字写)repeat(5) @(posedge clk);address_w  = 8'h20;address_r  = 8'h20;data_w     = 32'hAB_CD_EF_00;   // 先写全字byteenable = 4'b1111;start = 1; @(posedge clk); start = 0;wait(done);$display("[%0t] TB: pass1 read=0x%08x, err=%0d",$time, read_data_out, error);// 半字更新(高16位),期望=0x1234_EF00repeat(5) @(posedge clk);address_w  = 8'h20;address_r  = 8'h20;data_w     = 32'h12_34_00_00;byteenable = 4'b1100;start = 1; @(posedge clk); start = 0;wait(done);$display("[%0t] TB: pass2 read=0x%08x, err=%0d",$time, read_data_out, error);$display("[%0t] TB: finished", $time);#50 $finish;endendmodule
http://www.xdnf.cn/news/17660.html

相关文章:

  • MySQL 到 ClickHouse 明细分析链路改造:数据校验、补偿与延迟治理
  • React常见的Hooks
  • 华为认证的HCIE是永久的吗?
  • 使用TexLive与VScode排版论文
  • Verilog功能模块--SPI主机和从机(02)--SPI主机设计思路与代码解析
  • PyTorch基础(使用TensorFlow架构)
  • Deep Agents:用于复杂任务自动化的 AI 代理框架
  • Debian 网络服务管理的深度解析:传统与现代工具的碰撞
  • 肖臻《区块链技术与应用》第十二讲:比特币是匿名的吗?—— 深入解析匿名性、隐私风险与增强技术
  • VBS 时间函数
  • Redis命令大全
  • 调整UOS在VMware中的分辨率
  • 肖臻《区块链技术与应用》第九讲:比特币交易的“智能”核心:深入解析脚本语言Script
  • Windows已经安装了一个MySQL8,通过修改配置文件的端口号跑2个或多个Mysql服务方法,并注册为系统服务
  • 08--深入解析C++ list:高效操作与实现原理
  • DeepSeek-R1-0528 推理模型完整指南:领先开源推理模型的运行平台与选择建议
  • Android性能优化:架构层面的性能考量
  • Web 服务详解:HTTP 与 HTTPS 配置
  • 超详细!VMware12 安装win7操作系统
  • Linux下命名管道和共享内存
  • 邦纳BANNER相机视觉加镜头PresencePLUSP4 RICOH FL-CC2514-2M工业相机
  • 腾讯codebuddy.ai 安装实测【从零开始开发在线五子棋游戏:完整开发记录】
  • iceberg FlinkSQL 特性
  • QT(概述、基础函数、界面类、信号和槽)
  • 【SpringBoot】08 容器功能 - SpringBoot底层注解汇总大全
  • 《汇编语言:基于X86处理器》第13章 高级语言接口(2)
  • __base__属性
  • [ Mybatis ] 框架搭建与数据访问
  • 【Android】【bug】Json解析错误Expected BEGIN_OBJECT but was STRING...
  • Qt——信号和槽