基于AHB-APB BUS slave详解

1.目录

  • 高内聚:让模块的功能更集中,更单一。
  • AMBA总线例子,需要有一个模块和AMBA进行交互,就可以单独将与AHB总线进行交互的部分作为一个模块。经常需要一个模块处理ahb信号,可以设置ahb_slave_if.v模块
  • 轻耦合,两个模块之间的交互信号比较简单

2.模块描述

*** 寄存器配置种类:第一类,config(Master配置到slave),操作数和操作模式,比如图像处理器中的图像规格;第二类,启动信号;第三类,状态寄存器,当IP完成任务或者出现错误的时候,更新模块的状态。**

3.设计划分

  • Top模块不写逻辑,只进行模块的集成,避免gluelogic产生

3.1 项目目录规划

  • env
  • regression
  • rtl
  • sim
  • sim_ncverilog
  • sim_vcs
  • tb
  • tc

3.1.1 Env

  • Env目录下放置的是一些Interface的接口
  • Interface定义了AHB的一些接口,AHB总线的一些接口是固定的,不同的项目使用相同版本的AHB使用的总线接口是一致的。后续使用的时候可以类似于例化module一样,进行例化AHB
  • Interface是sv中的概念
// interface ahb_if(input logic,input hrestn);

interface ahb_if();

logic		hclk;
logic hrestn;
logic hsel;
logic hwrite;
logic hready;//hready_in
logic [2:0] hsize;
logic [2:0] hburst;
logic [1:0] htrans;
logic [31:0] hwdata;
logic [31:0] haddr; logic hready_resp;
logic [1:0] hresp;
logic [31:0] hrdata; reg [31:0] rdata; // clock generator
initial
begin
hclk = 0;
forver
begin
#10 hclk = ~hclk;
end
end parameter IDLE = 2'b00,
BUSY = 2'b01,
NONSEQ = 2'b10,
SEQ = 2'b11; initial
begin
hrestn = 0;
htrans = IDLE;
hsize = 3'b00;
hburst = 3'b00;
hwrite = 0;
hsel = 0;
hready = 0;
haddr = 0;
#200;
hrestn = 1;
end task ahb_write(input [31:0] addr,input [31:0] wdata);
begin
@(posedge hclk);
#1
hsize = 3'b10;
htrans = NONSEQ;
hwrite = 1;
hsel = 1;
hready = 1;
haddr = addr; @(posedge hclk)
#1
hsize = 2'b00;
htrans = IDLE;
hwrite = 0;
hsel = 0;
hwdata = wdata; @(posedge hclk);
#1
haddr = 32'b0;
@(posedge hclk);
end
endtask task ahb_read(input [31:0] addr,output [31:0] rdata);
begin
@(posedge hclk);
#1
haddr = addr;
hsize = 2'b10;
htrans = NONSEQ;
hwrite = 0;
hsel = 1; @(posedge hclk);
#1
hsize = 2'b00;
htrans = IDLE;
hwrite = 0;
hsel = 0; @(posedge hclk)
rdata = hrdata;
haddr = 32'b0;
@(posedge hclk); end
endtask endinterface

3.1.2 regression

  • regression中放置一个脚本,将许多testcase同过脚本进行管理
  • 在项目中后期的时候,每修改一次代码,都要跑一下regression

3.1.3 RTL







  1. 顶层模块,ahb_slave_clac.v

    hready

    *以AHB lite为例,只有一个Master,所以不需要Arbiter,有多个slave



  • 假设addr1对应slave1,addr2对应slave2。假设T0上升沿将地址addr1驱动到总线上,T1时候,slave1的hready_out是拉低的,要进行延迟。在T1上升沿的时候会将下一个地址addr2驱动到总线上。T2上升沿的时候将slave1的hready_out拉高,此时可以将addr1的数据驱动到总线上,但是在T2上升沿时不能驱动addr2的数据的,因为addr1的响应还没有结束。需要在T3上升沿的时候驱动addr2的数据。
  • slave2如何知道salve1的响应时完成的呢,可以将所有的slave的输出hready_out进行与操作(进行与操作这种方式是默认在slave没有被选中的时候,hready_resp默认是拉高的)或者mux,将与之后的信号广播到所有的slave,这个信号就是hready_in
  • 假设T1的时候slave1的hready_out = 0,0与任何信号输出0,hready_in就是0,hready作为slave2的输入,slave2看到hready_in为0的时候,在下一个周期上升沿就不能驱动数据到总线上。只有当slave2输入的hready_in为1的时候,在下一个周期上升沿才能驱动数据到总线上。
  • hready_in的作用就是告诉slave当前总线可以驱动数据
