Verilog99题——31-37题(存储相关)
前言
不忘出芯veriloig99题的31-37题是存储相关。
-
- 前言
- 31.名词解释
- 32. 用verilog实现一个深度16,位宽8bit的ROM,初始值等于对应地址加上
0xA0
。 - 33. 画出SRAM bit cell结构图——6管基本存储电路及其运作原理.
- 34. 用verilog实现一个单端口sram,深度16,位宽8bit。支持片选,读写请求,要求代码可综合。
- 35. 用verilog实现一个同步双端口sram,深度16,位宽8bit。A口读出,B口写入。支持片选,读写请求,要求代码可综合。
- 36. 用verilog实现一个异步双端口ram,深度16,位宽8bit。A口读出,B口写入。支持片选,读写请求,要求代码可综合。
- 37. 用verilog实现一个同步双端口ram,深度16,位宽8bit。A口可读可写,B口可读可写。支持片选,读写请求,要求代码可综合。
- 前言
31.名词解释
- ROM:Read Only Memory,只读存储器。
- RAM:Random Access Memory,随机存取存储器,可以作手机、电脑的运行内存。
- SRAM:Static Random-Access Memory,静态随机存取存储器,只要供电数据就会保持,但断电数据就会消失。
- DRAM:Dynamic Random Access Memory,动态随机存储器,主要原理是利用电容存储电荷的多少来代表一个bit是0还是1,由于晶体管的漏电电流现象,电容会放电,所以要周期性的给电容充电,叫刷新。SRAM不需要刷新也会保持数据丢失,但是两者断电后数据都会消失,称为Volatile Memory。
- SDRAM:Synchronous Dynamic Random Access Memory,同步动态随机存储器,同步写入和读出数据的DRAM。
- EEPROM:Electrically Erasable Programmable Read Only Memory,电可擦除可编程只读存储器。
- DDR:Double Data Synchronous Dynamic Random Access Memory,双倍速率同步动态随机存储器,双倍速率传输的SDRAM,在时钟的上升沿和下降沿都可以进行数据传输。我们电脑的内存条都是DDR芯片。
- MRAM:Magnetoresistive Random Access Memory,磁阻式随机存取内存,是一种非易失性内存技术,与传统的RAM芯片技术不同,MRAM中的数据不作为电荷或电流流动存储,而是由磁存储元件存储。
- FLASH: Flash Memory,闪存,非易失性固态存储,如制成内存卡或U盘。
32. 用verilog实现一个深度16,位宽8bit的ROM,初始值等于对应地址加上0xA0
。
module test32
#(
parameter WD = 4'd8, //数据位宽
parameter DP = 5'd16 //深度
)
(
input i_en ,
input [ADDR_WD-1:0] i_addr ,
output [WD-1:0] o_data
);
localparam ADDR_WD = clogb2(DP); //地址位宽
reg [WD-1:0] buffer [DP-1:0];
integer i;
initial begin
for (i = 0; i < DP; i = i + 1) begin
buffer[i] <= i + 8'hA0;
end
end
assign o_data = i_en ? buffer[i_addr] : 'hz ;
function integer clogb2 (input integer depth);
begin
for(clogb2=0; depth>0; clogb2=clogb2+1)
depth = depth >> 1;
end
endfunction
endmodule
33. 画出SRAM bit cell结构图——6管基本存储电路及其运作原理.
晶体管M1及M2构成一个inverter,M3及M4构成另外一个inverter。这两个inverter的output分别接到另外一个inverter的input而形成一个latch,可以将数据锁存。M5及M6是开关,最常见的架构和用法如图所示,M5和M6是一起开或关的。
连接到M5和M6的gate的信号一般称之为word line(字线,缩写成WL),用来控制SRAM bit cell的开关。M5和M6的漏极是数据读出或写入的端口,一般称之为bit line(位线,缩写成BL)。如图所示,M6接到BL,相对地,M5则接到 BLˉ 。bit cell的儲存值就是指Q的值。
SRAM的基本单元有3种状态:standby(电路处于空闲),reading(读)与writing(写)。
standby:如果字线(Word Line)没有设置为高电平,那么作为控制用的M5,M6两个晶体管处于断路,把基本单元与位线隔离。由M1-M4组成的两个反相器继续保持其状态。
reading:假定存储的内容为1,即在Q处的电平为高,读周期之初,两根位线预充值为逻辑1,随后字线WL置为高电平,使得晶体管M5与M6通路。然后保存在Q的值会传递给位线BL,并且 BLˉ 通过M1与M5通路直连到低电平,使其值为逻辑0(即Q的高电平使得晶体管M1通路);在位线BL一侧,晶体管M4与M6形成的通路,把位线BL连接到VDD所代表的逻辑1(M4作为P沟道场效应管,由于栅极加了低电平 Qˉ 而形成通路)。如果存储的内容为0,相反的电路状态将会使 BLˉ 为1而BL为0.这样在 BLˉ 与BL间就会有一个很小的电位差,后续放大电路将会辨识出哪根位线是1哪根是0,从而完成读操作。
writing:写周期之初,把要写入的状态加载到位线。如果要写入0,则设置 BLˉ 为1且BL为0,随后字线WL加载为高电平,位线的状态被载入SRAM的基本单元。
参考链接:
34. 用verilog实现一个单端口sram,深度16,位宽8bit。支持片选,读写请求,要求代码可综合。
module spram_16x8 (
input clk,
input [3:0] addr,
input [7:0] din,
output [7:0] dout,
...
);
...
endmodule
module spram
#(
parameter WD = 8, //位宽
parameter DP = 16 //深度
)
(
input clk ,
input cs_n ,
input w_r_n ,
input [AD-1:0] addr ,
input [WD-1:0] din ,
output reg [WD-1:0] dout
);
localparam AD = clogb2(DP);
reg [WD-1:0] buffer [DP-1:0];
always @(posedge clk) begin
casex ({cs_n,w_r_n})
2'b1x: dout <= 'hx;
2'b01: buffer[addr] <= din;
2'b00: dout <= buffer[addr];
default: ;
endcase
end
function integer clogb2 (input integer depth);
begin
for(clogb2=0; depth>1; clogb2=clogb2+1)
depth = depth >> 1;
end
endfunction
endmodule
35. 用verilog实现一个同步双端口sram,深度16,位宽8bit。A口读出,B口写入。支持片选,读写请求,要求代码可综合。
module dpram_16x8 (
input clk,
input [3:0] addr_a,
output [7:0] dout_a,
input [7:0] din_b,
input [3:0] addr_b,
...
);
...
endmodule
module sy_dpram
#(
parameter WD = 8, //位宽
parameter DP = 16 //深度
)
(
input clk ,
input cs_n ,
input wr_n ,
input rd_n ,
input [WD-1:0] din_b , //B口写入
input [AD-1:0] addr_b ,
input [AD-1:0] addr_a , //A口读出
output reg [WD-1:0] dout_a
);
localparam AD = clogb2(DP);
reg [WD-1:0] buffer [DP-1:0];
/*
always @(posedge clk) begin
if (!cs_n && !rd_n) begin
dout_a <= buffer[addr_a];
end
end
always @(posedge clk) begin
if (!cs_n && !wr_n) begin
buffer[addr_b] <= din_b;
end
end
*/
always @(posedge clk) begin
casex ({cs_n,wr_n,rd_n})
3'b1xx: dout_a <= 'hx;
3'b000: begin dout_a <= buffer[addr_a]; buffer[addr_b] <= din_b; end
3'b001: buffer[addr_b] <= din_b;
3'b010: dout_a <= buffer[addr_a];
default: ;
endcase
end
function integer clogb2 (input integer depth);
begin
for(clogb2=0; depth>1; clogb2=clogb2+1)
depth = depth >> 1;
end
endfunction
endmodule
36. 用verilog实现一个异步双端口ram,深度16,位宽8bit。A口读出,B口写入。支持片选,读写请求,要求代码可综合。
module dpram_16x8 (
input clk_a,
input [3:0] addr_a,
output [7:0] dout_a,
...
input clk_b,
input [7:0] din_b,
input [3:0] addr_b,
...
);
...
endmodule
module as_dpram
#(
parameter WD = 8, //位宽
parameter DP = 16 //深度
)
(
input clk_a ,
input rda_n ,
input [AD-1:0] addr_a ,
output reg [WD-1:0] dout_a ,
input clk_b ,
input wrb_n ,
input [WD-1:0] din_b ,
input [AD-1:0] addr_b ,
input cs_n
);
localparam AD = clogb2(DP);
reg [WD-1:0] buffer [DP-1:0];
always @(posedge clk_a) begin
casex ({cs_n,rda_n})
2'b1x: dout_a <= 'hx;
2'b00: dout_a <= buffer[addr_a];
default: ;
endcase
end
always @(posedge clk_b) begin
if (!cs_n && !wrb_n) begin
buffer[addr_b] <= din_b;
end
end
function integer clogb2 (input integer depth);
begin
for(clogb2=0; depth>1; clogb2=clogb2+1)
depth = depth >> 1;
end
endfunction
endmodule
37. 用verilog实现一个同步双端口ram,深度16,位宽8bit。A口可读可写,B口可读可写。支持片选,读写请求,要求代码可综合。
module dpram_16x8 (
input clk,
input [7:0] din_a,
input [3:0] addr_a,
output [7:0] dout_a,
...
input [7:0] din_b,
output [7:0] dout_b,
input [3:0] addr_b,
...
);
...
endmodule
module sy_ture_dpram
#(
parameter WD = 8, //数据位宽
parameter AD = 4 //地址位宽
)
(
input clk ,
input cs_n ,
input aw_r_n ,
input [AD-1:0] addr_a ,
input [WD-1:0] din_a ,
output reg [WD-1:0] dout_a ,
input bw_r_n ,
input [AD-1:0] addr_b ,
input [WD-1:0] din_b ,
output reg [WD-1:0] dout_b
);
localparam DP = 2**AD;
reg [WD-1:0] buffer [DP-1:0];
always @(posedge clk) begin
casex ({cs_n,aw_r_n})
2'b1x: dout_a <= 'hx;
2'b01: buffer[addr_a] <= din_a;
2'b00: dout_a <= buffer[addr_a];
default: ;
endcase
end
always @(posedge clk) begin
casex ({cs_n,bw_r_n})
2'b1x: dout_b <= 'hx;
2'b01: buffer[addr_b] <= din_b;
2'b00: dout_b <= buffer[addr_b];
default: ;
endcase
end
/* always @(posedge clk) begin
casex ({cs_n,aw_r_n,bw_r_n})
3'b1xx: begin dout_a <= 'hx; dout_b <= 'hx; end
3'b000: begin dout_a <= buffer[addr_a]; dout_b <= buffer[addr_b]; end //A读B读
3'b001: begin dout_a <= buffer[addr_a]; buffer[addr_b] <= din_b; end //A读B写
3'b010: begin buffer[addr_a] <= din_a; dout_b <= buffer[addr_b]; end //A写B读
3'b011: begin //A写B写
if (addr_a == addr_b) begin
buffer[addr_a] <= din_a;
end else begin
buffer[addr_a] <= din_a;
buffer[addr_b] <= din_b;
end
end
default: ;
endcase
end */
endmodule
注:注释里的描述无法综合出ram块,但是逻辑没有问题。
即将入行的数字IC设计工程师