SDRAM_spinal/Sdram_Tester.v
2026-04-09 10:44:54 +08:00

132 lines
4.5 KiB
Verilog
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

`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