代码构成
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_r时hwrite已经为低,需要将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]==0) begin
sram_cs=4'b0011;
end
else begin
sram_cs=4'b1100;
end
end
2:begin
sram_cs=4'b1111;
end
default: begin
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