使用chatgpt写的串口模块,verilog实现

Posted wu051778

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用chatgpt写的串口模块,verilog实现相关的知识,希望对你有一定的参考价值。

还是很震撼的,仅供参考:

由于串口模块的具体实现方式与所用的FPGA设备和外设有关,因此无法提供通用的Verilog代码。以下是一个简单的示例,仅供参考。

module uart(
input clk, // 时钟信号 
input reset, // 复位信号 
input tx_en, // 发送使能信号 
input [7:0] tx_data, // 发送数据 
input rx_en, // 接收使能信号 
output [7:0] rx_data, // 接收数据 
output rx_ready // 接收完成信号 
);

parameter DATA_WIDTH = 8; // 数据位宽 
parameter PARITY_EN = 1; // 奇偶校验使能 
parameter PARITY_TYPE = 0; // 奇偶校验类型(0:偶校验,1:奇校验) 
parameter STOP_BITS = 1; // 停止位数(1:1位,2:2位)
parameter BAUD_RATE = 9600; // 波特率参数(可根据需要修改)

reg [DATA_WIDTH+1:0] tx_reg; // 发送寄存器,包括起始位、数据位、奇偶校验位和停止位 
reg [DATA_WIDTH-1:0] tx_data_reg; // 发送数据寄存器 
reg [7:0] rx_reg; // 接收寄存器 
reg rx_ready_reg; // 接收完成寄存器

// 计算波特率分频系数 
reg [31:0] baud_div; 
always @(*) 
begin 
    baud_div = clk / (BAUD_RATE * 16); 
end

// 发送逻辑 
reg [3:0] tx_state; // 发送状态机状态 
parameter TX_IDLE = 4'b0000; // 空闲状态 
parameter TX_START = 4'b0001; // 起始位状态 
parameter TX_DATA = 4'b0010; // 数据位状态 
parameter TX_PARITY = 4'b0011; // 奇偶校验位状态 
parameter TX_STOP = 4'b0100; // 停止位状态 

always @(posedge clk or posedge reset) 
begin 
    if (reset) 
        begin 
            tx_reg <= 1'b0, DATA_WIDTH1'b0, 1'b0; 
            tx_data_reg <= DATA_WIDTH1'b0; 
            tx_state <= TX_IDLE; 
        end 
    else 
        begin 
            case (tx_state) 
                TX_IDLE: 
                    begin 
                        if (tx_en) 
                            begin 
                                tx_reg <= 1'b0, tx_data_reg, 1'b0; 
                                tx_state <= TX_START; 
                            end 
                    end 
                TX_START: 
                    begin 
                        tx_reg <= 1'b1, tx_data_reg, PARITY_TYPE ? ~tx_data_reg[DATA_WIDTH-1] : tx_data_reg[DATA_WIDTH-1]; 
                        tx_state <= PARITY_EN ? TX_PARITY : TX_STOP; 
                    end 
                TX_DATA: 
                    begin 
                        tx_reg <= 1'b0, tx_data_reg, PARITY_TYPE ? ~tx_data_reg[DATA_WIDTH-1] : tx_data_reg[DATA_WIDTH-1]; 
                        tx_state <= PARITY_EN ? TX_PARITY : TX_STOP; 
                    end 
                TX_PARITY: 
                    begin 
                        tx_reg <= 1'b0, tx_data_reg, PARITY_TYPE ? ~tx_data_reg[DATA_WIDTH-1] : tx_data_reg[DATA_WIDTH-1]; 
                        tx_state <= TX_STOP; 
                    end 
                TX_STOP: 
                    begin 
                        tx_reg <= 1'b1, DATA_WIDTH1'b1, 1'b1; 
                        tx_state <= TX_IDLE; 
                    end 
            endcase 
        end 
end

// 发送数据寄存器更新 
always @(posedge clk or posedge reset) 
begin 
    if (reset) 
        begin 
            tx_data_reg <= DATA_WIDTH1'b0; 
        end 
    else 
        begin 
            if (tx_en && tx_state == TX_IDLE) 
                begin 
                    tx_data_reg <= tx_data; 
                end 
        end 