// module ahb_clac_top

module ahb_clac_top (
hclk,
hrestn,
hsel,
hwrite,
hsize,
htrans,
hburst,
hwdata,
haddr, hready_resp,
hresp,
hrdata );
input hclk;
input hrestn;
input hsel;
input hwrite;
input hready;
input [2:0] hsize;
input [2:0] htrans;
input [2:0] hburst;
input [1:0] htrans;
input [31:0]hwdata;
input [7:0] haddr; output hready_resp;
output [1:0] hresp;
output [31:0] hrdata; wire ctrl;
wire [1:0] clac_mode;
wire [31:0] opcode_a;
wire [31:0] opcode_b;
wire [31:0] result; ahb_slave_clac U_slave_if (
.hclk (hclk),
.hsel (hrestn),
.hwrite (hwrite),
.hsize (hsize),
.hready (hready),
.htrans (htrans),
.hburst (hburst),
.hwdata (hwdata),
.haddr (haddr),
.result (result),
.hready_resp (hready_resp),
.hresp (hresp),
.hrdata (hrdata),
.ctrl (ctrl),
.clac_mode (clac_mode),
.opcode_a (opcode_a),
.opcode_b (opcode_b)
); clac U_clac (
.ctrl (ctrl),
.clac_mode (clac_mode),
.opcode_a (opcode_a),
.opcode_b (opcode_b),
.result (result)
); endmodule
  1. 计算模块 clac.v
  • 输入操作数,输入clac_mode(操作符),使能信号;输出result
  • 使能信号下,根据clac_mode进行操作,模块不使能的条件下,恒定输出为0
  • 在书写case语句的时候,需要使用default
  • cass语句能够覆盖所有的情况可以不用写default,最好写default



    注意位宽不匹配的问题
assign a[3:0] = b[7:0]  # 会进行截断
assign a[7:0] = b[3:0] # 综合的时候会报风险
//clac

module clac(
ctrl, // 使能信号
clac_mode,
opcode_a,
opcode_b,
result
); input ctrl;
input [31:0] opcode_a;
input [31:0] opcode_b;
input [1:0] clac_mode; output [31:0] result;
reg [31:0] result; always @(*)
begin
if(ctrl)
case(clac_mode)
2'b00:result = opcode_a & opcode_b;
2'b01:result = opcode_a | opcode_b;
2'b10:result = opcode_a ^ opcode_b;
2'b11:result = opcode_a + opcode_b;
default:result = 32'b0;
endcase
else
result = 32'b0;
end
endmodule
  1. ahb_slave_clac.v
  • 这个模块主要进行接口信号处理,将接口信号的输出,比如运算符和使能信号给计算模块,计算模块返回结果,ahb_slave将计算模块返回的结果作为hrdata返回给ahb总线

    ahb_slave接口模块的设计思路
  • ahb的传输有两个阶段,一个地址阶段,一个数据阶段。
  • AHB\APB\AXI地址都是以byte为单位的。
  • CPU通过总线配置模块中的寄存器,每个寄存器都有自己的地址空间。CPU读到写代码之后,AHB会发起写请求,根据地址找到slave,拉高hsel信号,将数据写到对应地址的寄存器中

  • 在进行设计的时候,需要将两个阶段进行对齐,如果不进行对齐,可能看到地址的时候,数据还没有准备好或者拿到数据的时候,地址已经进行了切换。解决方式就是将控制信号进行打拍的处理。
  • 为什么地址信号需要打一拍,因为AHB是分为两个阶段进行执行的,也就是说数据阶段要滞后地址阶段一个周期,所以将地址haddr打一拍,延迟一个周期,这样地址数据可以和写数据一起到组合逻辑中



  • 打一拍之后的信号是haddr_r,就可以和写数据共同将数据写到寄存器中。
  • 在组合逻辑中会产生什么时候写操作数(opcode_a,opcode_b),什么时候写clac mode,根据地址,判断地址落到哪一个寄存器上,可以将数据写道该寄存器中。

  • 对于读数据,T0时刻时钟上升沿,将haddr驱动到总线上,haddr打一拍之后,T1周期上升沿haddr_r驱动到总线上(相当于将haddr打一拍,沿长一个周期)。在T1周期内有地址和操作信号,经过组合逻辑产生hrdata。

