大三电子信息,跟着B站和CSDN的教程学了Verilog语法,状态机也能看懂,但一到自己写SPI主机就卡住:不知道从哪个状态开始、CPOL和CPHA怎么在代码里体现、采样沿和移位沿到底谁先谁后。仿真波形看着像对又像错,上板更不敢烧。想问问过来人,从”看懂代码”到”独立写出可综合模块”中间到底缺了哪一步训练?有没有具体的练手顺序推荐?
2026年FPGA零基础自学,每天两小时坚持了三个月,为什么还是写不出一个能综合的SPI主机模块?
3 个回答

先说结论:你缺的不是语法,是「先画图再写码」的习惯。SPI 这东西,别一上来就开 Vivado 敲 module。拿张纸,把 CPOL=0/CPHA=0 到 1/1 四种模式的 SCLK、MOSI、MISO、CS_N 波形各画一遍,标清楚哪条边沿采样、哪条边沿移位。画的时候你会突然发现:CPHA=0 是先采样后移位,CPHA=1 反过来,CPOL 只决定空闲电平。这四张图没画明白,代码写出来必然是「看着像对」。画完之后再写状态机,原则是每个状态只干一件事:IDLE、CS 拉低、发一位、收一位、移位、计数、结束。状态转移条件就是「第几个边沿到了」。最后别急着上板,先用 ModelSim 写个 testbench,自己给自己发数据,看收发是不是一致。这一步过了,综合基本就没问题。你现在卡住,恰恰是因为跳过了手绘和自测这两步。你目前用的是哪版 Vivado,仿真跑过完整收发回环吗?

你这三个月的状态我太熟了,说白了就是卡在「协议没在脑子里跑起来」这一步。给你一个我觉得最省事的练法:先别写SPI主机,先写一个纯移位寄存器。对,就是那种只做「时钟来一下,数据挪一位」的模块,不涉及CS、不涉及模式。写完之后,你自己在心里数:SCLK上升沿到了,我是先采MISO还是先推MOSI?这个问题想清楚,CPHA其实就懂了一半。CPHA=0是先采样再移位,CPHA=1是先移位再采样,CPOL只管空闲是高还是低,跟先来后到没关系。很多人写不出来,是因为把这两个概念混在一起记了。建议你今晚就拿张A4纸,把四种模式的波形各画一遍,画完再回去看你的代码,大概率一眼就能看出问题在哪。你现在用的是哪块板子或者哪个仿真环境?

你现在缺的不是再学一遍语法,而是一条能把「协议」和「代码」接上的小流水线。给你个可落地的顺序,按周来。
第一周别碰 SPI,先写一个最裸的移位寄存器模块,只有 clk、rst_n、din、dout、shift_en 这几个口,跑仿真看数据一位位挪出去。这一步的意义是让「时钟沿驱动状态」变成肌肉记忆。第二周再写一个分频器,把 50M 降到 1M 左右,用计数器实现,别用 IP。第三周才开始 SPI:把主机拆成「一个移位寄存器 + 一个位计数器 + 一个状态机」三块,状态机只负责 CS 什么时候拉低、什么时候发、什么时候收、什么时候结束,别让它去管数据挪位。
CPOL 和 CPHA 别硬记,落到代码里就两件事:CPOL 决定 SCLK 空闲时是高还是低,CPHA 决定第一拍是先采样还是先移位。你把 sclk 写成「空闲电平 + 翻转」的形式,采样沿和移位沿自然就出来了。
一个容易踩的坑:很多人一上来就想支持四种模式,结果参数化没写对,仿真全乱。建议先只做 CPOL=0、CPHA=0,跑通再说。仿真时 testbench 自己发一组已知数据,收回来对比,不一致就抓波形看是移位多了一拍还是少了一拍。
风险提醒:别把「上板」当验收标准,很多 bug 在仿真阶段就该拦住。你现在的环境是 Vivado 还是 Quartus?这会影响我推荐你用哪个仿真流程。
发表回答
登录后可在本页底部提交回答