end

// 发送数据输出 
assign tx_out = tx_reg[0];

// 接收逻辑 
reg [3:0] rx_state; // 接收状态机状态 
parameter RX_IDLE = 4'b0000; // 空闲状态 
parameter RX_START = 4'b0001; // 起始位状态 
parameter RX_DATA = 4'b0010; // 数据位状态 
parameter RX_PARITY = 4'b0011; // 奇偶校验位状态 
parameter RX_STOP = 4'b0100; // 停止位状态 
reg [3:0] rx_bit_cnt; // 接收位计数器 

always @(posedge clk or posedge reset) 
begin 
    if (reset) 
        begin 
            rx_reg <= 8'h00; 
            rx_ready_reg <= 1'b0; 
            rx_state <= RX_IDLE; 
            rx_bit_cnt <= 4'd0; 
        end 
    else 
        begin 
            case (rx_state) 
                RX_IDLE: 
                    begin 
                        if (!rx_en) 
                            begin 
                                rx_bit_cnt <= 4'd0; 
                            end 
                        else 
                            if (!rx_in) 
                                begin 
                                    rx_state <= RX_START; 
                                    rx_bit_cnt <= 4'd1; 
                                end 
                    end 
                RX_START: 
                    begin 
                        rx_bit_cnt <= rx_bit_cnt + 1; 
                        if (rx_bit_cnt == DATA_WIDTH+1) 
                            begin 
                                rx_state <= PARITY_EN ? RX_PARITY : RX_STOP; 
                                rx_bit_cnt <= 4'd0; 
                            end 
                    end 
                RX_DATA: 
                    begin 
                        rx_bit_cnt <= rx_bit_cnt + 1; 
                        if (rx_bit_cnt == DATA_WIDTH) 
                            begin 
                                rx_state <= PARITY_EN ? RX_PARITY : RX_STOP; 
                                rx_bit_cnt <= 4'd0; 
                            end 
                        else 
                            begin 
                                rx_reg <= rx_reg[6:0], rx_in; 
                            end 
                    end 
                RX_PARITY: 
                    begin 
                        rx_bit_cnt <= rx_bit_cnt + 1; 
                        if (rx_bit_cnt == 1) 
                            begin 
                                if (PARITY_TYPE) 
                                    begin 
                                        if (rx_in != ~rx_reg[DATA_WIDTH-1]) 
                                            begin 
                                                rx_state <= RX_IDLE; 
                                                rx_bit_cnt <= 4'd0; 
                                            end 
                                    end 
                                else 
                                    begin 
                                        if (rx_in != rx_reg[DATA_WIDTH-1]) 
                                            begin 
                                                rx_state <= RX_IDLE; 
                                                rx_bit_cnt <= 4'd0; 
                                            end 
                                    end 
                            end 
                        else 
                            begin 
                                rx_state <= RX_STOP; 
                                rx_bit_cnt <= 4'd0; 
                            end 
                    end 
                RX_STOP: 
                    begin 
                        rx_bit_cnt <= rx_bit_cnt + 1; 
                        if (rx_bit_cnt == STOP_BITS) 
                            begin 
                                rx_ready_reg <= 1'b1; 
                                rx_state <= RX_IDLE; 
                                rx_bit_cnt <= 4'd0; 
                            end 
                    end 
            endcase 
        end 
end

// 接收数据输出 
assign rx_data = rx_reg[DATA_WIDTH-1:0]; 
assign rx_ready = rx_ready_reg;

endmodule

串口接收模块(verilog) 波特率115200

我来分享一下uart协议之接收verilog代码

顶层实例化

