【数字IC】基于AHB协议的SRAM读写控制器

基于AHB协议的SRAM读写控制器

1.设计功能与要求

在这里插入图片描述

2.算法原理

本设计采用 三段式状态机 实现了一个AHB Slave,将其与Vivado中Block Memory Generator生成的SRAM单元相连,实现接受AHB控制信号完成对RAM单元的读写操作。由于地址空间大小为 ( 3 F F C ) 16 = ( 16380 ) 10 (3FFC)_{16}=(16380)_{10} (3FFC)16=(16380)10、SRAM深度为4096,因此地址映射为16380/4096≈4,所以需要对haddr>>2才能得到对应的SRAM地址。由AMBA总线传输协议得进行一次数据传输的时候首先需要在地址相位发送地址和控制信号,然后在下一个周期数据相位时发送或接受该地址对应的数据信号,其时序如下:
在这里插入图片描述

题目要求实现突发模式传输,在此模式下可以流水进行连续4/8/16个数据的读写操作,其时序如下:
在这里插入图片描述

本设计采用三段式状态机实现,在S0状态下进行地址相位,通过hwrite信号判断进入SW写数据相位还是SR读数据相位,在SW/SR状态下通过hburst、htrans信号控制计数器cnt来实现单数据传输模式和突发传输模式,然后cnt计数满之后再次进入S0状态,其状态转移图如下:
在这里插入图片描述

3.RTL实现

3.1 AHB从机模块

根据第2小节中的描述和参考文档《最经典的AMBA总线中文资料》中的描述,很容易采用状态机实现AHB从机Verilog代码如下。

