提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
前言
1. 结构图
2. 示例代码
2.1 SRAM BIST : MEM_BIST.V
// Author :
// Revision History : 2020-4-1
// Revision : 1.0
// Email :
//
`timescale 1ns/1ps
module mem_bist (
clk,
rstn,
error,
done
);
parameter data_size = 8;
parameter addr_size = 8;
parameter word_depth = 256;
input clk;
input rstn;
output reg error;
output reg done;
wire [data_size-1:0] datalock;
wire [addr_size-1:0] a;
wire [data_size-1:0] d;
wire [data_size-1:0] q;
wire wen;
wire cen;
control dut1 (
.clk(clk),
.rstn(rstn),
.wen(wen),
.cen(cen),
.addr(a),
.data(d),
.datalock(datalock)
);
data_comparator dut2 (
.clk(clk),
.rstn(rstn),
.q(q),
.datalock(datalock),
.wen(wen),
.error(error),
.done(done)
);
ram dut3 (
.clk(clk),
.cen(cen),
.wen(wen),
.a(a),
.d(d),
.q(q)
);
endmodule
2.1.1 代码分析
代码解释与功能说明
这段代码是一个 Verilog 模块,名为 mem_bist,用于实现一个内存内建自测试(Memory Built-In Self-Test, MBIST)的功能。MBIST 是一种嵌入式系统中常用的测试技术,用于在芯片制造完成后对内存进行自测试,以检测内存是否存在缺陷或故障。
1. 模块定义
module mem_bist (clk, rstn, error, done);
- clk: 时钟信号,用于同步模块内部的操作。
- rstn: 异步复位信号,低电平有效。用于初始化模块状态。
- error: 输出信号,表示测试过程中是否检测到错误。
- done: 输出信号,表示测试是否完成。
2. 参数定义
parameter data_size = 8;
parameter addr_size = 8;
parameter word_depth = 256;
- data_size: 数据总线的位宽,设置为 8 位。
- addr_size: 地址总线的位宽,设置为 8 位。
- word_depth: 内存的深度(即存储单元的数量),设置为 256 个单元。
3. 信号定义
wire [data_size-1:0] datalock;
wire [addr_size-1:0] a;
wire [data_size-1:0] d;
wire [data_size-1:0] q;
wire wen;
wire cen;
- datalock: 用于锁定数据的信号,通常用于在测试过程中保持数据的稳定性。
- a: 地址信号,用于访问内存中的特定存储单元。
- d: 写入数据信号,用于将数据写入内存。
- q: 读出数据信号,用于从内存中读取数据。
- wen: 写使能信号,高电平有效,表示允许写入操作。
- cen: 芯片使能信号,低电平有效,表示允许内存芯片工作。
4. 子模块实例化
4.1 控制模块 (control)
control dut1 (
.clk (clk),
.rstn (rstn),
.wen (wen),
.cen (cen),
.addr (a),
.data (d),
.datalock (datalock)
);
- control 模块负责生成控制信号,包括地址信号 a、写数据信号 d、写使能信号 wen 和芯片使能信号 cen。
- datalock 信号用于锁定数据,确保在测试过程中数据的稳定性。
4.2 数据比较模块 (data_comparator)
data_comparator dut2 (
.clk (clk),
.rstn (rstn),
.q (q),
.datalock (datalock),
.wen (wen),
.error (error),
.done (done)
);
- data_comparator 模块负责比较写入的数据和读出的数据,以检测内存是否存在错误。
- q: 从内存中读取的数据。
- datalock: 用于锁定数据的信号。
- wen: 写使能信号。
- error: 输出信号,表示是否检测到错误。
- done: 输出信号,表示测试是否完成。
4.3 内存模块 (ram)
ram dut3 (
.clk (clk),
.cen (cen),
.wen (wen),
.a (a),
.d (d),
.q (q)
);
- ram 模块是一个简单的内存模块,用于存储数据。
- clk: 时钟信号。
- cen: 芯片使能信号。
- wen: 写使能信号。
- a: 地址信号。
- d: 写入数据信号。
- q: 读出数据信号。
5. 功能描述
5.1 控制模块 (control)
- 功能: 生成控制信号,包括地址信号 a、写数据信号 d、写使能信号 wen 和芯片使能信号 cen。
- 工作流程:
- 在复位信号 rstn 的控制下,初始化所有控制信号。
- 生成地址信号 a,依次访问内存中的每个存储单元。
- 生成写数据信号 d,将测试数据写入内存。
- 生成写使能信号 wen 和芯片使能信号 cen,控制内存的写入操作。
5.2 数据比较模块 (data_comparator)
- 功能: 比较写入的数据和读出的数据,检测内存是否存在错误。
- 工作流程:
- 在复位信号 rstn 的控制下,初始化所有比较逻辑。
- 读取内存中的数据 q,并与写入的数据 d 进行比较。
- 如果数据不一致,设置 error 信号为高电平,表示检测到错误。
- 当所有数据比较完成后,设置 done 信号为高电平,表示测试完成。
5.3 内存模块 (ram)
- 功能: 存储数据,并根据控制信号进行读写操作。
- 工作流程:
- 在时钟信号 clk 的控制下,根据芯片使能信号 cen 和写使能信号 wen 进行读写操作。
- 当 cen 为低电平且 wen 为高电平时,将写数据信号 d 写入指定地址 a。
- 当 cen 为低电平且 wen 为低电平时,从指定地址 a 读取数据,并输出到 q。
6. 总体功能
mem_bist 模块通过实例化 control、data_comparator 和 ram 三个子模块,实现了内存内建自测试的功能。具体工作流程如下:
- 初始化: 在复位信号 rstn 的控制下,初始化所有控制信号和比较逻辑。
- 写入数据: control 模块生成地址信号 a 和写数据信号 d,并通过 wen 和 cen 控制 ram 模块将数据写入内存。
- 读取数据: control 模块生成地址信号 a,并通过 cen 控制 ram 模块从内存中读取数据。
- 数据比较: data_comparator 模块比较读取的数据 q 和写入的数据 d,如果数据不一致,设置 error 信号为高电平。
- 测试完成: 当所有数据比较完成后,设置 done 信号为高电平,表示测试完成。
7. 应用场景
- 芯片制造测试: 在芯片制造完成后,使用 MBIST 技术对内存进行自测试,以检测内存是否存在缺陷或故障。
- 系统级测试: 在嵌入式系统中,使用 MBIST 技术对内存进行定期测试,以确保系统的可靠性和稳定性。
- 故障诊断: 在系统运行过程中,如果检测到内存错误,可以使用 MBIST 技术进行故障诊断,以确定故障的具体位置。
8. 总结
mem_bist 模块通过实例化 control、data_comparator 和 ram 三个子模块,实现了内存内建自测试的功能。通过生成控制信号、写入数据、读取数据和数据比较,mem_bist 模块能够检测内存是否存在错误,并在测试完成后输出 error 和 done 信号。这种设计方法在芯片制造测试、系统级测试和故障诊断中具有广泛的应用。
2.2 CONTROL.V
// Author :
// Revision History : 2020-4-1
// Revision : 1.0
// Email :
//
`timescale 1ns/1ps
module control (
clk,
rstn,
wen,
cen,
addr,
data,
datalock
);
parameter addr_size = 8;
parameter data_size = 8;
parameter word_depth = 256;
input clk;
input rstn;
output wen;
output cen;
output [addr_size-1:0] addr;
output [data_size-1:0] data;
output [data_size-1:0] datalock;
reg wen;
reg cen;
reg [addr_size-1:0] addr;
reg [data_size-1:0] data;
reg [data_size-1:0] datalock;
reg [1:0] pattern;
reg i;
reg [3:0] state;
parameter data_b1 = 8'b0000_0000;
parameter data_b2 = 8'b0000_1111;
parameter data_b3 = 8'b0101_0101;
parameter data_b4 = 8'b0011_0011;
parameter idle = 4'd0,
s1 = 4'd1,
s2 = 4'd2,
s3 = 4'd3,
s4 = 4'd4,
s5 = 4'd5,
s6 = 4'd6,
updata = 4'd7,
stop = 4'd8;
always @ (posedge clk or negedge rstn) begin
if (!rstn) begin
cen <= 1'b1;
wen <= 1'b0;
pattern <= 2'b0;
data <= data_b1;
addr <= 8'd0;
datalock <= 8'd0;
i <= 1'b0;
state <= idle;
end else begin
case (state)
idle: begin
cen <= 1'b0;
wen <= 1'b0;
addr <= word_depth-1;
data <= data_b1;
pattern <= 2'd0;
i <= 1'b0;
state <= s1;
end
s1: begin
if (addr > 8'd0) begin
addr <= addr - 8'd1;
state <= s1;
end else begin
addr <= 8'd0;
wen <= 1'b1;
data <= ~data;
datalock <= data;
state <= s2;
end
end
s2: begin
if (wen == 0) begin
wen <= 1'b1;
datalock <= ~datalock;
state <= s2;
end else if (i == 0) begin
wen <= 1'b0;
i <= 1'b1;
state <= s2;
end else if (addr < word_depth - 1) begin
addr <= addr + 8'd1;
i <= 1'b0;
datalock <= ~datalock;
state <= s2;
end else begin
addr <= 8'd0;
data <= ~data;
state <= s3;
i <= 1'b0;
datalock <= data;
end
end
s3: begin
if (wen == 1'b0) begin
wen <= 1'b1;
datalock <= ~datalock;
state <= s3;
end else if (i == 0) begin
wen <= 1'b0;
i <= 1'b1;
state <= s3;
end else if (addr < word_depth - 1) begin
addr <= addr + 8'd1;
i <= 1'b0;
datalock <= ~datalock;
state <= s3;
end else begin
addr <= word_depth - 1;
data <= ~data;
i <= 1'b0;
datalock <= data;
state <= s4;
end
end
s4: begin
if (wen == 0) begin
wen <= 1'b1;
datalock <= ~datalock;
state <= s4;
end else if (i == 0) begin
wen <= 1'b0;
i <= 1'b1;
state <= s4;
end else if (addr > 8'd0) begin
addr <= addr - 8'd1;
datalock <= ~datalock;
i <= 1'b0;
state <= s4;
end else begin
addr <= word_depth - 1;
data <= ~data;
datalock <= data;
i <= 1'b0;
state <= s5;
end
end
s5: begin
if (wen == 0) begin
wen <= 1'b1;
datalock <= ~datalock;
state <= s5;
end else if (i == 0) begin
i <= 1'b1;
wen <= 1'b0;
state <= s5;
end else if (addr > 8'd0) begin
i <= 1'b0;
addr <= addr - 8'd1;
datalock <= ~datalock;
state <= s5;
end else begin
addr <= 8'd0;
datalock <= data;
state <= s6;
end
end
s6: begin
if (addr < word_depth - 1) begin
addr <= addr + 8'd1;
end else begin
wen <= 0;
i <= 0;
state <= updata;
end
end
updata: begin
if (pattern == 0) begin
data <= data_b2;
pattern <= pattern + 1;
state <= s1;
end else if (pattern == 1) begin
data <= data_b3;
pattern <= pattern + 1;
state <= s1;
end else if (pattern == 2) begin
data <= data_b4;
pattern <= pattern + 1;
state <= s1;
end else begin
state <= stop;
end
end
stop: begin
cen <= 1;
end
default: state <= idle;
endcase
end
end
endmodule
2.2.1功能说明
control 模块通过有限状态机实现了一个内存测试流程,具体步骤如下:
- 初始化:在复位信号 rstn 的控制下,初始化所有控制信号和状态。
- 测试模式选择:通过 pattern 寄存器选择不同的测试数据模式。
- 地址递增/递减:根据当前状态,递增或递减地址 addr,以访问内存中的不同位置。
- 数据写入:在写使能信号 wen 的控制下,将数据 data 写入内存。
- 数据锁定:通过 datalock 信号锁定数据,用于后续的比较操作。
- 状态转换:根据当前状态和条件,转换到下一个状态,继续测试流程。
- 测试完成:在 stop 状态,设置 cen 信号为高,表示测试完成。
2.3 DATA_COMPATATOR.V
// Author :
// Revision History : 2020-4-1
// Revision : 1.0
// Email :
//
`timescale 1ns/1ps
module data_comparator (
clk,
rstn,
datalock,
wen,
q,
error,
done
);
parameter addr_size = 8,
data_size = 8,
word_depth = 256;
input wen;
input [data_size-1:0] datalock;
input clk;
input rstn;
input [data_size-1:0] q;
output error;
output done;
reg error;
reg done;
reg [data_size-1:0] q1;
reg [data_size-1:0] datalock1;
always @ (posedge clk or negedge rstn) begin
if (!rstn) begin
error <= 0;
done <= 0;
q1 <= 8'd0;
datalock1 <= 8'd0;
end else begin
q1 <= q;
datalock1 <= datalock;
if (wen == 1'b1) begin
if (datalock1 == q1) begin
error <= 0;
done <= 1;
end else begin
error <= 1;
done <= 1;
end
end else begin
error <= error;
done <= done;
end
end
end
endmodule
2.3.1 功能说明
data_comparator 模块通过比较从内存读取的数据(q)和预期的锁定数据(datalock),以检测内存测试过程中是否存在错误。具体步骤如下:
- 初始化:在复位信号 rstn 的控制下,初始化所有输出信号和内部寄存器。
- 数据存储:在每个时钟周期,将从内存读取的数据(q)和预期的锁定数据(datalock)存储到内部寄存器 q1 和 datalock1。
- 数据比较:如果 wen 信号为高(表示当前操作是写入),则比较 datalock1 和 q1:
- 如果数据匹配(datalock1 == q1),则设置 error 为0,表示没有错误,并设置 done 为1,表示测试完成。
- 如果数据不匹配,则设置 error 为1,表示检测到错误,并设置 done 为1,表示测试完成。
- 保持状态:如果 wen 信号为低(表示当前操作不是写入),则保持 error 和 done 的当前状态不变。