• 已绑定课时
  • 工程师可点评
  • 教务通过

【作业要求】1、什么是波特率? 2、利用状态机编写串口接收端代码? 【我的做法】1、波特率是串行通信中衡量数据传输速率的一个核心指标,它代表每秒传输的码元符号数量。 2、module uart_rx ( input wire clk, // 50MHz系统时钟 input wire rst_n, // 异步复位,低有效 input wire rx, // 串行输入线 output reg [7:0…

童乐天
69 0
教务通过
教务通过
教务评价

教务通过

3342599708 · 2026-08-05

教务已盖章,暂无文字评语。

2、利用状态机编写串口接收端代码?

【我的做法】1、波特率是串行通信中衡量数据传输速率的一个核心指标,它代表每秒传输的码元符号数量。

2、module uart_rx (

input  wire       clk,          // 50MHz系统时钟
input  wire       rst_n,        // 异步复位,低有效
input  wire       rx,           // 串行输入线
output reg  [7:0] rx_data,      // 接收到的并行数据
output reg        rx_valid      // 接收完成有效脉冲
);
// 波特率16倍采样时钟生成(50MHz / (9600*16) = 50_000_000 / 153600 ≈ 325.5)
// 取计数周期326-1=325
localparam BPS16_CNT_MAX = 10'd325;
reg [9:0] bps_cnt;
wire      bps16_en;              // 16倍波特率使能脉冲
always @(posedge clk or negedge rst_n)
begin
if (!rst_n)
bps_cnt <= 10'd0;
else if (bps16_en)
bps_cnt <= 10'd0;
else
bps_cnt <= bps_cnt + 1'b1;
end
assign bps16_en = (bps_cnt == BPS16_CNT_MAX);
// 状态定义
localparam IDLE      = 3'd0,
START_BIT = 3'd1,
DATA_BITS = 3'd2,
STOP_BIT  = 3'd3;
reg [2:0] state, next_state;
reg [3:0] bit_cnt;           // 数据位计数(0-7)
reg [7:0] shift_reg;         // 移位寄存器
// 第一段:状态寄存器
always @(posedge clk or negedge rst_n)
begin
if (!rst_n)
state <= IDLE;
else
state <= next_state;
end
// 第二段:次态逻辑和内部逻辑控制
always @(*)
begin
next_state = state;
case (state)
IDLE:
begin
// 检测到rx的下降沿(起始位),进入START_BIT状态
if (rx == 1'b0 && bps16_en)
next_state = START_BIT;
end
START_BIT:
begin
// 在起始位中间采样(计数8个bps16_en)确认起始位有效
// 实际处理中,我们利用位半逻辑,这里简化为到达第8个使能脉冲时跳转
if (bps16_en && bit_cnt == 4'd7)
next_state = DATA_BITS;
end
DATA_BITS:
begin
// 每16个bps16_en脉冲接收一个数据位,在中间点采样
if (bps16_en && bit_cnt == 4'd15)
begin
if (bit_cnt == 4'd15 && shift_reg[0])  // 这个判断是为了说明,实际靠bit_cnt==7跳转
;  // 注:这里改为使用独立的bit_cnt位计数器
end
// 重新组织:使用一个独立的位循环计数器,每16个使能收一位
// 当收到8个数据位后,进入停止位状态
if (bit_cnt == 4'd7 && bps16_en)
next_state = STOP_BIT;
end
STOP_BIT:
begin
// 在停止位中间采样,完成后回到IDLE
if (bps16_en && bit_cnt == 4'd15)
begin
next_state = IDLE;
end
end
default: next_state = IDLE;
endcase
end
// 第三段:输出逻辑与时序控制(实际将数据位计数、移位等放入时序块)
reg [3:0] sample_cycle;   // 每个位内的16倍计数(0-15)
reg [3:0] data_bit_idx;   // 当前正在接收的数据位索引(0-7)
always @(posedge clk or negedge rst_n)
begin
if (!rst_n)
begin
shift_reg     <= 8'd0;
data_bit_idx  <= 4'd0;
sample_cycle  <= 4'd0;
rx_data       <= 8'd0;
rx_valid      <= 1'b0;
end else
begin
case (state)
IDLE:
begin
data_bit_idx <= 4'd0;
sample_cycle <= 4'd0;
rx_valid     <= 1'b0;
end
START_BIT:
begin
if (bps16_en)
begin
sample_cycle <= sample_cycle + 1'b1;
// 计数到8时认为到达起始位中心,准备进入数据状态并复位周期
if (sample_cycle == 4'd7)
begin
sample_cycle <= 4'd0;
// 这里其实state会转为DATA_BITS,但要配合次态逻辑
end
end
end
DATA_BITS:
begin
if (bps16_en)
begin
sample_cycle <= sample_cycle + 1'b1;
// 每个位的中心点是在 sample_cycle == 8 吗?我们设为第8个脉冲,即sample_cycle=7时采样
if (sample_cycle == 4'd7)
begin
// 采样rx,移入移位寄存器(先收最低位)
shift_reg <= {rx, shift_reg[7:1]};
data_bit_idx <= data_bit_idx + 1'b1;
if (data_bit_idx == 4'd7)
begin
// 收完8位,进入停止位状态
data_bit_idx <= 4'd0;
end
end
if (sample_cycle == 4'd15)
begin
sample_cycle <= 4'd0;
end
end
end
STOP_BIT:
begin
if (bps16_en)
begin
sample_cycle <= sample_cycle + 1'b1;
if (sample_cycle == 4'd7)
begin
// 采样停止位,应为高电平,可做帧错误检测(略)
// 输出接收到的数据
rx_data  <= shift_reg;
rx_valid <= 1'b1;
end
if (sample_cycle == 4'd15)
begin
sample_cycle <= 4'd0;
end
end
end
endcase
end
end
endmodule

学习上下文

产出状态

工程师已阅69 位工程师
教务教务通过