代码

1、先进行打拍处理,将address phaze和data phaze进行对齐

注意:hesel拉高和hready(拉高)表示当前的输入是有效的,hsel拉高表示选择当前的slave,hready拉高表示当前总线可以驱动数据,将ahb信号进行打拍

2、生成读或者是写的操作信号,

3、hready_resp表示能不能再下一个周期能够拉起hready_out

4、写操作,在写信号下,根据地址,判断将写数据给哪个寄存器

5、读操作,在读信号下,根据地址,读取数据

//ahb_slave_clac slave接口模块

module ahb_slave_clac(
// input signals
hclk,
hrestn, //时钟复位信号 hsel,
htrans,
hwrite,
hsize,
hburst,
haddr, //控制信号
hwdata,
hready, // hready_in,所有slave输出的hready_out,经过与门之后广播到所有slave result, // output signals
hready_resp,
hrdata,
hresp, ctrl,
opcode_a, // 配置寄存器信号
opcode_b,
clac_mode ); input hclk;
input hrestn;
input hsel;
input hwrite;
input hready;
input [2:0] hsize;
input [2:0] htrans;
input [2:0] hburst;
input [31:0]hwdata;
input [7:0] haddr;
input [31:0] result; // 要将clac返回的结果作为rdata给总线 output hready_resp;
output [1:0] hresp;
output [31:0] hrdata; // 输出给AHB总线的 output ctrl;
output [1:0] clac_mode;
output [31:0] opcode_a;
output [31:0] opcode_b; // 输出给计算模块的 reg hwrite_r;
reg [2:0] hsize_r;
reg [2:0] hburst_r;
reg [1:0] htrans_r; // addtress phaze阶段的信号打一拍,配置地址和控制信号寄存器
reg [7:0] haddr_r; reg [31:0] hrdata; // 配置读数据寄存器 wire ahb_write;
wire ahb_read; reg enable_r; // 配置clac寄存器,需要CPU进行配置,通过AHB总线传递数据
reg [1:0] ctrl_r;
reg [31:0] opa_r;
reg [31:0] opb_r; // 设置htrans状态参数
parameter IDLE = 2'b00,
BUSY = 2'b01,
NONSEQ = 2'b10,
SEQ = 2'b11; // 设置配置寄存器的地址
parameter ENABLE_ADDR = 8'h00,
CTRL_ADDR = 8'h4,
OPA_ADDR = 8'h08,
OPB_ADDR = 8'h0c,
RESULT_ADDR = 8'h10; // 将address phaze阶段的信号打一拍
always@(posedge hclk or negedge hrestn);
begin
if(!hrestn)
begin
hwrite_r <= 1'b0;
hsize_r <= 2'b0;
hburst_r <= 3'b0;
htrans_r <= 2'b0;
haddr_r <= 8'b0;
end
else if(hready && hsel)
begin
hwrite_r <= hwrite;
hsize_r <= hsize;
hburst_r <= hburst;
htrans_r <= htrans; // 将address phaze数据与data phaze对齐
haddr_r <= haddr;
end
end assign ctrl = enable_r;
assign clac_mode = ctrl_r;
assign opcode_a = opa_r;
assign opcode_b = opb_r; assign hready_resp = 1'b1; // hready_resp 固定为1表示能够随时输出计算结果
assign hresp = 2'b00; // 产生读写数据的控制信号
// 根据AHB传递过来的信号进行读写信号的判断
assign ahb_write = ((htrans_r == NONSEQ)|| (htrans_r == SEQ)) && hwrite_r && hready;
assign ahb_read = ((htrans_r == NONSEQ)|| (htrans_r == SEQ)) && (!hwrite_r) && hready; // 进行写操作,写操作数和操作符和使能寄存器
always @(posedge hclk or negedge hrestn)
begin
if(!hrestn)
begin
enable_r <= 1'b0;;
ctrl_r <= 2'b0;
opa_r <= 16'b0;
opb_r <= 16'b0;
end
else if(ahb_write)
begin
case(haddr_r)
ENABLE_ADDR : enable_r = hwdata[0];
CTRL_ADDR : ctrl_r = hwdata[1:0];
OPA_ADDR : opa_r = hwdata[15:0];
OPB_ADDR : opb_r = hwdata[15:0];
endcase
end
end //进行读操作,读出clac返回的结果
always @(*)
begin
if(ahb_read)
begin
case(haddr_r[7:0])
ENABLE_ADDR :hrdata = {31'b0,enable_r};
CTRL_ADDR :hrdata = {31'b0,ctrl_r};
OPA_ADDR :hrdata = {16'b0,opa_r};
OPB_ADDR :hrdata = {16'b0,opb_r};
RESULT_ADDR :hrdata = result;
default :hrdata = 32'h0;
endcase
end
else
hrdata = 32'h0;
end
endmodule

3.1.4 sim_vcs

存放的是vcs仿真的Makefile文件





3.1. tb

4.总结

1.两阶段对齐

2.产生读写信号

3.配置寄存器(根据寄存器地址写寄存器,在模块当中定义寄存器和寄存器地址)

4.写输出

5.读数据

基于AHB_BUS Clac slave详解的更多相关文章

  1. 基于模型的特征选择详解 (Embedded & Wrapper)

    目录 基于模型的特征选择详解 (Embedded & Wrapper) 1. 线性模型和正则化(Embedded方式) 2. 基于树模型的特征选择(Embedded方式) 3. 顶层特征选择算 ...

  2. MySQL 主从复制:基于二进制文件复制配置详解

    MySQL-主从复制:基于二进制文件复制详解 前言 主从复制是指把一个MySQL的数据库服务器作为主服务器(master),然后把master的数据复制到一个或者多个MySQL数据库服务器作为从服务器 ...

  3. Java基于回调的观察者模式详解

    本文由“言念小文”原创,转载请说明文章出处 一.前言 什么是回调?回调如何使用?如何优雅的使用?本文将首先详解回调的原理,然后介绍回调的基本使用方法,最后介绍基于回调的“观察者模式”实现,演示如何优化 ...

  4. 实战!基于lamp安装wordpress详解-技术流ken

    简介 LAMP 是Linux Apache MySQL PHP的简写,其实就是把Apache, MySQL以及PHP安装在Linux系统上,组成一个环境来运行动态的脚本文件.现在基于lamp搭建wor ...

  5. SpringMVC 基于注解的Controller详解

    本文出处 http://blog.csdn.net/lufeng20/article/details/7598801 概述 继 Spring 2.0 对 Spring MVC 进行重大升级后,Spri ...

  6. 正则表达式基于JavaScript的入门详解

    关于正则表达式,和很多前辈聊起这个知识点时,他们的反馈都比聊其他技术谦逊,而和很多刚入门的程序员讨论时甚至会有觉得你看不起他. 的确,正则表达式从通常的应用来看,的确不难,比如电话,邮箱等验证.语法, ...

  7. Hadoop IO基于文件的数据结构详解【列式和行式数据结构的存储策略】

    Charles所有关于hadoop的文章参考自hadoop权威指南第四版预览版 大家可以去safari免费阅读其英文预览版.本人也上传了PDF版本在我的资源中可以免费下载,不需要C币,点击这里下载. ...

  8. 基于php-fpm的配置详解[转载]

    php自带php-fpm/usr/local/php/etc/php-fpm.confpid = run/php-fpm.pidpid设置,默认在安装目录中的var/run/php-fpm.pid,建 ...

  9. jumpserver v0.4.0 基于 CenOS7 的安装详解

    标签(linux): jumpserver 笔者Q:972581034 交流群:605799367.有任何疑问可与笔者或加群交流 笔者已经弃用Jumpserver,并自已开发了shell跳板机. sh ...

  10. 基于php-fpm的配置详解

    php5.3自带php-fpm/usr/local/php/etc/php-fpm.confpid = run/php-fpm.pidpid设置,默认在安装目录中的var/run/php-fpm.pi ...

随机推荐

  1. 创建定义store并使用组合式api、选项式api

    在项目根目录创建store文件夹(此步骤和vuex相同) 在步骤一的store文件夹下根据不同的用途场景创建单独的store文件(等同于vuex中分模块). 定义store基本步骤 步骤 导入defi ...

  2. 华企盾DSC无缝替换亿赛通案例

    第一种方法无缝替换亿赛通案例 1. 把DSCClient.exe和DSCService.exe添加到亿赛通的加密控制策略中,关联类型设置为*.*|,配置为落地自动解密,包括其它程序也配置成落地自动解密 ...

  3. python tkinter使用(九)

    python tkinter使用(九) 本文主要讲下scrolledText中图片的插入,以及常见的错误. 使用Image.open来打开图片 使用ImageTk.PhotoImage()方法将图片转 ...

  4. 聊聊流式数据湖Paimon(五)

    从Demo入手,了解Paimon/Flink项目搭建的全过程.记录下采坑之旅. 创建Flink项目 在IDEA中创建Flink项目,由于没有Flink的archetype,因此需要手动创建一下. 参考 ...

  5. 【笔记】 springCloud-configServer配置中心

    当然第一步还是得要了解啦! 介绍 做项目, 那么就少不了配置微服务架构中,配置文件众多,各个服务的配置文件也有可能不一样, Spring为我们提供了相应的配置中心组件--Spring Cloud co ...

  6. SQL Server系列:系统函数之聚合函数

    聚合函数:指对一组值执行计算,并返回单个值.除了 Count(统计函数) 外,聚合函数都会忽略 Null 值 聚合函数经常与 SELECT 语句的 GROUP BY 子句一起使用 1.Avg():返回 ...

  7. 带你认识全新的华为云IoT路网数字化服务

    摘要:随着通信技术的发展,交通领域提出以C-V2X车路协同技术来弥补单车智能存在的缺陷,从而推动智能驾驶.自动驾驶技术的成熟. 本文分享自华为云社区<带你全新认识华为云IoT路网数字化服务> ...

  8. 解读知识蒸馏模型TinyBert

    摘要:本篇文章的重点在于改进信息瓶颈的优化机制,并且围绕着高纬空间中互信息难以估计,以及信息瓶颈优化机制中的权衡难题这两个点进行讲解. 本文分享自华为云社区<[云驻共创]美文赏析:大佬对变分蒸馏 ...

  9. Python pdf 转 图片

    安装依赖 D:\OpenSource\Python>pip install pdf2image pillow -i https://pypi.tuna.tsinghua.edu.cn/simpl ...

  10. 自然语言处理 Paddle NLP - 机器同传技术及应用-理论

    基础 自然语言处理(NLP) 自然语言处理PaddleNLP-词向量应用展示 自然语言处理(NLP)-前预训练时代的自监督学习 自然语言处理PaddleNLP-预训练语言模型及应用 自然语言处理Pad ...