132 lines
4.5 KiB
Verilog
132 lines
4.5 KiB
Verilog
`timescale 1ns/1ps
|
||
|
||
module Sdram_Tester #(
|
||
parameter TEST_LENGTH = 24'd1048576
|
||
)(
|
||
input wire clk,
|
||
input wire rst_n,
|
||
|
||
// --- 连接到 SDRAM 控制器的用户接口 ---
|
||
output reg cmd_valid,
|
||
input wire cmd_ready,
|
||
output reg is_write,
|
||
output reg [23:0] address,
|
||
output wire [15:0] write_data,
|
||
|
||
input wire rsp_valid,
|
||
input wire [15:0] rsp_data,
|
||
|
||
// --- 外部 LED 状态指示灯 ---
|
||
output reg test_pass, // 绿色 LED,成功后闪烁
|
||
output reg test_fail // 红色 LED,发生错误时常亮
|
||
);
|
||
|
||
// ==========================================
|
||
// 状态机定义
|
||
// ==========================================
|
||
localparam S_INIT = 3'd0; // 等待 SDRAM 初始化
|
||
localparam S_WRITE = 3'd1; // 发起单次写命令
|
||
localparam S_READ = 3'd2; // 发起单次读命令 (交替操作)
|
||
localparam S_WAIT_RSP = 3'd3; // 等待读响应并比对
|
||
localparam S_DONE = 3'd4; // 测试成功完成
|
||
localparam S_ERROR = 3'd5; // 数据校验错误
|
||
|
||
reg [2:0] state;
|
||
reg [15:0] init_cnt; // 用于上电延时计数
|
||
reg [23:0] test_addr; // 当前正在测试的地址
|
||
|
||
// 新增:用于控制 LED 闪烁的 26 位计数器
|
||
reg [25:0] blink_cnt;
|
||
|
||
// ==========================================
|
||
// 测试数据生成器
|
||
// ==========================================
|
||
// 地址低16位 异或 0x5A5A,保证每个地址的数据唯一且具有翻转特性
|
||
wire [15:0] expected_data = test_addr[15:0] ^ 16'h5A5A;
|
||
assign write_data = expected_data;
|
||
|
||
// ==========================================
|
||
// 主状态机控制逻辑
|
||
// ==========================================
|
||
always @(posedge clk or negedge rst_n) begin
|
||
if (!rst_n) begin
|
||
state <= S_INIT;
|
||
init_cnt <= 16'd0;
|
||
test_addr <= 24'd0;
|
||
blink_cnt <= 26'd0; // 复位闪烁计数器
|
||
cmd_valid <= 1'b0;
|
||
is_write <= 1'b0;
|
||
address <= 24'd0;
|
||
test_pass <= 1'b0;
|
||
test_fail <= 1'b0;
|
||
end else begin
|
||
case (state)
|
||
// 1. 等待初始化 (200us @ 100MHz)
|
||
S_INIT: begin
|
||
if (init_cnt < 16'd20000) begin
|
||
init_cnt <= init_cnt + 1'b1;
|
||
end else begin
|
||
state <= S_WRITE;
|
||
end
|
||
end
|
||
|
||
// 2. 写操作
|
||
S_WRITE: begin
|
||
cmd_valid <= 1'b1;
|
||
is_write <= 1'b1;
|
||
address <= test_addr;
|
||
|
||
if (cmd_valid && cmd_ready) begin
|
||
cmd_valid <= 1'b0;
|
||
state <= S_READ;
|
||
end
|
||
end
|
||
|
||
// 3. 读操作
|
||
S_READ: begin
|
||
cmd_valid <= 1'b1;
|
||
is_write <= 1'b0;
|
||
address <= test_addr;
|
||
|
||
if (cmd_valid && cmd_ready) begin
|
||
cmd_valid <= 1'b0;
|
||
state <= S_WAIT_RSP;
|
||
end
|
||
end
|
||
|
||
// 4. 数据比对
|
||
S_WAIT_RSP: begin
|
||
if (rsp_valid) begin
|
||
if (rsp_data == expected_data) begin
|
||
if (test_addr == TEST_LENGTH - 1) begin
|
||
state <= S_DONE;
|
||
end else begin
|
||
test_addr <= test_addr + 2'b11;
|
||
state <= S_WRITE;
|
||
end
|
||
end else begin
|
||
state <= S_ERROR;
|
||
end
|
||
end
|
||
end
|
||
|
||
// 5. 测试通过:LED 闪烁逻辑
|
||
S_DONE: begin
|
||
// 计数器不断累加
|
||
blink_cnt <= blink_cnt + 1'b1;
|
||
test_pass <= blink_cnt[25];
|
||
test_fail <= 1'b0;
|
||
end
|
||
|
||
// 6. 测试失败:红灯常亮
|
||
S_ERROR: begin
|
||
test_pass <= 1'b0;
|
||
test_fail <= 1'b1;
|
||
end
|
||
|
||
default: state <= S_INIT;
|
||
endcase
|
||
end
|
||
end
|
||
|
||
endmodule |