module sram_ctr_ahb(
    input hclk,
    input hresetn,
    input hwrite,
    input [1:0] htrans,
    input [2:0] hsize,
    input [31:0] haddr,
    input [2:0] hburst,
    input [31:0] hwdata,
    output reg hready,
    output reg [1:0] hresp,
    output [31:0] hrdata,
    output reg sram_scn, //低有效
    output reg sram_wen, //低有效
    output [11:0] sram_a,
    output [31:0] sram_d,
    input [31:0] sram_q
    );
    // parameter define
    // hsize == 3'b000;//8bit
    // hsize == 3'b001;//16bit
    // hsize == 3'b010;//32bit
    // hsize == 3'b011;//64bit
    // hsize == 3'b100;//128bit
    // hsize == 3'b101;//256bit
    // hsize == 3'b110;//512bit
    // hsize == 3'b111;//1024bit
    // htrans
    localparam IDLE  = 2'b00;
    localparam BUSY  = 2'b01;
    localparam NONSEQ = 2'b10;
    localparam SEQ = 2'b11;
    // hburst
    localparam SINGLE = 3'b000;//单一传输
    localparam INCR   = 3'b001;//未指定长度的增量突发
    localparam WRAP4  = 3'b010;//4拍回环突发
    localparam INCR4  = 3'b011;//4拍增量突发
    localparam WRAP8  = 3'b100;//8拍回环突发
    localparam INCR8  = 3'b101;//8拍增量突发
    localparam WRAP16 = 3'b110;//16拍回环突发
    localparam INCR16 = 3'b111;//16拍增量突发
    // hresp
    localparam OKAY  = 2'b00;
    localparam ERROR = 2'b01;
    localparam RETRY = 2'b10;
    localparam SPLIT = 2'b11;
    // FSM state
    localparam S0 = 3'b001;//地址相位
    localparam SW = 3'b010;//数据相位-写
    localparam SR = 3'b100;//数据相位-读

    // signal define
    reg [2:0] cstate, nstate, cstate_r;
    reg cnt_flag;
    reg [3:0] cnt;
    reg [2:0] hsize_r;
    reg [31:0] haddr_r;
    reg [2:0] hburst_r;

    // define cnt max by hburst
    always @(*) begin
        case (hburst)
            SINGLE: cnt_flag = (cnt==4'd0)?1'b1:1'b0;
            INCR  : cnt_flag = (cnt==4'd0)?1'b1:1'b0;
            WRAP4 : cnt_flag = (cnt==4'd3)?1'b1:1'b0;
            INCR4 : cnt_flag = (cnt==4'd3)?1'b1:1'b0;
            WRAP8 : cnt_flag = (cnt==4'd7)?1'b1:1'b0;
            INCR8 : cnt_flag = (cnt==4'd7)?1'b1:1'b0;
            WRAP16: cnt_flag = (cnt==4'd15)?1'b1:1'b0;
            INCR16: cnt_flag = (cnt==4'd15)?1'b1:1'b0;
            default:cnt_flag = (cnt==4'd0)?1'b1:1'b0;
        endcase
    end

    // FSM1
    always @(posedge hclk or negedge hresetn) begin
        if(!hresetn)begin
            cstate <= S0;
            cstate_r <= S0;
            hsize_r <= 3'd0;
            haddr_r <= 32'd0;
            hburst_r <= 3'd0;
        end
        else begin
            cstate <= nstate;
            cstate_r <= cstate;
            hsize_r <= hsize;
            haddr_r <= haddr;
            hburst_r <= hburst;
        end
    end

    // FSM2
    always @(*) begin
        case (cstate)
            S0: begin
                if(hwrite) begin
                    nstate = SW;
                end
                else begin
                    nstate = SR;
                end
            end
            SW: begin
                if(cnt_flag) begin
                    nstate = S0;
                end
                else begin
                    nstate = SW;
                end
            end 
            SR: begin
                if(cnt_flag) begin
                    nstate = S0;
                end
                else begin
                    nstate = SR;
                end
            end 
            default: nstate = S0;
        endcase
    end

    // FSM3
    always @(posedge hclk or negedge hresetn) begin
        if(!hresetn)begin
            hready <= 1'b0;
            hresp <= RETRY;
            sram_scn <= 1'b1;
            sram_wen <= 1'b0;
        end
        else begin
            hready <= 1'b1;
            hresp <= OKAY;

            case (nstate)
                S0: begin
                    // SRAM控制
                    sram_scn <= 1'b1;
                    sram_wen <= 1'b0;
                end
                SW: begin
                    // SRAM控制
                    sram_scn <= 1'b0;
                    sram_wen <= 1'b0;
                end
                SR: begin
                    // SRAM控制
                    sram_scn <= 1'b0;
                    sram_wen <= 1'b1;
                end
                default: begin
                    // SRAM控制
                    sram_scn <= 1'b1;
                    sram_wen <= 1'b0;
                end
            endcase
        end
    end

    always @(posedge hclk or negedge hresetn) begin
        if(!hresetn)begin
            cnt <= 4'd0;
        end
        else begin
            case (cstate)
                S0: begin
                    cnt <= 4'd0;
                end
                SW: begin
                    if(htrans==BUSY) begin
                        cnt <= cnt;
                    end
                    else begin
                        cnt <= cnt + 4'd1;
                    end
                end
                SR: begin
                    if(htrans==BUSY) begin
                        cnt <= cnt;
                    end
                    else begin
                        cnt <= cnt + 4'd1;
                    end
                end
                default: begin
                    cnt <= 4'd0;
                end
            endcase
        end
    end

    assign hrdata = (cstate_r==SR)?sram_q:32'd0;
    assign sram_d = (cstate==SW)?hwdata:32'd0;
    assign sram_a = ((cstate==SW)||(cstate==SR))?haddr_r[13:2]:12'd0;

endmodule

3.2 顶层模块

在顶层中例化AHB从机和Vivado的SRAM IP,可得Verilog代码如下。

module AHB_SRAM_top(
    input hclk,
    input hresetn,
    input hwrite,
    input [1:0] htrans,
    input [2:0] hsize,
    input [31:0] haddr, // 0x00000000 – 0x00003FFC
    input [2:0] hburst,
    input [31:0] hwdata,
    output hready,
    output [1:0] hresp,
    output [31:0] hrdata
    );
    // signal define
    wire sram_scn, sram_wen;
    wire [11:0] sram_a;
    wire [31:0] sram_d;
    wire [31:0] sram_q;

    // module instance
    sram_ctr_ahb  sram_ctr_ahb_inst (
        .hclk(hclk),
        .hresetn(hresetn),
        .hwrite(hwrite),
        .htrans(htrans),
        .hsize(hsize),
        .haddr(haddr),
        .hburst(hburst),
        .hwdata(hwdata),
        .hready(hready),
        .hresp(hresp),
        .hrdata(hrdata),
        .sram_scn(sram_scn),
        .sram_wen(sram_wen),
        .sram_a(sram_a),
        .sram_d(sram_d),
        .sram_q(sram_q)
    );
    
    SRAM_4096_32 SRAM (
        .clka(hclk),    // input wire clka
        .ena(!sram_scn),// input wire ena
        .wea(!sram_wen),// input wire [0 : 0] wea
        .addra(sram_a), // input wire [11 : 0] addra
        .dina(sram_d),  // input wire [31 : 0] dina
        .douta(sram_q)  // output wire [31 : 0] douta
    );

endmodule

Vivado RTL analysis结果如下图所示,在顶层AHB_SRAM_top中例化本设计sram_ctr_ahb和vivado的BRAM IP核SRAM,符合设计预期。
在这里插入图片描述

AHB总线从机sram_ctr_ahb采用三段式状态机实现,其vivado原理图如下:
在这里插入图片描述

4.RTL仿真结果

测试用例1:16拍增量突发写SRAM

在地址相位输入hwrite=1、hburst=INCR16、htrans=SEQ、haddr=32’h00000010,然后在后续15个连续时钟周期每个时钟周期haddr的地址+16’d4,并使用hwdata=$random随机生成测试激励,可得仿真波形如下:
在这里插入图片描述

通过modelsim的Memory List观察得到SRAM中数据如下:
在这里插入图片描述

由于地址对齐因此0x00000010对应到SRAM地址为0x00000004,可见数据被成功写入SRAM。

测试用例2:8拍增量突发读SRAM

在地址相位输入hwrite=0、hburst=INCR8、htrans=SEQ、haddr=32’h00000010,然后在后续7个连续时钟周期每个时钟周期haddr的地址+16’d4,可得仿真波形如下:

在这里插入图片描述

由于SRAM输出会延迟一个周期,可见仿真波形正确。

参考与致谢

《最经典的AMBA总线中文资料》

写在最后

2025年1月上旬总算结束了研一上学期繁忙的课程,总算有时间整理总结UCAS《高等数字集成电路分析与设计》课程中老师所布置的作业题,作为老师上课来不及仔细讲解内容的补充,也作为以后自己复习的参考。笔者作为初学者难免出现错误,请读者多多批评指正,也希望看到本博客的学弟学妹多多思考、不要盲目抄袭。

源码

verilog源码开源在:lionelZhaowy/Digital-IC-Analysis-and-Design

作者:LionelZhao 欢迎转载,主动输出、与人分享是进步的源泉!!!

转载请保留原文地址:https://blog.csdn.net/LionelZhao/article/details/145285744?spm=1001.2014.3001.5501

创作不易,如果觉得本文对您有帮助欢迎读者客官多多打赏!!!

工程文件请在海鲜市场购买。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值