AHB SRAM控制器设计

5 篇文章 1 订阅
5 篇文章 0 订阅

代码构成

ahb_slave_if_tb.v  //仿真文件

ahb_slave_if.v      //控制器文件

sram_core.v        //sram 文件

 

ahb_slave_if_tb.v

用于模拟生成AHB的读写信号

1、时钟的生成

hclk为AHB总线时钟

sram_clk为hclk的反相,为了保证但周期读写

2、读写任务ahb_write_32()和ahb_read_32(),模拟AHB总线行为

 

task

输入参数为haddr与wdata

第一周期:

与ahb时钟同步

向slave发送传输大小hsize、传输类型htrans、数据方向hwrite、decoder根据地址选中信号hsel、其他slave是否全都hready信号、以及要写的地址haddr信号

第二周期:

与ahb时钟同步

向slave发送传输大小hsize,传输类型IDLE,hwrite、hsel、haddr置零,hwdata给出要传输的数据

task ahb_write_32(input [31:0]addr,input [31:0]wdata);begin

    @(posedge hclk)

        #1;

    hsize=2;

    htrans=NONSEQ;

    hwrite=1;

    hsel=1;

    hready=1;

    haddr=addr;

    @(posedge hclk)

        #1;

    hsize=2;

    htrans=IDLE;

    hsel=0;

    hwrite=0;

    hwdata=wdata;

    haddr=0;

    @(posedge hclk)

        #1;

end

endtask

 

task

输入参数为读地址haddr、读取到的内容hrdata

第一周期:

与ahb时钟同步

向slave发送传输大小hsize、传输类型htrans、数据方向hwrite、decoder根据地址选中信号hsel、以及要写的地址haddr信号

第二周期:

与ahb时钟同步

向slave发送传输大小hsize,传输类型IDLE,hwrite、hsel、haddr置零

 

task ahb_read_32(input [31:0]addr,output [31:0]rdata);begin

    @(posedge hclk)

        #1;

    haddr=addr;

    hsize=2;

    htrans=NONSEQ;

    hwrite=0;

    hsel=1;

    @(posedge hclk)

        #1;

    hsize=2;

    htrans=IDLE;

    hsel=0;

    hwrite=0;

    @(posedge hclk)

        rdata=hrdata;

    haddr=0;

    @(posedge hclk)

        #1;    

end

endtask

 

ahb_slave_if.v

接收ahb总线的信号和作出反馈,根据ahb置零控制sram写入或返回数据

1、haddr和hwrite打一拍

因为ahb协议中,数据比地址晚一拍到达,所以需要将haddr打一拍得到addr_r,hwrite同理

//haddr_r is 1 beat after haddr

always @(posedge hclk or negedge hresetn) begin

    if(!hresetn)begin

        haddr_r<=0;

    end

    else

        haddr_r<=haddr;   

end

//hwrite_r is 1 beat after hwrite

always @(posedge hclk or negedge hresetn) begin

    if(!hresetn)begin

        hwrite_r<=0;

    end

    else

        hwrite_r<=hwrite;   

end

 

通过hwrite获得sram的写使能以及选择haddr(读)还是haddr_r(写)——haddr_rhwrite已经为低,需要将hwrite延长一拍

assign sram_addr=(hwrite||hwrite_r)?haddr_r:haddr;

 

2、bank0_cs与bank1_cs由地址线数据和hsize得到;32bit,可分为8、16、32三种,共7种组合方式

hsize=0:8bit,地址直接对应相应sram,地址haddr[1:0]对应第几个sram

hsize=1:16bit,地址haddr[1]对应选择哪两个sram

hsize=2:32bit,地址haddr[1:0]必须是0,自动选择4个sram

