\documentclass[12pt]{ctexart} % 使用 ctexart 文档类支持中文，12pt 字号
\usepackage[utf8]{inputenc}    % 输入编码，保持兼容性
\usepackage[margin=2.5cm]{geometry} % 设置页边距
\usepackage{graphicx}          % 导入图片
\usepackage{amsmath}           % 支持数学公式
\usepackage{listings}          % 代码块高亮
\usepackage{xcolor}            % 用于代码高亮颜色
\usepackage{hyperref}          % 目录、交叉引用可点击，生成PDF书签
\hypersetup{
    colorlinks=true,   % 这是关键，它会让链接文本以颜色显示，而不是边框
    linkcolor=black,   % 内部链接（如目录、章节引用）的颜色设为黑色
    citecolor=green,   % 引用文献的颜色（如果用不到可以忽略或设为黑色）
    urlcolor=blue,     % URL链接的颜色（如果用不到可以忽略或设为黑色）
    filecolor=magenta, % 文件链接的颜色（如果用不到可以忽略或设为黑色）
    % 可以添加更多其他 PDF 元数据，让 PDF 文件信息更完整
    pdftitle={实验四：总线接口设计与实现},
    pdfauthor={朱梓涵},
    pdfsubject={AXI4-Lite 总线协议设计与实现报告},
    pdfkeywords={RISC-V, CPU, Chisel, AXI4-Lite, 总线, 实验报告}
}
        % 目录、交叉引用可点击，生成PDF书签
\usepackage{fancyhdr}          % 自定义页眉页脚
\usepackage{enumitem}          % 列表项自定义
\usepackage{ifthen}            % 条件判断（用于图片占位）

