BIST_en ),
.oBIST_done (BIST_done_5 ),
.oBIST_fail (BIST_fail_5 )
);
sram_bist u_bank1_sram6 (
// Function Mode IO
.iSRAM_CLK (iHCLK ),
.iSRAM_CSN (iSRAM_CSN_BANK1[2]),
.iSRAM_WEN (iSRAM_WEN_BANK1 ),
.iSRAM_ADDR (iSRAM_ADDR ), //13 bits SRAM ADDR
.iSRAM_WDATA(iSRAM_WDATA[23:16]),
.oSRAM_RDATA(oSRAM6_q ),
// Test Mode IO
.iBIST_en (iBIST_en ),
.oBIST_done (BIST_done_6 ),
.oBIST_fail (BIST_fail_6 )
);
sram_bist u_bank1_sram7 (
// Function Mode IO
.iSRAM_CLK (iHCLK ),
.iSRAM_CSN (iSRAM_CSN_BANK1[3]),
.iSRAM_WEN (iSRAM_WEN_BANK1 ),
.iSRAM_ADDR (iSRAM_ADDR ), //13 bits SRAM ADDR
.iSRAM_WDATA(iSRAM_WDATA[31:24]),
.oSRAM_RDATA(oSRAM7_q ),
// Test Mode IO
.iBIST_en (iBIST_en ),
.oBIST_done (BIST_done_7 ),
.oBIST_fail (BIST_fail_7 )
);
endmodule
1.6 SRAM读写功能的仿真验证
在完成RTL设计后,我们编写了Testbench,
并在Vivado平台上进行了简单的读写仿真验证,波形如下:
分析一下Testbench具体对SRAM发起了什么操作:
首先,T1-T7进行了六次写操作,将6个数据依次写入SRAM的0x0000,0x0004,0x0008,0x8000,0x8004,0x8008六个地址当中
其中前三个地址对应Bank0,后三个地址对应Bank1,
因此在T2-T4期间 SRAM_CSN_BANK0 和 SRAM_WEN_BANK0 被拉高,
在T5-T7期间 SRAM_CSN_BANK1 和 SRAM_WEN_BANK1 被拉高,
从上图中可以看出,T7除了是Data 6的写数据周期,也是Data 1 读地址周期,
但是由于SRAM端口上,该周期需要执行写Data 6的操作。
于是发生了地址冲突,无法在该周期同时进行读Data 1
因此,在T8并没有返回Data 1的读数据,HREADY被拉低,
随后,在T9-T14,总线上HRDATA依次拿到了六个SRAM读数据,读出的data与T1-T7写入的data完全一致,证明了以上SRAM控制器的设计逻辑是正确的
1.7 支持半字/字节读写
细心的读者们可能发现上述设计仅考虑了读SRAM按字进行读写的情况,
也就是每次读写都是32位的。
实际上,AHB协议同样支持我们以16位/8位的方式对SRAM进行访问,由HSIZE[2:0]控制,具体对应关系如下:
HSIZE[2:0] = 3'b000:按BYTE读写
HSIZE[2:0] = 3'b001:按Half Word读写
HSIZE[2:0] = 3'b010:按Word读写
支持半字/字节读写使得CSN信号的生成变得更为复杂,
基于上述设计,读者们可以思考一下如何实现该功能,
以下给出参考设计:
// SRAM Bank CSN
wire [3:0] SRAM_CSN_BANK0_write;
wire [3:0] SRAM_CSN_BANK0_read ;
wire [3:0] SRAM_CSN_BANK1_write;
wire [3:0] SRAM_CSN_BANK1_read ;
always @(*) begin
case( {iHADDR[15],iHSIZE} )
//选中BANK0,HSIZE = Word
4'b0010:begin
SRAM_CSN_BANK0_read <= 4'b1111;
SRAM_CSN_BANK0_read <= 4'b0000;
end
//选中BANK1,HSIZE = Word
4'b1010:begin
SRAM_CSN_BANK0_read <= 4'b0000;
SRAM_CSN_BANK1_read <= 4'b1111;
end
//选中BANK0,HSIZE = Half Word
4'b0001:begin
if(iHADDR[1]) begin
SRAM_CSN_BANK0_read <= 4'b1100;
SRAM_CSN_BANK1_read <= 4'b0000;
end else begin
SRAM_CSN_BANK0_read <= 4'b0011;
SRAM_CSN_BANK1_read <= 4'b0000;
end
end
//选中BANK1,HSIZE = Half Word
4'b1001:begin
if(iHADDR[1]) begin
SRAM_CSN_BANK0_read <= 4'b0000;
SRAM_CSN_BANK1_read <= 4'b1100;
end else begin
SRAM_CSN_BANK0_read <= 4'b0000;
SRAM_CSN_BANK1_read <= 4'b0011;
end
end
//选中BANK0,HSIZE = BYTE
4'b0000:begin
case (iHADDR[1:0])
2'b00: begin
SRAM_CSN_BANK0_read <= 4'b0001;
SRAM_CSN_BANK1_read <= 4'b0000;
end
2'b01: begin
SRAM_CSN_BANK0_read <= 4'b0010;
SRAM_CSN_BANK1_read <= 4'b0000;
end
2'b10: begin
SRAM_CSN_BANK0_read <= 4'b0100;
SRAM_CSN_BANK1_read <= 4'b0000;
end
2'b11: begin
SRAM_CSN_BANK0_read <= 4'b1000;
SRAM_CSN_BANK1_read <= 4'b0000;
end
endcase
end
//选中BANK1,HSIZE = BYTE
4'b1000:begin
case (iHADDR[1:0])
2'b00: begin
SRAM_CSN_BANK0_read <= 4'b0000;
SRAM_CSN_BANK1_read <= 4'b0001;
end
2'b01: begin
SRAM_CSN_BANK0_read <= 4'b0000;
SRAM_CSN_BANK1_read <= 4'b0010;
end
2'b10: begin
SRAM_CSN_BANK0_read <= 4'b0000;
SRAM_CSN_BANK1_read <= 4'b0100;
end
2'b11: begin
SRAM_CSN_BANK0_read <