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

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.lryc.cn/news/619663.html

相关文章:

  • 浅层神经网络
  • SimD小目标样本分配方法
  • 开发避坑指南(24):RocketMQ磁盘空间告急异常处理,CODE 14 “service not available“解决方案
  • 设计原则之【抽象层次一致性(SLAP)】,方法也分三六九等
  • 从零到一:TCP 回声服务器与客户端的完整实现与原理详解
  • Linux LNMP配置全流程
  • 机器学习之词向量转换
  • 第5章 学习的机制
  • 对比学习中核心损失函数的发展脉络
  • AI服务器需求激增,三星内存与SSD供不应求,HBM与DDR5成关键驱动力
  • 2025年高效能工程项目管理软件推荐榜单:AI重构工程进度可视化与资源动态调度体系
  • kernel pwn 入门(四) ret2dir详细
  • 《嵌入式Linux应用编程():Linux Framebuffer图形编程》
  • Win11和Mac设置环境变量
  • 机器学习阶段性总结:对深度学习本质的回顾 20250813
  • Html5-canvas动态渐变背景
  • mac 安卓模拟器 blueStacks
  • MacOS字体看起来比在 Windows 上更好?
  • 367. 有效的完全平方数
  • Spring Boot + MyBatis
  • Python 元类基础:从理解到应用的深度解析
  • [CSCCTF 2019 Qual]FlaskLight
  • [AI React Web] 包与依赖管理 | `axios`库 | `framer-motion`库
  • Spring cloud集成ElastictJob分布式定时任务完整攻略(含snakeyaml报错处理方法)
  • 使用TexLive与VScode排版论文
  • 从0开始配置conda环境并在PyCharm中使用
  • Node.js浏览器引擎+Python大脑的智能爬虫系统
  • 低成本扩展方案:S7-200SMART作为S7-1500分布式IO从站的上位机配置指南
  • Linux网络性能调优终极指南:深度解析与实践
  • 初识c语言————排序方法