% --- 图片缺失占位宏 ---
\newcommand{\includegraphicsorplaceholder}[2][]{%
    \IfFileExists{#2}{\includegraphics[#1]{#2}}{\fbox{\parbox[c][0.2\textheight][c]{0.9\textwidth}{\centering Missing image: #2}}}%
}

% --- 页眉页脚设置 ---
\pagestyle{fancy}
\fancyhf{} % 清除所有页眉页脚字段
\fancyhead[L]{\MakeUppercase{实验四：总线接口设计与实现}} % 左侧页眉：大写实验名称
\fancyfoot[C]{\thepage} % 居中页脚：页码
\renewcommand{\headrulewidth}{0.4pt} % 页眉下方的横线粗细
\renewcommand{\footrulewidth}{0.4pt} % 页脚上方的横线粗细
% 解决 fancyhdr 提示的 \headheight 偏小问题
\setlength{\headheight}{15pt}

% --- 标题信息 ---
\title{\vspace{-2cm}\textbf{实验四：总线接口设计与实现}} % 标题，垂直间距调整
\author{朱梓涵 \ 学号：24325356} % 作者信息
\date{\today} % 显示当前日期

% --- 代码高亮风格定义 (Solarized-light) ---
\definecolor{sol-base03}{HTML}{002b36}
\definecolor{sol-base02}{HTML}{073642}
\definecolor{sol-base01}{HTML}{586e75}
\definecolor{sol-base00}{HTML}{657b83}
\definecolor{sol-base0}{HTML}{839496}
\definecolor{sol-base1}{HTML}{93a1a1}
\definecolor{sol-base2}{HTML}{eee8d5}
\definecolor{sol-base3}{HTML}{fdf6e3}
\definecolor{sol-yellow}{HTML}{b58900}
\definecolor{sol-orange}{HTML}{cb4b16}
\definecolor{sol-red}{HTML}{dc322f}
\definecolor{sol-magenta}{HTML}{d33682}
\definecolor{sol-violet}{HTML}{6c71c4}
\definecolor{sol-blue}{HTML}{268bd2}
\definecolor{sol-cyan}{HTML}{2aa198}
\definecolor{sol-green}{HTML}{859900}

\lstdefinestyle{ScalaChiselStyle}{
    commentstyle=\color{sol-base01}\itshape,
    keywordstyle=\color{sol-green}\bfseries,
    stringstyle=\color{sol-cyan},
    basicstyle=\ttfamily\small,
    breakatwhitespace=false,
    breaklines=true,
    captionpos=b,
    keepspaces=true,
    numbers=none,
    showspaces=false,
    showstringspaces=false,
    showtabs=false,
    tabsize=2,
    frame=single,
    rulecolor=\color{black},
    % 添加 Chisel 相关关键字
    morekeywords={when, Mux, MuxLookup, IndexedSeq, U, io, :=, object, val, def, class, override, package, import, extends, with, Bits, UInt, SInt, elsewhen, otherwise, Wire, Bool, RegInit, asSInt, asUInt, switch, is, ChiselEnum, Value},
    literate={:}{{\color{sol-base02}:}}1
}

\lstset{style=ScalaChiselStyle} % 默认代码风格为 Scala/Chisel

% --- 图片计数器与章节联动 ---
\counterwithin{figure}{section}
\counterwithin{table}{section}

% --- 文档开始 ---
\begin{document}

\maketitle % 生成标题
\thispagestyle{empty} % 标题页无页码

% --- 正文开始 ---

\section{实验目的}
本实验的主要目的是：
\begin{enumerate}[label=\arabic*.]
    \item 理解 AXI4-Lite 总线协议的基本原理和通信机制。
    \item 学习使用状态机实现总线协议。
    \item 掌握主从设备之间的握手通信过程。
    \item 理解 MMIO（Memory-Mapped I/O）的工作原理。
    \item 将总线协议集成到流水线 CPU 中。
\end{enumerate}

\section{实验环境}
\begin{itemize}
    \item \textbf{操作系统}: Windows 11
    \item \textbf{开发工具}: IntelliJ IDEA
    \item \textbf{构建工具}: SBT
    \item \textbf{仿真与测试}: Verilator, chiseltest
\end{itemize}

\section{实验原理}

\subsection{AXI4-Lite 协议概述}
AXI4-Lite 是总线协议的简化版本。它包含 5 个独立的通道：
\begin{itemize}
    \item \textbf{读地址通道（AR）}：主机发送读地址。
    \item \textbf{读数据通道（R）}：从机返回读取的数据。
    \item \textbf{写地址通道（AW）}：主机发送写地址。
    \item \textbf{写数据通道（W）}：主机发送写数据。
    \item \textbf{写响应通道（B）}：从机返回写操作响应。
\end{itemize}

\subsection{通信框架}
本实验采用的通信框架如下：
\begin{itemize}
    \item \textbf{CPU 侧}：通过 \texttt{AXI4LiteMasterBundle} 接口发起读写请求。
    \item \textbf{AXI4LiteMaster}：将简单的读写请求转换为符合 AXI4-Lite 协议的信号。
    \item \textbf{AXI4LiteChannels}：5 个通道的信号线，符合 AXI4-Lite 规范。
    \item \textbf{AXI4LiteSlave}：接收 AXI4-Lite 协议信号，转换为设备可理解的读写操作。
    \item \textbf{设备侧}：通过 \texttt{AXI4LiteSlaveBundle} 接口响应读写请求。
\end{itemize}

\subsection{握手机制}
AXI4-Lite 协议采用 VALID/READY 握手机制：
\begin{itemize}
    \item 发送方通过 \texttt{VALID} 信号表示数据有效。
    \item 接收方通过 \texttt{READY} 信号表示准备接收。
    \item 只有当 \texttt{VALID} 和 \texttt{READY} 同时为高时，握手完成，数据传输成功。
\end{itemize}

\section{模块实现与分析}

\subsection{状态机设计}
本实验使用状态机实现 AXI4-Lite 协议。定义了以下状态：
\begin{lstlisting}[caption={状态定义}]
object AXI4LiteStates extends ChiselEnum {
  val Idle, ReadAddr, ReadDataWait, ReadData, 
      WriteAddr, WriteData, WriteResp = Value
}
\end{lstlisting}

\subsection{AXI4LiteMaster 实现}

\subsubsection{主机状态机逻辑}
\begin{enumerate}
    \item \textbf{Idle 状态}：等待来自 CPU 的读写请求。收到读请求时，保存地址并转到 \texttt{ReadAddr} 状态；收到写请求时，保存地址和数据并转到 \texttt{WriteAddr} 状态。
    \item \textbf{ReadAddr 状态}：拉高 \texttt{ARVALID}，发送读地址 \texttt{ARADDR}。等待从机 \texttt{ARREADY} 信号，握手完成后，拉高 \texttt{RREADY}，转到 \texttt{ReadData} 状态。
    \item \textbf{ReadData 状态}：保持 \texttt{RREADY} 为高，等待从机 \texttt{RVALID}。收到 \texttt{RVALID} 时，锁存 \texttt{RDATA}，拉高 \texttt{read_valid} 一个周期，通知 CPU 读取完成，随后返回 \texttt{Idle} 状态。
    \item \textbf{WriteAddr 状态}：拉高 \texttt{AWVALID}，发送写地址 \texttt{AWADDR}。等待从机 \texttt{AWREADY} 信号，握手完成后，拉高 \texttt{WVALID}，转到 \texttt{WriteData} 状态。
    \item \textbf{WriteData 状态}：保持 \texttt{WVALID} 为高，发送 \texttt{WDATA} 和 \texttt{WSTRB}。等待从机 \texttt{WREADY} 信号，握手完成后，拉高 \texttt{BREADY}，转到 \texttt{WriteResp} 状态。
    \item \textbf{WriteResp 状态}：保持 \texttt{BREADY} 为高，等待从机 \texttt{BVALID}。收到 \texttt{BVALID} 时，拉高 \texttt{write_valid} 一个周期，随后返回 \texttt{Idle} 状态。
\end{enumerate}

\subsubsection{关键代码实现}
\begin{lstlisting}[caption={主机状态机核心代码}, label={lst:master_core}]
switch(state) {
  is(AXI4LiteStates.Idle) {
    when(io.bundle.read) {
      addr := io.bundle.address
      state := AXI4LiteStates.ReadAddr
      ARVALID := true.B
    }.elsewhen(io.bundle.write) {
      addr := io.bundle.address
      write_data := io.bundle.write_data
      write_strobe := io.bundle.write_strobe
      state := AXI4LiteStates.WriteAddr
      AWVALID := true.B
    }
  }
}
\end{lstlisting}

此外，当主机不在 \texttt{Idle} 状态时，\texttt{busy} 信号为高，拒绝新的请求：
\begin{lstlisting}
io.bundle.busy := state =/= AXI4LiteStates.Idle
\end{lstlisting}
且 \texttt{valid} 信号在状态机执行前清零，确保只持续一个周期：
\begin{lstlisting}
when(read_valid) { read_valid := false.B }
when(write_valid) { write_valid := false.B }
\end{lstlisting}

\subsection{AXI4LiteSlave 实现}

\subsubsection{从机状态机逻辑}
\begin{enumerate}
    \item \textbf{Idle 状态}：清除所有控制信号。优先响应读请求（\texttt{ARVALID}），收到时保存地址，拉高 \texttt{ARREADY}，转到 \texttt{ReadAddr}。收到写请求时，保存地址，拉高 \texttt{AWREADY}，转到 \texttt{WriteAddr}。
    \item \textbf{ReadAddr 状态}：拉低 \texttt{ARREADY}，拉高 \texttt{read} 信号通知设备读取数据，转到 \texttt{ReadData} 状态。
    \item \textbf{ReadData 状态}：保持 \texttt{read} 为高，等待设备 \texttt{read_valid}。收到时锁存 \texttt{read_data} 到 \texttt{rdataReg}，拉高 \texttt{RVALID}，等待主机 \texttt{RREADY}。握手完成后返回 \texttt{Idle} 状态。
    \item \textbf{WriteAddr 状态}：拉低 \texttt{AWREADY}，等待主机 \texttt{WVALID}。收到写数据后，锁存数据和写选通，拉高 \texttt{WREADY} 和 \texttt{write}，转到 \texttt{WriteData}。
    \item \textbf{WriteData 状态}：拉低 \texttt{WREADY} 和 \texttt{write}，拉高 \texttt{BVALID}，转到 \texttt{WriteResp}。
    \item \textbf{WriteResp 状态}：保持 \texttt{BVALID} 为高，等待主机 \texttt{BREADY}。握手完成后返回 \texttt{Idle} 状态。
\end{enumerate}

\subsubsection{关键代码实现}
\begin{lstlisting}[caption={从机状态机核心代码}, label={lst:slave_core}]
switch(state) {
  is(AXI4LiteStates.Idle) {
    when(io.channels.read_address_channel.ARVALID) {
      addr := io.channels.read_address_channel.ARADDR
      ARREADY := true.B
      state := AXI4LiteStates.ReadAddr
    }.elsewhen(io.channels.write_address_channel.AWVALID) {
      addr := io.channels.write_address_channel.AWADDR
      AWREADY := true.B
      state := AXI4LiteStates.WriteAddr
    }
  }
}
\end{lstlisting}

使用寄存器保证 \texttt{RDATA} 在 \texttt{RVALID} 为高时保持稳定：
\begin{lstlisting}
val rdataReg = RegInit(0.U(dataWidth.W))
io.channels.read_data_channel.RDATA := rdataReg
\end{lstlisting}

\subsection{性能优化}
本实现采用了以下优化策略：
\begin{enumerate}
    \item \textbf{流水化握手}：在地址握手完成后立即准备数据握手，减少等待周期。
    \item \textbf{优先级处理}：从机优先响应读请求，提高取指效率。
    \item \textbf{信号稳定性}：使用寄存器锁存关键数据，避免毛刺。
\end{enumerate}

\section{CSR 指令与总线交互}
CSR 指令在总线协议中的交互主要体现在 MMIO（Memory-Mapped I/O）上。CPU 通过地址映射访问 CSR 寄存器或外设寄存器：
\begin{itemize}
    \item 读写 CSR 时，控制单元发出相应的读写请求。
    \item AXI4-Lite Master 接收请求，将地址和数据转换为总线事务。
    \item AXI4-Lite Slave 根据地址将请求路由到具体的 CSR 模块或外设。
    \item 通过握手机制，确保数据传输的正确性和稳定性。
\end{itemize}

\section{测试结果与分析}

\subsection{测试原理}
\texttt{BusTest.scala} 包含多个测试用例，验证 AXI4-Lite 实现的正确性：
\begin{itemize}
    \item \textbf{FunctionalTest}：创建 \texttt{TestBox} 模块，模拟主从机忙碌状态，验证读写事务的地址、数据、选通信号及 \texttt{valid} 信号时序。
    \item \textbf{连续事务测试}：随机生成 1000 个读写事务，模拟从机忙碌状态，验证高负载下的总线稳定性。
    \item \textbf{其他测试}：包括 \texttt{TimerTest}（定时器）、\texttt{MemoryTestF}（内存）和 \texttt{ROMLoaderTestF}（ROM 加载）。
\end{itemize}

\subsection{分析}
\begin{enumerate}
    \item \textbf{正确性验证}：所有测试用例通过，说明实现符合 AXI4-Lite 协议规范。数据传输正确，地址、数据、选通信号及 \texttt{valid} 信号时序均符合预期。
    \item \textbf{性能分析}：单次读写事务的握手周期符合设计预期（约 3-4 周期）。连续事务测试证明了总线在高负载下的可靠性。
\end{enumerate}

\section{改进建议}
\begin{enumerate}[label=\arabic*.]
    \item \textbf{建议：提供更多调试案例和方法指导。}
    
    建议增加具体的调试案例，例如如何追踪一条指令在总线中的完整传输过程，如何分析波形图定位握手失败问题等。

    \item \textbf{建议：增加可视化工具。}
    
    建议提供或推荐一些工具，能够将总线上的信号交互以图形化方式展示，辅助理解握手过程。
\end{enumerate}

\section{实验结论}
通过本次实验，我深入理解了 AXI4-Lite 总线协议的工作原理，掌握了使用状态机实现复杂通信协议的方法。我成功实现了：
\begin{itemize}
    \item 符合 AXI4-Lite 规范的主机和从机模块。
    \item 基于 VALID/READY 握手机制的通信流程。
    \item 完善的测试用例，验证了总线的正确性和稳定性。
\end{itemize}

本次实验不仅提升了我的硬件设计能力，也让我对计算机系统中各模块间的互连和通信有了更深刻的认识，为后续更复杂的系统设计打下了坚实基础。

\end{document}