当前位置: 首页 > article >正文

串口通信控制LED灯

做这个东西的目的是锻炼一下自己的编程能力以及系统思维能力

首先,清楚自己要干什么,正点原子大家应该都看过,系统框图是一个比较重要的东西,引导我们去设计和思考。

下面先给出系统框图:

模块划分好后,结构就比较清晰了,可以分成三个文件实现,一个是LED控制模块,一个是串口接收模块,还有一个是顶层模块。

串口接收模块
module uart_recv (
    input clk,
    input rst_n,
    input uart_rx,
    output reg [7:0] rx_data,
    output reg data_valid
);

reg [1:0] signal;
wire falling_edge; 
always @ (posedge clk or negedge rst_n) begin
    if (!rst_n) begin
        signal[0] <= 1'd0;
        signal[1] <= 1'd0;
    end else begin
        signal[0] <= uart_rx;
        signal[1] <= signal[0];
    end
end

assign falling_edge = ~signal[0] & signal[1];    //检测下降沿

reg rx_flag;
always @ (posedge clk or negedge rst_n) begin
    if (!rst_n) begin
        rx_flag <= 1'd0;
    end else if (falling_edge) begin
        rx_flag <= 1'd1;
    end else if (data_cnt == 4'd8) begin
        rx_flag <= 1'd0;
    end else begin
        rx_flag <= rx_flag;
    end
end

//115200bps 8680ns接收一位数据 系统时钟50M 20ns 每计数434次接收一位数据
reg [8:0] cnt;
always @ (posedge clk or negedge rst_n) begin
    if (!rst_n) begin
        cnt <= 9'd0;
    end else if (rx_flag && cnt < 9'd434) begin
        cnt <= cnt + 1;
    end else begin
        cnt <= 9'd0;
    end
end

reg [7:0] data;
reg [3:0] data_cnt;
always @ (posedge clk or negedge rst_n) begin
    if (!rst_n) begin
        data <= 8'd0;
        data_cnt <= 4'd0;
    end else if (rx_flag && cnt == 9'd434) begin
        data <= {data[6:0],uart_rx};
        data_cnt <= data_cnt + 1;
    end else if (rx_flag) begin
        data <= data;
        data_cnt <= data_cnt;
    end else
        data <= 8'd0;
        data_cnt <= 4'd0;
    end
end

always @ (posedge clk or negedge rst_n) begin
    if (!rst_n) begin
        rx_data <= 8'd0;
        data_valid <= 1'd0;
    end else if (data_cnt == 4'd8) begin
        rx_data <= data;
        data_valid <= 1'd1;
    end else begin
        rx_data <= 8'd0;
        data_valid <= 1'd0;
    end
end
    

endmodule

对该模块进行仿真测试

`timescale 1ns / 1ps

module uart_recv_tb;

reg clk;
reg rst_n;
reg uart_rx;
wire [7:0] rx_data;
wire data_valid;

// 实例化模块
uart_recv uut (
    .clk(clk),
    .rst_n(rst_n),
    .uart_rx(uart_rx),
    .rx_data(rx_data),
    .data_valid(data_valid)
);

// 时钟生成
initial begin
    clk = 1'b0;
    forever #10 clk = ~clk; // 50 MHz 时钟
end

// 复位信号
initial begin
    rst_n = 1'b0;
    #50 rst_n = 1'b1;
end

// 模拟 UART 数据帧传输(起始位+8数据位+停止位)
initial begin
    uart_rx = 1'b1; // 空闲状态

    // 发送起始位(低电平)
    #8680 uart_rx = 1'b0;

    // 发送数据位 (10101011)
    #8680 uart_rx = 1'b1;
    #8680 uart_rx = 1'b0;
    #8680 uart_rx = 1'b1;
    #8680 uart_rx = 1'b0;
    #8680 uart_rx = 1'b1;
    #8680 uart_rx = 1'b0;
    #8680 uart_rx = 1'b1;
    #8680 uart_rx = 1'b1;

    // 发送停止位(高电平)
    #8680 uart_rx = 1'b1;

    // 等待接收完成
    #50000 $finish;
end

endmodule

测试结果

检测到起始位:

读出数据正确,读有效信号拉高


LED控制模块
module led_control(
	input clk,
	input rst_n,
	input [7:0] data,
	input data_valid,
	output reg led
);

always @ (posedge clk or negedge rst_n) begin
	if (!rst_n) begin
		led <= 1'd0;
	end else if (data_valid && data == 8'h12) begin
		led <= 1'd1;
	end else if (data_valid && data == 8'h23) begin
		led <= 1'd0;
	end else begin
		led <= led;
	end
end

endmodule

顶层模块
module top(
    input clk,
    input rst_n,
    input uart_rx,
    output led
    );

wire [7:0] data;
wire data_valid;

uart_recv u_uart_recv(
    .clk        (clk),
    .rst_n      (rst_n),
    .uart_rx    (uart_rx),
    .rx_data    (data),
    .data_valid (data_valid)
);

led_control u_led_control(
    .clk        (clk),
    .rst_n      (rst_n),
    .data       (data),
    .data_valid (data_valid),
    .led        (led)
);


ila_0 your_instance_name (
	.clk(clk), // input wire clk
	.probe0(led), // input wire [0:0]  probe0  
	.probe1(data_valid), // input wire [0:0]  probe1 
	.probe2(data) // input wire [7:0]  probe2
);

endmodule
综合仿真

仿真结果正确,串口发送12时led点亮,串口发送23时,led熄灭


上板测试结果与仿真一致


http://www.kler.cn/a/444694.html

相关文章:

  • SpringBoot开发——整合JSONPath解析JSON信息
  • C语言编程1.27汉诺塔
  • 中间件 redis安装
  • 机器学习中做时间序列模型考虑把时间作为特征分析
  • 三七互娱Java开发150道面试题及参考答案(下)
  • 苹果电脑可以安装windows操作系统吗?Mac OS X/OS X/macOS傻傻分不清?macOS系统的Java支持?什么是macOS的五大API法王?
  • 车辆重识别代码笔记12.20
  • 项目搭建+删除(单/批)
  • 【机器学习】机器学习的基本分类-强化学习-REINFORCE 算法
  • 带渐变边框的图(uniapp版本+uview)
  • 使用idea进行maven项目打war包
  • 【Linux】UDP通信
  • AOI外观缺陷检测机
  • unordered_map和unorderset_set的使用
  • Dot Foods EDI 需求分析及对接流程
  • Java爬虫大冒险:如何征服1688商品搜索之巅
  • 自然语言处理的不同流派
  • 冬日养仓鼠小指南:温暖与陪伴同行
  • 【LeetCode】将有序数组转换为二叉搜索树
  • 虚幻引擎游戏开发系列专题-官方编码标准或规约
  • 初阶3 链表
  • Java算法题-前缀和
  • 【证书】免费的证书+1 Ai Prompt Engineer
  • 【Unity基础】AudioSource 常用方法总结
  • 第J9周:Inception v3算法实战与解析
  • Linux限制root 用户的远程登录(安全要求)