reg [DATA_WIDTH-1:0] mem [0:((1<<ADDR_WIDTH)-1)]; // 存储器数组
integer id;
always @(posedge clk) begin if (ce) begin if (we) begin for (id = 0; id < WBE_NUM; id = id + 1) begin if (wbe[id]) begin mem[addr][id*WBE_GRP_WIDTH +: WBE_GRP_WIDTH] <= din[id*WBE_GRP_WIDTH +: WBE_GRP_WIDTH]; dout[id*WBE_GRP_WIDTH +: WBE_GRP_WIDTH] <= din[id*WBE_GRP_WIDTH +: WBE_GRP_WIDTH]; endelsebegin // 显式赋值保持 memory 原值或 dout 明确逻辑,防止综合歧义 dout[id*WBE_GRP_WIDTH +: WBE_GRP_WIDTH] <= mem[addr][id*WBE_GRP_WIDTH +: WBE_GRP_WIDTH]; end end endelsebegin dout <= mem[addr]; end end end
endmodule
1.2 DP-SRAM
双端口SRAM**(DP-SRAM)**,端口结构如下图所示:
其中,
“a” 口只写, “b” 口只读;
“a” 口的写不会改变 “b” 口的 doutb;
为了兼容性,禁止 “a”/“b” 口同时 r/w 同一个地址。
然后来看一下各个端口定义:
端口
方向
含义
clka
输入
A 端口时钟,A 端口所有读写操作同步于该时钟上升沿
ena
输入
A 端口使能(chip enable),高电平端口工作;低电平端口不动作
wea
输入
A 端口写使能(write enable A):1 = 写操作,0 = 读操作
wbea
输入
A 端口字节写掩码(write byte‑enable A),位选写使能,支持部分 bit / 字节分片写入,1 代表对应分组允许写入
addra
输入
A 端口地址,A 端口读写的存储单元地址
dina
输入
A 端口写输入数据,写操作时送入存储器的数据
clkb
输入
B 端口时钟,B 端口操作同步于该时钟上升沿;双端口可以是异步时钟(真正 DP),clka 与 clkb 可以不同频不同相
always @(posedge clka)begin if(ena)begin if(wea)begin for(id=0; id<WBE_NUM; id=id+1)begin if(wbea[id])begin mem[addra][id*WBE_GRP_WIDTH +: WBE_GRP_WIDTH] <= dina[id*WBE_GRP_WIDTH +: WBE_GRP_WIDTH]; end end end end end
always @(posedge clkb)begin if(enb)begin doutb <= mem[addrb]; end end