SDRAM_spinal/Sdram_Tester.v

132 lines
4.5 KiB
Coq
Raw Normal View History

2026-04-09 10:44:54 +08:00
`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