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

143 lines
6.4 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 Top_Project (
// ==========================================
// 1. 系统全局时钟与复位输入
// ==========================================
input wire sys_clk_50m, // 开发板上的 50MHz 晶振输入
input wire sys_rst_n, // 开发板上的复位按键 (低电平有效按下为0)
// ==========================================
// 2. 外部 SDRAM 物理芯片接口 (匹配 W9825G6JH-6)
// ==========================================
output wire [12:0] sdram_ADDR, // 13位行地址 / 9位列地址复用
output wire [1:0] sdram_BA, // 2位 Bank 地址
inout wire [15:0] sdram_DQ, // 16位数据总线 (必须是 inout 双向类型)
output wire [1:0] sdram_DQM, // 数据掩码
output wire sdram_CASn, // 列选通 (低有效)
output wire sdram_CKE, // 时钟使能
output wire sdram_CSn, // 片选 (低有效)
output wire sdram_RASn, // 行选通 (低有效)
output wire sdram_WEn, // 写使能 (低有效)
output wire sdram_CLK, // 输出给 SDRAM 芯片的时钟引脚 (带相位偏移)
// ==========================================
// 3. 测试状态指示灯 (新增)
// ==========================================
output wire led_test_pass, // 测试通过指示灯 (建议接绿色 LED)
output wire led_test_fail // 测试失败指示灯 (建议接红色 LED)
);
// ==========================================
// 内部信号声明
// ==========================================
wire clk_100m; // PLL 输出的 100MHz (0度相位给 FPGA 内部逻辑用)
wire clk_100m_shift; // PLL 输出的 100MHz (-90度相位给 SDRAM 芯片用)
wire pll_locked; // PLL 锁定指示信号 (高电平表示时钟已稳定输出)
wire [15:0] sdram_DQ_read; // 从双向引脚分离出的读数据
wire [15:0] sdram_DQ_write; // 准备输出到双向引脚的写数据
wire [15:0] sdram_DQ_writeEnable; // 控制总线方向的写使能信号
// --- 新增:用户逻辑交互总线连线 ---
wire user_cmd_valid;
wire user_cmd_ready;
wire user_is_write;
wire [23:0] user_address;
wire [15:0] user_write_data;
wire user_rsp_valid;
wire [15:0] user_rsp_data;
// ==========================================
// 模块 1例化系统 PLL IP 核 (sys_pll)
// ==========================================
sys_pll u_sys_pll (
// ALTPLL 的 areset 是高电平有效。
// 因为板载按键 sys_rst_n 是低电平有效,所以这里必须加非逻辑 '~'
.areset (~sys_rst_n),
.inclk0 (sys_clk_50m),
.c0 (clk_100m), // 内部 100MHz 时钟
.c1 (clk_100m_shift),// 偏移 100MHz 时钟
.locked (pll_locked)
);
// 将带有 -90 度相位偏移的时钟直接连到顶层输出引脚,送给 SDRAM 物理芯片
assign sdram_CLK = clk_100m_shift;
// ==========================================
// 模块 2复位信号反相与同步处理
// ==========================================
// SpinalHDL 生成的 MyCustomSdramTop 是【高电平复位】的。
// 我们在此生成一个全局的【高电平有效】复位信号 system_reset。
wire system_reset;
assign system_reset = (~sys_rst_n) | (~pll_locked);
// ==========================================
// 模块 3处理 SDRAM 双向数据总线 (inout 三态门)
// ==========================================
// 读取通道:直接将外部管脚状态输入给控制器
assign sdram_DQ_read = sdram_DQ;
// 写入通道:通过三态门控制
// 当控制器拉高写使能 (16'hFFFF) 时,将写数据推送到总线上。
assign sdram_DQ = (sdram_DQ_writeEnable == 16'hFFFF) ? sdram_DQ_write : 16'hZZZZ;
// ==========================================
// 模块 4例化由 SpinalHDL 生成的 SDRAM 控制器
// ==========================================
MyCustomSdramTop u_sdram_ctrl (
// --- 时钟与复位 ---
.clk (clk_100m), // 接入稳定的 100MHz 内部时钟
.reset (system_reset), // 接入经过处理的高有效复位信号
// --- 连接到底层的 SDRAM 物理接口信号 ---
.io_sdram_ADDR (sdram_ADDR),
.io_sdram_BA (sdram_BA),
.io_sdram_DQ_read (sdram_DQ_read),
.io_sdram_DQ_write (sdram_DQ_write),
.io_sdram_DQ_writeEnable (sdram_DQ_writeEnable),
.io_sdram_DQM (sdram_DQM),
.io_sdram_CASn (sdram_CASn),
.io_sdram_CKE (sdram_CKE),
.io_sdram_CSn (sdram_CSn),
.io_sdram_RASn (sdram_RASn),
.io_sdram_WEn (sdram_WEn),
// --- 连接到测试模块的用户逻辑接口 ---
.io_userCmdValid (user_cmd_valid),
.io_userCmdReady (user_cmd_ready),
.io_userIsWrite (user_is_write),
.io_userAddress (user_address),
.io_userWriteData (user_write_data),
.io_userWriteMask (2'b11), // 写数据掩码 (2'b00表示16位全部写入不屏蔽)
.io_userRspValid (user_rsp_valid),
.io_userRspData (user_rsp_data)
);
// ==========================================
// 模块 5例化读写校验测试模块 (新增)
// ==========================================
Sdram_Tester #(
.TEST_LENGTH(24'd4096) // 测试的地址长度,这里设置为测试前 4096 个地址
) u_tester (
.clk (clk_100m),
// 注意Tester 内部是下降沿复位 (低有效),所以需要将高有效的 system_reset 取反
.rst_n (~system_reset),
// --- 挂载到 SDRAM 用户总线 ---
.cmd_valid (user_cmd_valid),
.cmd_ready (user_cmd_ready),
.is_write (user_is_write),
.address (user_address),
.write_data (user_write_data),
.rsp_valid (user_rsp_valid),
.rsp_data (user_rsp_data),
// --- 连接到顶层外部引脚 ---
.test_pass (led_test_pass),
.test_fail (led_test_fail)
);
endmodule