`timecale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 17:38:36 11/07/2017
// Design Name: chendog
// Module Name: uart_receive_top
// Project Name: uart_receive
// Target Devices:
// Tool versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module uart_receive_top(
input wire clk, //时钟信号
input wire rst_n, //复位信号
input wire receive, //接收信号
output wire [7:0] data //接收数据
);

wire cnt_start; //开始计数
wire bps_sig; //读数据中间位置
wire recei_nege; //下降沿开始接收数据

/////////////////////////////////////波特率设置模块
bps_set bps_set1(
.clk(clk),
.rst_n(rst_n),
.receive(receive),
.cnt_start(cnt_start),
.bps_sig(bps_sig),
.recei_nege(recei_nege)
);


////////////////////////////////////数据接收状态转换
receive_fsm receive_fsm1(
.clk(clk),
.rst_n(rst_n),
.receive(receive),
.bps_sig(bps_sig),
.recei_nege(recei_nege),
.cnt_start(cnt_start),
.data(data)
);

endmodule

 

波特率设置

 

module bps_set(
input wire clk,
input wire rst_n,
input wire receive,
input wire cnt_start,
output wire bps_sig,
output wire recei_nege
);

///////////////////////////////////////////////下降沿检测
reg receive1;
reg receive2;

[email protected](posedge clk or negedge rst_n)
begin
if(!rst_n) begin
receive1 <= 1‘b0;
receive2 <= 1‘b0;
end
else begin
receive1 <= receive;
receive2 <= receive1;
end
end

assign recei_nege = receive2 & ~receive1;


/////////////////////////////////////////////////分频计数
parameter CONSTANT1 = 9‘d434;  //波特率115200  434 = 50m/115200

reg [8:0] cnt;

[email protected](posedge clk or negedge rst_n)
begin
if(!rst_n)
cnt <= 9‘d0;
else if(cnt_start) begin
if(cnt == CONSTANT1 - 1‘b1)
cnt <= 9‘d0;
else
cnt <= cnt + 1‘b1;
end
else
cnt <= cnt;
end

assign bps_sig = (cnt == CONSTANT1 / 2)? 1‘b1:1‘b0; //采集计数中间位置

endmodule

 

接收状态机

module receive_fsm(
input wire clk,
input wire rst_n,
input wire receive,
input wire bps_sig,
input wire recei_nege,
output reg cnt_start,
output reg [7:0] data
);

reg [3:0] state;

////////////////////////////////////////////一段式状态机
[email protected](posedge clk or negedge rst_n)
begin
if(!rst_n) begin
cnt_start <= 1‘b0;
state <= 4‘d0;
data <= 8‘d0;
end
else case(state)
0: if(recei_nege) begin //等待数据线下降沿 下降沿到来 进入计数状态
state <= 4‘d1;
cnt_start <= 1‘b1;
data <= 8‘d0;
end

else begin
state <= 4‘d0;
cnt_start <= 1‘b0;
data <= 8‘d0;
end

1: if(bps_sig) begin //第一位 起始位
state <= state + 4‘d1;
end
else begin
state <= state;
end

2,3,4,5,6,7,8,9: //数据位开始接收
if(bps_sig) begin
state <= state + 4‘d1;
data[state - 4‘d2] <= receive;
end

else begin
state <= state;
end

10,11:if(bps_sig) begin //停止位与校验位
state <= state + 4‘d1;
end

else begin
state <= state;
end
12:if(bps_sig) begin //完成一次接收 停止计数 回到state = 0
state <= 4‘b0;
cnt_start <= 1‘b0;
end
else begin
state <= state;
end
endcase
end

endmodule

 

纯代码与注释,有问题联系qq:1424307272

 

以上是关于使用chatgpt写的串口模块,verilog实现的主要内容,如果未能解决你的问题,请参考以下文章

基于Verilog的带FIFO输出缓冲的串口接收接口封装

如何将自己写的verilog模块封装成IP核

用Vivado写的verilog交通灯课程作业

串口发送端verilog代码分析

ChatGPT这是一篇ChatGPT写的关于Python的文章

Verilog中使用'include实现参数化设计