基于AHB协议的SRAMC设计

本系列文章将从零开始,完成一个基于AHB协议的SRAM控制器设计,并对代码进行详细分析。
摘要由CSDN通过智能技术生成


前言

本系列文章将从零开始,完成一个基于AHB协议的SRAM控制器设计,并对代码进行详细分析。主要是记录一下我之前的学习过程,方便日后复习查看,如有错误,希望大家批评指正。


一、SRAMC的总体框架和功能

SRAM有着很高的读写速度,常在整个系统中作为缓存,是必不可少的一个存在。基于AHB协议的SRAMC可以实现SRAM存储器与AHB总线的数据信息交换。本设计将其分为三个模块,sram_core、ahb_slave_if以及顶层模块sram_top。

1.总体框架

顶层模块框架图
core
if

2.功能

  • 可以按照AHB的时序进行连续的读取和写入
  • 可以传输8位、16位、32位的数据

实现功能的主要为sram_core和ahb_slave_if模块,ahb_slave_if模块负责处理来自AHB总线的信号(控制信号、地址信号、数据信号),将其转换为对sram_core的信号,控制sram_core的使能和读写。sram_core模块部分主要负责数据的写入和读取,针对ahb_slave_if模块传来的信号做出响应,使能对应的srambank,写入或读出数据。

二、设计代码实现

1.sram_core

不会使用Memory compiler,所以这一部分我就自己简单写了写。

由于最大要传输32位的数据,而sram一般是8位,因此sram_core最少需要4个srambank才能支持,所以本设计的sram_core模块一共包含了4个srambank。

我将每个srambank的大小设置为8K(数据位宽8位,数据深度1K),一共采用了4个srambank,在传输32位数据的时候他们是同时工作的,在传输8位或16位数据时只有部分srambank工作,因此需要对不同的srambank进行地址分配。我采用了以下方式分配地址。

地址0代表srambank0的0地址,地址1代表srambank1的0地址,地址2代表srambank2的0地址,地址3代表srambank3的0地址,地址4代表srambank0的1地址,地址5代表srambank1的1地址。。。以此类推。

sram代码如下:

module sram #(
  parameter ADDR_WIDTH = 10,
            ADDR_DEPTH = 1024,
            DATA_WIDTH = 8
)(
  input clk,
  input en,
  input write,
  input read,
  input [ADDR_WIDTH-1:0] addr,
  input [DATA_WIDTH-1:0] wdata,
  output reg [DATA_WIDTH-1:0] rdata
);
  reg [DATA_WIDTH-1:0] mem [ADDR_DEPTH-1:0];
  
  always@(posedge clk)
    if(en&&write)
      mem[addr] <= wdata;
    else
      mem[addr] <= mem[addr];

  always@(posedge clk)
    if(en&&read)
      rdata <= mem[addr];
    else
      rdata <= rdata;

endmodule

sram部分就是一个简单的mem,这里就不多说了。注意:虽然sram具有读写两个端口,但是不能同时读写,这是一个伪双口ram(可以改为一个端口控制,我只是懒得改了)

sram_core代码如下:

module sram_core (
  input clk,
  input [3:0]en,
  input write,
  input read,
  input [31:0] sram_addr,
  input [31:0] wdata,
  output [31:0] rdata
);

  genvar i;
  generate for(i=0;i<4;i=i+1)begin:sram_instance
    sram #(
      .ADDR_WIDTH(10),
      .ADDR_DEPTH(1024),
      .DATA_WIDTH(8)
    )u_sram(
      .clk(clk),
      .en(en[i]),
      .write(write),
      .read(read),
      .addr(sram_addr[11:2]),
      .wdata(wdata[8*i+7-:8]),
      .rdata(rdata[8*i+7-:8])
    );
  end
  endgenerate

endmodule

sram_core只是对sram进行了四次例化,非常简单。

注意:例化时地址连接的并不是sram_addr[9:0],而是sram_addr[11:2],这是因为将sram_addr的最后低两位用作srambank的片选。

传输8位数据时,00选择srambank0,01选择srambank1,10选择srambank2,11选择srambank3;传输16位数据时,00选择srambank0和srambank1,10选择srambank2和srambank3。

这里解释一下 为什么传输16位数据时00选择srambank0和srambank1,10选择srambank2和srambank3,为什么没有01和11呢
这是因为AHB协议中要求了传输地址和传输位宽要对齐,每次需要读写两个srambank,对于sram_core来说就要一次读写两个地址,故AHB连续给地址的时候一定是每次+2,也就是00——10。最低位一定是0。
同理传输32位数据时,地址就要每次+4,对应最低两位一定是00。

2.ahb_slave_if

本模块才是此次设计中最重要的部分,这里先简单说一下模块中都包含哪些组成部分,后面会再详细介绍。

  • 地址和控制信号寄存器,用来打排延迟,因为AHB完成一次读或写需要两个周期,地址周期和数据周期,而sram的地址和数据在同一拍。
  • 地址处理,对AHB传来的地址进行处理,将其变为sram的地址。
  • 数据大小处理,即对hsize的处理,跟地址处理是一起的,这俩个其实可以合并到一起。
  • 使能控制,当传输16位或8位数据时只有部分srambank工作,只对工作的srambank使能,对不工作的不使能。
  • 写入读出数据处理,对来自AHB总线和sram_core的数据进行处理,确保能从正确的srambank中写入和读出数据。
  • 读写信号控制,顾名思义,产生sram_core的读写信号。

ahb_slave_if代码如下:

module ahb_slave_if (
  input hclk,
  input hrstn,
  input hsel,
  input hready,
  input hwrite,
  input [2:0]hburst,
  input [31:0]haddr,
  input [1:0]htrans,
  input [2:0]hsize,
  input [31:0]hwdata,
  input [31:0]rdata,
  output reg [31:0]hrdata,
  output reg [3:0]en,
  output write,
  output read,
  output [31:0]sram_addr,
  output reg [31:0]wdata
);
//地址和控制信号寄存器
  reg [31:0] haddr_r;
  reg [2:0]  hsize_r;
  reg hwrite_r;
  reg [2:0]hburst_r;
  reg [1:0]htrans_r;

  always@(posedge hclk or negedge hrstn)begi
  • 6
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值