always @(*) begin

    if(!hresetn)begin

        sram_cs<=0;

    end

    else begin

        case (hsize)

            0:begin

              if(haddr_r[1:0]==0)begin

                  sram_cs=4'b0001;

              end

              else if(haddr_r[1:0]==1)begin

                  sram_cs=4'b0010;

              end

              else if(haddr_r[1:0]==2)begin

                  sram_cs=4'b0100;

              end

              else begin

                  sram_cs=4'b1000;

              end

            end

            1:begin

              if (haddr_r[1:0]==0begin

                  sram_cs=4'b0011;

              end

              else begin

                  sram_cs=4'b1100;

              end

            end

            2:begin

               sram_cs=4'b1111;

            end

            defaultbegin

                sram_cs=4'b1111;

            end

        endcase

    end

end

 

bank0与bank1选择由haddr[15]决定

assign bank0_cs=haddr_r[15]?0:sram_cs;

assign bank1_cs=haddr_r[15]?sram_cs:0;

 

sram_core.v

由haddr[15]决定选择bank输出

assign sram_rdata_out=sram_addr[15]?{bank1_q3,bank1_q2,bank1_q1,bank1_q0}:{bank0_q3,bank0_q2,bank0_q1,bank0_q0};

 

按bank分配输入和输出

blk_mem_gen_0 bank0_ram0 (

  .clka(sram_clk),    // input wire clka

  .ena(bank0_cs[0]),      // input wire ena

  .wea(sram_wen),      // input wire [0 : 0] wea

  .addra(sram_addr[12:0]),  // input wire [12 : 0] addra

  .dina(sram_wdata_in[7:0]),    // input wire [7 : 0] dina

  .douta(bank0_q0)  // output wire [7 : 0] douta

);

blk_mem_gen_0 bank0_ram1 (

  .clka(sram_clk),    // input wire clka

  .ena(bank0_cs[1]),      // input wire ena

  .wea(sram_wen),      // input wire [0 : 0] wea

  .addra(sram_addr[12:0]),  // input wire [12 : 0] addra

  .dina(sram_wdata_in[15:8]),    // input wire [7 : 0] dina

  .douta(bank0_q1)  // output wire [7 : 0] douta

);

blk_mem_gen_0 bank0_ram2 (

  .clka(sram_clk),    // input wire clka

  .ena(bank0_cs[2]),      // input wire ena

  .wea(sram_wen),      // input wire [0 : 0] wea

  .addra(sram_addr[12:0]),  // input wire [12 : 0] addra

  .dina(sram_wdata_in[23:16]),    // input wire [7 : 0] dina

  .douta(bank0_q2)  // output wire [7 : 0] douta

);

blk_mem_gen_0 bank0_ram3 (

  .clka(sram_clk),    // input wire clka

  .ena(bank0_cs[3]),      // input wire ena

  .wea(sram_wen),      // input wire [0 : 0] wea

  .addra(sram_addr[12:0]),  // input wire [12 : 0] addra

  .dina(sram_wdata_in[31:24]),    // input wire [7 : 0] dina

  .douta(bank0_q3)  // output wire [7 : 0] douta

);

 

blk_mem_gen_0 bank1_ram0 (

  .clka(sram_clk),    // input wire clka

  .ena(bank1_cs[0]),      // input wire ena

  .wea(sram_wen),      // input wire [0 : 0] wea

  .addra(sram_addr[12:0]),  // input wire [12 : 0] addra

  .dina(sram_wdata_in[7:0]),    // input wire [7 : 0] dina

  .douta(bank1_q0)  // output wire [7 : 0] douta

);

blk_mem_gen_0 bank1_ram1 (

  .clka(sram_clk),    // input wire clka

  .ena(bank1_cs[1]),      // input wire ena

  .wea(sram_wen),      // input wire [0 : 0] wea

  .addra(sram_addr[12:0]),  // input wire [12 : 0] addra

  .dina(sram_wdata_in[15:8]),    // input wire [7 : 0] dina

  .douta(bank1_q1)  // output wire [7 : 0] douta

);

blk_mem_gen_0 bank1_ram2 (

  .clka(sram_clk),    // input wire clka

  .ena(bank1_cs[2]),      // input wire ena

  .wea(sram_wen),      // input wire [0 : 0] wea

  .addra(sram_addr[12:0]),  // input wire [12 : 0] addra

  .dina(sram_wdata_in[23:16]),    // input wire [7 : 0] dina

  .douta(bank1_q2)  // output wire [7 : 0] douta

);

blk_mem_gen_0 bank1_ram3 (

  .clka(sram_clk),    // input wire clka

  .ena(bank1_cs[3]),      // input wire ena

  .wea(sram_wen),      // input wire [0 : 0] wea

  .addra(sram_addr[12:0]),  // input wire [12 : 0] addra

  .dina(sram_wdata_in[31:24]),    // input wire [7 : 0] dina

  .douta(bank1_q3)  // output wire [7 : 0] douta

);

endmodule

 

  • 4
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值