### 一、基础模块(同步/边沿检测/分频)
#### 1. SyncTwoStage.v(异步信号同步,消除亚稳态)
```verilog
module SyncTwoStage(
input wire clk, // 目标时钟域(SYS_CLK)
input wire rst_n, // 低电平复位(0=复位)
input wire din, // 异步输入(外部传感器SIGNAL)
output reg dout // 同步后输出(无亚稳态)
);
reg din_sync1; // 第一级同步寄存器
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
din_sync1 <= 1'b0;
dout <= 1'b0;
end else begin
din_sync1 <= din; // 第一级采样
dout <= din_sync1; // 第二级同步
end
end
endmodule
```
#### 2. EdgeDetector.v(边沿检测,生成1周期脉冲)
```verilog
module EdgeDetector(
input wire SYS_CLK, // 系统时钟
input wire RST_N, // 低电平复位
input wire sig_in, // 同步输入信号
output reg rise, // 上升沿脉冲(1周期)
output reg fall // 下降沿脉冲(1周期)
);
reg sig_prev; // 前态寄存器
always @(posedge SYS_CLK or negedge RST_N) begin
if (!RST_N) begin
sig_prev <= 1'b0;
rise <= 1'b0;
fall <= 1'b0;
end else begin
sig_prev <= sig_in;
rise <= sig_in & ~sig_prev; // 上升沿:当前1,前态0
fall <= ~sig_in & sig_prev; // 下降沿:当前0,前态1
end
end
endmodule
```
#### 3. Div2Gen.v(2分频生成,50%占空比)
```verilog
module Div2Gen(
input wire SYS_CLK, // 系统时钟
input wire RST_N, // 低电平复位
input wire sync_signal, // 同步输入信号(来自SyncTwoStage)
output reg div2 // 2分频输出
);
reg signal_prev; // 前态寄存器(检测上升沿)
always @(posedge SYS_CLK or negedge RST_N) begin
if (!RST_N) begin
signal_prev <= 1'b0;
div2 <= 1'b0;
end else begin
signal_prev <= sync_signal;
if (sync_signal & ~signal_prev) begin // 检测上升沿
div2 <= ~div2; // 翻转输出,实现50%占空比
end
end
end
endmodule
```
#### 4. DivNGen.v(N分频生成,支持8/16/24/32/40分频)
```verilog
module DivNGen(
input wire SYS_CLK, // 系统时钟
input wire RST_N, // 低电平复位
input wire [2:0] WHEEL, // 分频配置:001=8,010=16,011=24,100=32,101=40
input wire sync_signal, // 同步输入信号
output reg div_N, // N分频输出(50%占空比)
output reg wheel_valid // 配置有效标志(1=有效)
);
reg [5:0] div_cnt; // 计数器(最大支持40分频)
reg [5:0] max_cnt; // 计数阈值(N/2 - 1)
reg signal_prev; // 前态寄存器
reg first_edge; // 首个上升沿标记(同步启动)
// 分频系数配置(组合逻辑)
always @(*) begin
case(WHEEL)
3'b001: begin max_cnt = 6'd3; wheel_valid = 1'b1; end // 8分频:(8/2)-1=3
3'b010: begin max_cnt = 6'd7; wheel_valid = 1'b1; end // 16分频:(16/2)-1=7
3'b011: begin max_cnt = 6'd11; wheel_valid = 1'b1; end // 24分频:(24/2)-1=11
3'b100: begin max_cnt = 6'd15; wheel_valid = 1'b1; end // 32分频:(32/2)-1=15
3'b101: begin max_cnt = 6'd19; wheel_valid = 1'b1; end // 40分频:(40/2)-1=19
default: begin max_cnt = 6'd3; wheel_valid = 1'b0; end // 无效配置
endcase
end
// 首个上升沿检测
always @(posedge SYS_CLK or negedge RST_N) begin
if (!RST_N) begin
signal_prev <= 1'b0;
first_edge <= 1'b1;
end else begin
signal_prev <= sync_signal;
if (first_edge && (sync_signal & ~signal_prev)) begin
first_edge <= 1'b0;
end
end
end
// N分频逻辑
always @(posedge SYS_CLK or negedge RST_N) begin
if (!RST_N) begin
div_cnt <= 6'd0;
div_N <= 1'b0;
end else if (first_edge && (sync_signal & ~signal_prev)) begin
div_N <= ~div_N; // 首个上升沿直接翻转
end else if (!first_edge && wheel_valid && (sync_signal & ~signal_prev)) begin
if (div_cnt == max_cnt) begin
div_N <= ~div_N; // 计数到阈值翻转
div_cnt <= 6'd0;
end else begin
div_cnt <= div_cnt + 1'b1;
end
end
end
endmodule
```
### 二、核心模块(计数锁存/FIFO/命令缓存)
#### 5. CntLatch1.v(2分频计数锁存,双缓冲+精准清零)
```verilog
module CntLatch1(
input wire SYS_CLK, // 系统时钟
input wire RST_N, // 低电平复位
input wire STM32_RD_DONE, // 读取完成(全部数据已读)
input wire div2_rise, // 2分频上升沿(计数启动)
input wire div2_fall, // 2分频下降沿(计数停止)
output reg [23:0] latch1_data, // 锁存数据(供FIFO)
output reg latch1_valid, // 数据有效标志
output reg latch1_overflow, // 溢出标志(1=计数超24位)
input wire fifo_wr_ack // FIFO写确认(数据已入FIFO)
);
reg [23:0] cnt1; // 24位计数器(最大16777215)
reg en_cnt1; // 计数使能
reg overflow_flag; // 溢出临时标志
reg [23:0] latch_buf; // 双缓冲(FIFO满时暂存,防覆盖)
reg buf_valid; // 缓冲有效标志
// 计数控制逻辑
always @(posedge SYS_CLK or negedge RST_N) begin
if (!RST_N) begin
cnt1 <= 24'd0;
en_cnt1 <= 1'b0;
overflow_flag <= 1'b0;
end else if (STM32_RD_DONE) begin
cnt1 <= 24'd0; // 读取完成,计数器清零
en_cnt1 <= 1'b0;
overflow_flag <= 1'b0;
end else if (div2_rise) begin
en_cnt1 <= 1'b1; // 上升沿启动计数
overflow_flag <= 1'b0;
end else if (div2_fall) begin
en_cnt1 <= 1'b0; // 下降沿停止计数
latch_buf <= cnt1; // 锁存数据到双缓冲
buf_valid <= 1'b1;
latch1_overflow <= overflow_flag;
end else if (en_cnt1) begin
if (cnt1 == 24'hFFFFFF) begin
overflow_flag <= 1'b1; // 检测溢出
cnt1 <= 24'hFFFFFF; // 保持最大值,避免翻转
end else begin
cnt1 <= cnt1 + 1'b1; // 正常计数
end
end
end
// 双缓冲→FIFO输出逻辑(FIFO空闲时自动写入)
always @(posedge SYS_CLK or negedge RST_N) begin
if (!RST_N) begin
latch1_data <= 24'd0;
latch1_valid <= 1'b0;
end else if (fifo_wr_ack) begin
latch1_valid <= 1'b0; // FIFO写入成功,清除有效标志
buf_valid <= 1'b0; // 清空缓冲
end else if (buf_valid && !latch1_valid) begin
latch1_data <= latch_buf; // 缓冲有数据且FIFO空闲,输出到FIFO
latch1_valid <= 1'b1;
end
end
// 读取完成强制清缓冲(确保锁存器完全复位)
always @(posedge SYS_CLK or negedge RST_N) begin
if (!RST_N) begin
buf_valid <= 1'b0;
end else if (STM32_RD_DONE) begin
buf_valid <= 1'b0;
latch1_valid <= 1'b0;
end
end
endmodule
```
#### 6. CntLatch2.v(N分频计数锁存,双缓冲+独立异常编码)
```verilog
module CntLatch2(
input wire SYS_CLK, // 系统时钟
input wire RST_N, // 低电平复位
input wire STM32_RD_DONE, // 读取完成(全部数据已读)
input wire div_N_rise, // N分频上升沿(计数启动)
input wire div_N_fall, // N分频下降沿(计数停止)
input wire wheel_valid, // 分频配置有效标志
output reg [23:0] latch2_data, // 锁存数据(供FIFO)
output reg latch2_valid, // 数据有效标志
output reg latch2_overflow, // 溢出标志(1=计数超24位)
output reg latch2_invalid_cfg, // 配置无效标志(1=无效)
input wire fifo_wr_ack // FIFO写确认(数据已入FIFO)
);
reg [23:0] cnt2; // 24位计数器
reg en_cnt2; // 计数使能
reg overflow_flag; // 溢出临时标志
reg [23:0] latch_buf; // 双缓冲(防覆盖)
reg buf_valid; // 缓冲有效标志
reg invalid_cfg_reg; // 配置无效临时标志
// 计数控制逻辑
always @(posedge SYS_CLK or negedge RST_N) begin
if (!RST_N) begin
cnt2 <= 24'd0;
en_cnt2 <= 1'b0;
overflow_flag <= 1'b0;
invalid_cfg_reg <= 1'b0;
end else if (STM32_RD_DONE) begin
cnt2 <= 24'd0;
en_cnt2 <= 1'b0;
overflow_flag <= 1'b0;
invalid_cfg_reg <= 1'b0;
end else if (div_N_rise) begin
en_cnt2 <= 1'b1;
overflow_flag <= 1'b0;
invalid_cfg_reg <= ~wheel_valid; // 记录配置有效性
end else if (div_N_fall) begin
en_cnt2 <= 1'b0;
latch_buf <= cnt2;
buf_valid <= 1'b1;
latch2_overflow <= overflow_flag;
latch2_invalid_cfg <= invalid_cfg_reg;
end else if (en_cnt2 && wheel_valid) begin
if (cnt2 == 24'hFFFFFF) begin
overflow_flag <= 1'b1;
cnt2 <= 24'hFFFFFF;
end else begin
cnt2 <= cnt2 + 1'b1;
end
end
end
// 双缓冲→FIFO输出逻辑
always @(posedge SYS_CLK or negedge RST_N) begin
if (!RST_N) begin
latch2_data <= 24'd0;
latch2_valid <= 1'b0;
end else if (fifo_wr_ack) begin
latch2_valid <= 1'b0;
buf_valid <= 1'b0;
end else if (buf_valid && !latch2_valid) begin
latch2_data <= latch_buf;
latch2_valid <= 1'b1;
end
end
// 读取完成强制清缓冲
always @(posedge SYS_CLK or negedge RST_N) begin
if (!RST_N) begin
buf_valid <= 1'b0;
end else if (STM32_RD_DONE) begin
buf_valid <= 1'b0;
latch2_valid <= 1'b0;
end
end
endmodule
```
#### 7. SyncFIFO.v(数据FIFO,防溢出/下溢+写确认)
```verilog
module SyncFIFO #(
parameter DATA_WIDTH = 24, // 数据宽度(匹配锁存器)
parameter DEPTH = 16, // FIFO深度(2的幂,支持16个数据)
parameter HALF_DEPTH = 8 // 半满阈值
)(
input wire clk, // 系统时钟
input wire rst_n, // 低电平复位
input wire wr_en, // 写使能(1=允许写入,需!full)
input wire [DATA_WIDTH-1:0] wr_data, // 写入数据
input wire rd_en, // 读使能(1=允许读取,需!empty)
output reg [DATA_WIDTH-1:0] rd_data, // 读出数据
output reg empty, // 空标志(1=无数据)
output reg full, // 满标志(1=已满)
output reg half_full, // 半满标志(1=数据≥HALF_DEPTH)
output reg wr_ack // 写确认(1=数据已写入)
);
reg [DATA_WIDTH-1:0] fifo_mem[DEPTH-1:0]; // FIFO存储数组
localparam PTR_WIDTH = $clog2(DEPTH); // 指针位宽(自动计算)
reg [PTR_WIDTH-1:0] wr_ptr; // 写指针(指向下次写入地址)
reg [PTR_WIDTH-1:0] rd_ptr; // 读指针(指向下次读取地址)
reg [PTR_WIDTH-1:0] data_cnt; // 当前数据量(0~DEPTH)
// 空/满/半满标志+数据计数(修复溢出/下溢)
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
data_cnt <= {PTR_WIDTH{1'b0}};
empty <= 1'b1;
full <= 1'b0;
half_full <= 1'b0;
wr_ack <= 1'b0;
end else begin
wr_ack <= 1'b0;
case ({wr_en, rd_en})
2'b00: data_cnt <= data_cnt; // 无读写,计数不变
2'b01: data_cnt <= (data_cnt > 0) ? data_cnt - 1 : 0; // 只读,防下溢
2'b10: begin // 只写,防上溢
if (data_cnt < DEPTH) begin
data_cnt <= data_cnt + 1;
wr_ack <= 1'b1; // 写成功,输出确认
end
end
2'b11: data_cnt <= data_cnt; // 同时读写,计数不变
endcase
empty <= (data_cnt == 0);
full <= (data_cnt == DEPTH);
half_full <= (data_cnt >= HALF_DEPTH);
end
end
// 写数据逻辑
always @(posedge clk or negedge rst_n) begin
integer i;
if (!rst_n) begin
wr_ptr <= {PTR_WIDTH{1'b0}};
for (i = 0; i < DEPTH; i = i + 1) begin
fifo_mem[i] <= {DATA_WIDTH{1'b0}}; // 复位时FIFO清零
end
end else if (wr_en && !full) begin
fifo_mem[wr_ptr] <= wr_data; // 写入数据到当前地址
wr_ptr <= (wr_ptr == DEPTH - 1) ? {PTR_WIDTH{1'b0}} : wr_ptr + 1; // 指针循环
end
end
// 读数据逻辑
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
rd_ptr <= {PTR_WIDTH{1'b0}};
rd_data <= {DATA_WIDTH{1'b0}};
end else if (rd_en && !empty) begin
rd_data <= fifo_mem[rd_ptr]; // 读取当前地址数据
rd_ptr <= (rd_ptr == DEPTH - 1) ? {PTR_WIDTH{1'b0}} : rd_ptr + 1; // 指针循环
end
end
endmodule
```
#### 8. CmdFIFO.v(命令缓冲区,支持连续命令接收)
```verilog
module CmdFIFO #(
parameter DATA_WIDTH = 8, // 命令宽度(UART字节)
parameter DEPTH = 4 // 缓存深度(支持4个连续命令)
)(
input wire clk, // 系统时钟
input wire rst_n, // 低电平复位
input wire wr_en, // 写使能(UART接收命令)
input wire [DATA_WIDTH-1:0] wr_data, // 写入命令(来自UART_RX)
input wire rd_en, // 读使能(处理命令)
output reg [DATA_WIDTH-1:0] rd_data, // 读出命令(供处理)
output reg empty, // 空标志(1=无命令)
output reg full // 满标志(1=命令缓存满)
);
reg [DATA_WIDTH-1:0] fifo_mem[DEPTH-1:0]; // 命令存储数组
localparam PTR_WIDTH = $clog2(DEPTH); // 指针位宽
reg [PTR_WIDTH-1:0] wr_ptr; // 写指针
reg [PTR_WIDTH-1:0] rd_ptr; // 读指针
reg [PTR_WIDTH-1:0] data_cnt; // 命令计数
// 空/满标志+计数(防溢出)
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
data_cnt <= {PTR_WIDTH{1'b0}};
empty <= 1'b1;
full <= 1'b0;
end else begin
case ({wr_en, rd_en})
2'b00: data_cnt <= data_cnt;
2'b01: data_cnt <= (data_cnt > 0) ? data_cnt - 1 : 0;
2'b10: data_cnt <= (data_cnt < DEPTH) ? data_cnt + 1 : DEPTH;
2'b11: data_cnt <= data_cnt;
endcase
empty <= (data_cnt == 0);
full <= (data_cnt == DEPTH);
end
end
// 写命令逻辑(UART接收命令存入)
always @(posedge clk or negedge rst_n) begin
integer i;
if (!rst_n) begin
wr_ptr <= {PTR_WIDTH{1'b0}};
for (i = 0; i < DEPTH; i = i + 1) begin
fifo_mem[i] <= {DATA_WIDTH{1'b0}};
end
end else if (wr_en && !full) begin
fifo_mem[wr_ptr] <= wr_data;
wr_ptr <= (wr_ptr == DEPTH - 1) ? {PTR_WIDTH{1'b0}} : wr_ptr + 1;
end
end
// 读命令逻辑(处理模块读取命令)
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
rd_ptr <= {PTR_WIDTH{1'b0}};
rd_data <= {DATA_WIDTH{1'b0}};
end else if (rd_en && !empty) begin
rd_data <= fifo_mem[rd_ptr];
rd_ptr <= (rd_ptr == DEPTH - 1) ? {PTR_WIDTH{1'b0}} : rd_ptr + 1;
end
end
endmodule
```
### 三、通信控制模块(UART收发+命令处理+中断)
#### 9. UART_BaudGen.v(UART波特率发生器,16倍采样时钟)
```verilog
module UART_BaudGen #(
parameter SYS_CLK_FREQ = 50_000_000, // 系统时钟频率(50MHz)
parameter BAUD_RATE = 115200 // 目标波特率(115200)
)(
input wire clk, // 系统时钟
input wire rst_n, // 低电平复位
output reg baud_clk_16x // 16倍波特率采样时钟(高脉冲有效)
);
localparam DIV_CNT = SYS_CLK_FREQ / (BAUD_RATE * 16) - 1; // 分频系数
reg [15:0] cnt; // 计数器(支持最大分频系数65535)
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
cnt <= 16'd0;
baud_clk_16x <= 1'b0;
end else begin
if (cnt == DIV_CNT) begin
cnt <= 16'd0;
baud_clk_16x <= 1'b1; // 生成1周期采样脉冲
end else begin
cnt <= cnt + 1'b1;
baud_clk_16x <= 1'b0;
end
end
end
endmodule
```
#### 10. STM32Comm_UART_FIFO.v(核心通信控制,整合UART+FIFO+命令)
```verilog
module STM32Comm_UART_FIFO #(
parameter SYS_CLK_FREQ = 50_000_000, // 系统时钟频率
parameter BAUD_RATE = 115200 // UART波特率
)(
input wire SYS_CLK, // 系统时钟
input wire RST_N, // 低电平复位
// 锁存器接口
input wire [23:0] latch1_data,// 锁存器1数据
input wire latch1_valid,// 锁存器1有效
input wire latch1_overflow,// 锁存器1溢出
input wire [23:0] latch2_data,// 锁存器2数据
input wire latch2_valid,// 锁存器2有效
input wire latch2_overflow,// 锁存器2溢出
input wire latch2_invalid_cfg,// 锁存器2配置无效
output reg fifo1_wr_ack,// FIFO1写确认(给CntLatch1)
output reg fifo2_wr_ack,// FIFO2写确认(给CntLatch2)
output reg STM32_RD_DONE,// 读取完成(给锁存器清零)
// UART物理接口
input wire UART_RX, // UART接收(来自STM32)
output reg UART_TX, // UART发送(给STM32)
// 系统状态输出
output reg FPGA_INT, // 1周期中断脉冲(给STM32)
output wire FPGA_DATA_RDY, // 数据就绪(任一FIFO非空)
output wire FIFO1_FULL, // FIFO1满标志
output wire FIFO2_FULL, // FIFO2满标志
output wire FIFO1_HALF_FULL,// FIFO1半满标志
output wire FIFO2_HALF_FULL,// FIFO2半满标志
output wire LATCH1_OVERFLOW,// 锁存器1溢出报警
output wire LATCH2_OVERFLOW,// 锁存器2溢出报警
output wire LATCH2_INVALID_CFG // 锁存器2配置无效报警
);
// 命令定义(STM32→FPGA)
localparam CMD_READ_FIFO1 = 8'h01; // 读取FIFO1(2分频数据)
localparam CMD_READ_FIFO2 = 8'h02; // 读取FIFO2(N分频数据)
localparam CMD_CLEAR_FIFO1 = 8'h03; // 清除FIFO1
localparam CMD_CLEAR_FIFO2 = 8'h04; // 清除FIFO2
localparam CMD_CLEAR_ALL = 8'h05; // 清除所有FIFO+锁存器
// 状态编码定义(FPGA→STM32)
localparam DATA_EMPTY = 24'h000000; // FIFO空(无数据)
localparam DATA_OVERFLOW = 24'hFFFFFF; // 计数溢出
localparam DATA_INVALID_CFG = 24'hFF0000; // 配置无效(仅FIFO2)
// 内部信号
wire baud_clk_16x; // 16倍波特率采样时钟
wire [7:0] uart_rx_data; // UART接收数据
wire uart_rx_done; // UART接收完成
reg uart_tx_en; // UART发送使能
reg [7:0] uart_tx_data; // UART发送数据
wire uart_tx_busy; // UART发送忙
// 命令缓冲区信号
wire cmd_fifo_wr_en = uart_rx_done; // 接收完成自动写命令
wire [7:0] cmd_fifo_wr_data = uart_rx_data;
wire cmd_fifo_rd_en; // 命令读取使能
wire [7:0] cmd_fifo_rd_data; // 读出命令
wire cmd_fifo_empty; // 命令缓冲区空
wire cmd_fifo_full; // 命令缓冲区满
// FIFO1信号(2分频数据缓存)
wire fifo1_wr_en = latch1_valid & ~FIFO1_FULL;
wire [23:0] fifo1_wr_data = latch1_data;
wire fifo1_rd_en;
wire [23:0] fifo1_rd_data;
wire fifo1_empty;
// FIFO2信号(N分频数据缓存)
wire fifo2_wr_en = latch2_valid & ~FIFO2_FULL;
wire [23:0] fifo2_wr_data = latch2_data;
wire fifo2_rd_en;
wire [23:0] fifo2_rd_data;
wire fifo2_empty;
// 发送状态机(24位数据分3字节发送:高→中→低)
localparam S_TX_IDLE = 3'd0; // 发送空闲
localparam S_TX_HIGH = 3'd1; // 发送高8位
localparam S_TX_MID = 3'd2; // 发送中8位
localparam S_TX_LOW = 3'd3; // 发送低8位
reg [2:0] tx_state; // 发送状态
reg [23:0] tx_data_buf; // 发送数据缓冲
reg cmd_process_done; // 命令处理完成标志
// 1. 例化波特率发生器
UART_BaudGen #(
.SYS_CLK_FREQ(SYS_CLK_FREQ),
.BAUD_RATE(BAUD_RATE)
) u_baud_gen (
.clk(SYS_CLK),
.rst_n(RST_N),
.baud_clk_16x(baud_clk_16x)
);
// 2. 例化UART收发器
UART_Transceiver #(
.SYS_CLK_FREQ(SYS_CLK_FREQ),
.BAUD_RATE(BAUD_RATE)
) u_uart (
.clk(SYS_CLK),
.rst_n(RST_N),
.uart_rx(UART_RX),
.rx_done(uart_rx_done),
.rx_data(uart_rx_data),
.tx_en(uart_tx_en),
.tx_data(uart_tx_data),
.uart_tx(UART_TX),
.tx_busy(uart_tx_busy)
);
// 3. 例化命令缓冲区
CmdFIFO u_cmd_fifo (
.clk(SYS_CLK),
.rst_n(RST_N),
.wr_en(cmd_fifo_wr_en & ~cmd_fifo_full),
.wr_data(cmd_fifo_wr_data),
.rd_en(cmd_fifo_rd_en),
.rd_data(cmd_fifo_rd_data),
.empty(cmd_fifo_empty),
.full(cmd_fifo_full)
);
// 4. 例化数据FIFO1
SyncFIFO #(
.DATA_WIDTH(24),
.DEPTH(16),
.HALF_DEPTH(8)
) u_fifo1 (
.clk(SYS_CLK),
.rst_n(RST_N),
.wr_en(fifo1_wr_en),
.wr_data(fifo1_wr_data),
.rd_en(fifo1_rd_en),
.rd_data(fifo1_rd_data),
.empty(fifo1_empty),
.full(FIFO1_FULL),
.half_full(FIFO1_HALF_FULL),
.wr_ack(fifo1_wr_ack)
);
// 5. 例化数据FIFO2
SyncFIFO #(
.DATA_WIDTH(24),
.DEPTH(16),
.HALF_DEPTH(8)
) u_fifo2 (
.clk(SYS_CLK),
.rst_n(RST_N),
.wr_en(fifo2_wr_en),
.wr_data(fifo2_wr_data),
.rd_en(fifo2_rd_en),
.rd_data(fifo2_rd_data),
.empty(fifo2_empty),
.full(FIFO2_FULL),
.half_full(FIFO2_HALF_FULL),
.wr_ack(fifo2_wr_ack)
);
// 6. 命令读取使能(发送空闲且有命令)
assign cmd_fifo_rd_en = (tx_state == S_TX_IDLE) && !cmd_fifo_empty;
// 7. FIFO读使能(命令有效且发送空闲)
assign fifo1_rd_en = (cmd_fifo_rd_data == CMD_READ_FIFO1) && (tx_state == S_TX_IDLE) && !fifo1_empty;
assign fifo2_rd_en = (cmd_fifo_rd_data == CMD_READ_FIFO2) && (tx_state == S_TX_IDLE) && !fifo2_empty;
// 8. 状态输出映射
assign FPGA_DATA_RDY = !fifo1_empty || !fifo2_empty;
assign LATCH1_OVERFLOW = latch1_overflow;
assign LATCH2_OVERFLOW = latch2_overflow;
assign LATCH2_INVALID_CFG = latch2_invalid_cfg;
// 9. 命令处理逻辑(解析命令,填充发送缓冲)
always @(posedge SYS_CLK or negedge RST_N) begin
if (!RST_N) begin
tx_data_buf <= 24'd0;
cmd_process_done <= 1'b0;
STM32_RD_DONE <= 1'b0;
end else begin
cmd_process_done <= 1'b0;
STM32_RD_DONE <= 1'b0;
case (cmd_fifo_rd_data)
// 读取FIFO1
CMD_READ_FIFO1: begin
if (tx_state == S_TX_IDLE && !cmd_fifo_empty) begin
if (fifo1_empty) begin
tx_data_buf <= DATA_EMPTY; // FIFO空,返回0x000000
end else if (latch1_overflow) begin
tx_data_buf <= DATA_OVERFLOW; // 溢出,返回0xFFFFFF
end else begin
tx_data_buf <= fifo1_rd_data; // 正常数据
end
tx_state <= S_TX_HIGH; // 启动发送
end
end
// 读取FIFO2
CMD_READ_FIFO2: begin
if (tx_state == S_TX_IDLE && !cmd_fifo_empty) begin
if (fifo2_empty) begin
tx_data_buf <= DATA_EMPTY; // FIFO空
end else if (latch2_overflow) begin
tx_data_buf <= DATA_OVERFLOW; // 溢出
end else if (latch2_invalid_cfg) begin
tx_data_buf <= DATA_INVALID_CFG; // 配置无效
end else begin
tx_data_buf <= fifo2_rd_data; // 正常数据
end
tx_state <= S_TX_HIGH; // 启动发送
end
end
// 清除FIFO1
CMD_CLEAR_FIFO1: begin
cmd_process_done <= 1'b1;
end
// 清除FIFO2
CMD_CLEAR_FIFO2: begin
cmd_process_done <= 1'b1;
end
// 清除所有(FIFO+锁存器)
CMD_CLEAR_ALL: begin
cmd_process_done <= 1'b1;
STM32_RD_DONE <= 1'b1; // 通知锁存器清零
end
// 无效命令
default: begin
if (tx_state == S_TX_IDLE && !cmd_fifo_empty) begin
tx_data_buf <= 24'h000000; // 返回空数据
tx_state <= S_TX_HIGH;
end
end
endcase
end
end
// 10. 发送状态机(分3字节发送24位数据)
always @(posedge SYS_CLK or negedge RST_N) begin
if (!RST_N) begin
tx_state <= S_TX_IDLE;
uart_tx_en <= 1'b0;
uart_tx_data <= 8'd0;
end else begin
uart_tx_en <= 1'b0;
case (tx_state)
S_TX_IDLE: begin
// 命令处理完成或发送结束,回到空闲
end
S_TX_HIGH: begin
if (!uart_tx_busy) begin
uart_tx_en <= 1'b1;
uart_tx_data <= tx_data_buf[23:16]; // 发送高8位
tx_state <= S_TX_MID;
end
end
S_TX_MID: begin
if (!uart_tx_busy) begin
uart_tx_en <= 1'b1;
uart_tx_data <= tx_data_buf[15:8]; // 发送中8位
tx_state <= S_TX_LOW;
end
end
S_TX_LOW: begin
if (!uart_tx_busy) begin
uart_tx_en <= 1'b1;
uart_tx_data <= tx_data_buf[7:0]; // 发送低8位
tx_state <= S_TX_IDLE;
// 读取命令完成,通知锁存器(仅读取命令)
if (cmd_fifo_rd_data == CMD_READ_FIFO1 || cmd_fifo_rd_data == CMD_READ_FIFO2) begin
STM32_RD_DONE <= 1'b1;
end
end
end
endcase
end
end
// 11. 中断脉冲生成(新数据写入FIFO或溢出时,1周期高脉冲)
reg fifo1_empty_prev, fifo2_empty_prev;
reg latch1_overflow_prev, latch2_overflow_prev;
always @(posedge SYS_CLK or negedge RST_N) begin
if (!RST_N) begin
fifo1_empty_prev <= 1'b1;
fifo2_empty_prev <= 1'b1;
latch1_overflow_prev <= 1'b0;
latch2_overflow_prev <= 1'b0;
FPGA_INT <= 1'b0;
end else begin
// 新数据写入FIFO(空→非空)
wire new_data = (!fifo1_empty && fifo1_empty_prev) || (!fifo2_empty && fifo2_empty_prev);
// 新溢出发生(0→1)
wire new_overflow = (latch1_overflow && !latch1_overflow_prev) || (latch2_overflow && !latch2_overflow_prev);
FPGA_INT <= new_data || new_overflow; // 1周期脉冲
// 更新前态
fifo1_empty_prev <= fifo1_empty;
fifo2_empty_prev <= fifo2_empty;
latch1_overflow_prev <= latch1_overflow;
latch2_overflow_prev <= latch2_overflow;
end
end
endmodule
```
#### 11. UART_Transceiver.v(UART收发器,16倍采样+抗干扰)
```verilog
module UART_Transceiver #(
parameter SYS_CLK_FREQ = 50_000_000, // 系统时钟频率
parameter BAUD_RATE = 115200 // 波特率
)(
input wire clk, // 系统时钟
input wire rst_n, // 低电平复位
input wire uart_rx, // UART接收线
output reg rx_done, // 接收完成标志(1周期)
output reg [7:0] rx_data,// 接收数据(8位)
input wire tx_en, // 发送使能
input wire [7:0] tx_data,// 发送数据(8位)
output reg uart_tx, // UART发送线
output reg tx_busy // 发送忙标志
);
wire baud_clk_16x; // 16倍波特率采样时钟(来自BaudGen)
// 接收逻辑内部信号
reg [7:0] rx_buf; // 接收缓冲
reg [3:0] rx_bit_cnt; // 数据位计数(0~7)
reg [3:0] rx_sample_cnt; // 采样计数(0~15)
reg [1:0] rx_state; // 接收状态机
reg [2:0] start_sample; // 起始位3次采样(抗干扰)
localparam RX_IDLE = 2'd0; // 空闲
localparam RX_START = 2'd1; // 起始位
localparam RX_DATA = 2'd2; // 数据位
localparam RX_STOP = 2'd3; // 停止位
// 发送逻辑内部信号
reg [7:0] tx_buf; // 发送缓冲
reg [3:0] tx_bit_cnt; // 数据位计数(0~7)
reg [3:0] tx_sample_cnt; // 采样计数(0~15)
reg [1:0] tx_state; // 发送状态机
localparam TX_IDLE = 2'd0; // 空闲
localparam TX_START = 2'd1; // 起始位
localparam TX_DATA = 2'd2; // 数据位
localparam TX_STOP = 2'd3; // 停止位
// 例化波特率发生器
UART_BaudGen #(
.SYS_CLK_FREQ(SYS_CLK_FREQ),
.BAUD_RATE(BAUD_RATE)
) u_baud_gen (
.clk(clk),
.rst_n(rst_n),
.baud_clk_16x(baud_clk_16x)
);
// 接收逻辑(16倍采样,起始位3次采样抗干扰)
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
rx_state <= RX_IDLE;
rx_done <= 1'b0;
rx_data <= 8'd0;
rx_buf <= 8'd0;
rx_bit_cnt <= 4'd0;
rx_sample_cnt <= 4'd0;
start_sample <= 3'b000;
end else if (baud_clk_16x) begin
rx_done <= 1'b0;
case (rx_state)
RX_IDLE: begin
if (!uart_rx) begin // 检测起始位(低电平)
rx_state <= RX_START;
rx_sample_cnt <= 4'd0;
start_sample <= 3'b000;
end
end
RX_START: begin
rx_sample_cnt <= rx_sample_cnt + 1'b1;
// 起始位3次采样(第5、7、9个采样点)
if (rx_sample_cnt == 4'd5 || rx_sample_cnt == 4'd7 || rx_sample_cnt == 4'd9) begin
start_sample[rx_sample_cnt[1:0]] <= uart_rx;
end else if (rx_sample_cnt == 4'd15) begin
// 多数表决(≥2次低电平则确认起始位)
if (start_sample[0] + start_sample[1] + start_sample[2] <= 1'b1) begin
rx_state <= RX_DATA;
rx_bit_cnt <= 4'd0;
end else begin
rx_state <= RX_IDLE; // 噪声,返回空闲
end
rx_sample_cnt <= 4'd0;
end
end
RX_DATA: begin
rx_sample_cnt <= rx_sample_cnt + 1'b1;
if (rx_sample_cnt == 4'd15) begin // 中间点采样
rx_buf[rx_bit_cnt] <= uart_rx; // 低位优先
rx_bit_cnt <= rx_bit_cnt + 1'b1;
rx_sample_cnt <= 4'd0;
if (rx_bit_cnt == 4'd7) begin
rx_state <= RX_STOP; // 8位数据接收完成
end
end
end
RX_STOP: begin
rx_sample_cnt <= rx_sample_cnt + 1'b1;
if (rx_sample_cnt == 4'd15) begin // 停止位采样完成
rx_state <= RX_IDLE;
rx_done <= 1'b1;
rx_data <= rx_buf; // 输出接收数据
end
end
endcase
end
end
// 发送逻辑(16倍采样同步,低位优先)
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
tx_state <= TX_IDLE;
uart_tx <= 1'b1; // 空闲高电平
tx_busy <= 1'b0;
tx_buf <= 8'd0;
tx_bit_cnt <= 4'd0;
tx_sample_cnt <= 4'd0;
end else if (baud_clk_16x) begin
case (tx_state)
TX_IDLE: begin
uart_tx <= 1'b1;
tx_busy <= 1'b0;
if (tx_en) begin // 收到发送使能
tx_state <= TX_START;
tx_busy <= 1'b1;
tx_buf <= tx_data;
tx_sample_cnt <= 4'd0;
end
end
TX_START: begin
uart_tx <= 1'b0; // 发送起始位(低电平)
tx_sample_cnt <= tx_sample_cnt + 1'b1;
if (tx_sample_cnt == 4'd15) begin
tx_state <= TX_DATA;
tx_bit_cnt <= 4'd0;
tx_sample_cnt <= 4'd0;
end
end
TX_DATA: begin
uart_tx <= tx_buf[tx_bit_cnt]; // 低位优先发送
tx_sample_cnt <= tx_sample_cnt + 1'b1;
if (tx_sample_cnt == 4'd15) begin
tx_bit_cnt <= tx_bit_cnt + 1'b1;
tx_sample_cnt <= 4'd0;
if (tx_bit_cnt == 4'd7) begin
tx_state <= TX_STOP; // 8位数据发送完成
end
end
end
TX_STOP: begin
uart_tx <= 1'b1; // 发送停止位(高电平)
tx_sample_cnt <= tx_sample_cnt + 1'b1;
if (tx_sample_cnt == 4'd15) begin
tx_state <= TX_IDLE; // 发送完成,返回空闲
end
end
endcase
end
end
endmodule
```
### 四、顶层模块(模块互联,对外接口)
#### 12. Top_UART_FIFO.v(顶层模块,整合所有子模块)
```verilog
module Top_UART_FIFO #(
parameter SYS_CLK_FREQ = 50_000_000, // 系统时钟频率(50MHz)
parameter BAUD_RATE = 115200 // UART波特率
)(
// 输入信号
input wire SIGNAL, // 外部传感器输入(异步)
input wire SYS_CLK, // 系统时钟
input wire RST_N, // 全局低电平复位(0=复位)
input wire [2:0] WHEEL, // 分频配置:001=8,010=16,011=24,100=32,101=40
// UART接口(与STM32通信)
input wire UART_RX, // UART接收(来自STM32)
output wire UART_TX, // UART发送(给STM32)
// 输出状态信号(调试/报警)
output wire FPGA_INT, // 中断脉冲(给STM32)
output wire FPGA_DATA_RDY, // 数据就绪标志
output wire FIFO1_FULL, // FIFO1满标志
output wire FIFO2_FULL, // FIFO2满标志
output wire FIFO1_HALF_FULL, // FIFO1半满标志
output wire FIFO2_HALF_FULL, // FIFO2半满标志
output wire LATCH1_OVERFLOW, // 锁存器1溢出报警
output wire LATCH2_OVERFLOW, // 锁存器2溢出报警
output wire LATCH2_INVALID_CFG // 锁存器2配置无效报警
);
// 内部互联信号
wire signal_sync; // 传感器信号同步后(无亚稳态)
wire div2, div_N; // 2分频/N分频输出
wire div2_rise, div2_fall; // 2分频边沿脉冲
wire div_N_rise, div_N_fall; // N分频边沿脉冲
wire [23:0] latch1_data, latch2_data; // 锁存器数据
wire latch1_valid, latch2_valid; // 锁存器有效标志
wire latch1_overflow, latch2_overflow; // 锁存器溢出标志
wire latch2_invalid_cfg; // 配置无效标志
wire STM32_RD_DONE; // 读取完成(通知锁存器)
wire fifo1_wr_ack, fifo2_wr_ack; // FIFO写确认(给锁存器)
wire wheel_valid; // 分频配置有效标志
// 1. 异步信号同步(消除亚稳态)
SyncTwoStage u_sync_signal(
.clk(SYS_CLK),
.rst_n(RST_N),
.din(SIGNAL),
.dout(signal_sync)
);
// 2. 分频模块(生成2分频/N分频)
Div2Gen u_div2(
.SYS_CLK(SYS_CLK),
.RST_N(RST_N),
.sync_signal(signal_sync),
.div2(div2)
);
DivNGen u_divN(
.SYS_CLK(SYS_CLK),
.RST_N(RST_N),
.WHEEL(WHEEL),
.sync_signal(signal_sync),
.div_N(div_N),
.wheel_valid(wheel_valid)
);
// 3. 边沿检测(生成计数启动/停止脉冲)
EdgeDetector u_edg_div2(
.SYS_CLK(SYS_CLK),
.RST_N(RST_N),
.sig_in(div2),
.rise(div2_rise),
.fall(div2_fall)
);
EdgeDetector u_edg_divN(
.SYS_CLK(SYS_CLK),
.RST_N(RST_N),
.sig_in(div_N),
.rise(div_N_rise),
.fall(div_N_fall)
);
// 4. 计数锁存器(计数系统时钟,双缓冲锁存)
CntLatch1 u_cnt1(
.SYS_CLK(SYS_CLK),
.RST_N(RST_N),
.STM32_RD_DONE(STM32_RD_DONE),
.div2_rise(div2_rise),
.div2_fall(div2_fall),
.latch1_data(latch1_data),
.latch1_valid(latch1_valid),
.latch1_overflow(latch1_overflow),
.fifo_wr_ack(fifo1_wr_ack)
);
CntLatch2 u_cnt2(
.SYS_CLK(SYS_CLK),
.RST_N(RST_N),
.STM32_RD_DONE(STM32_RD_DONE),
.div_N_rise(div_N_rise),
.div_N_fall(div_N_fall),
.wheel_valid(wheel_valid),
.latch2_data(latch2_data),
.latch2_valid(latch2_valid),
.latch2_overflow(latch2_overflow),
.latch2_invalid_cfg(latch2_invalid_cfg),
.fifo_wr_ack(fifo2_wr_ack)
);
// 5. 通信控制模块(UART+FIFO+命令处理)
STM32Comm_UART_FIFO #(
.SYS_CLK_FREQ(SYS_CLK_FREQ),
.BAUD_RATE(BAUD_RATE)
) u_comm(
.SYS_CLK(SYS_CLK),
.RST_N(RST_N),
.latch1_data(latch1_data),
.latch1_valid(latch1_valid),
.latch1_overflow(latch1_overflow),
.latch2_data(latch2_data),
.latch2_valid(latch2_valid),
.latch2_overflow(latch2_overflow),
.latch2_invalid_cfg(latch2_invalid_cfg),
.fifo1_wr_ack(fifo1_wr_ack),
.fifo2_wr_ack(fifo2_wr_ack),
.STM32_RD_DONE(STM32_RD_DONE),
.UART_RX(UART_RX),
.UART_TX(UART_TX),
.FPGA_INT(FPGA_INT),
.FPGA_DATA_RDY(FPGA_DATA_RDY),
.FIFO1_FULL(FIFO1_FULL),
.FIFO2_FULL(FIFO2_FULL),
.FIFO1_HALF_FULL(FIFO1_HALF_FULL),
.FIFO2_HALF_FULL(FIFO2_HALF_FULL),
.LATCH1_OVERFLOW(LATCH1_OVERFLOW),
.LATCH2_OVERFLOW(LATCH2_OVERFLOW),
.LATCH2_INVALID_CFG(LATCH2_INVALID_CFG)
);
endmodule
```