通信总线----UART(有详细代码)

本文详细介绍了UART通信协议,包括硬件连接、软件通信协议,并提供了STM32的发送和接收模块介绍及代码示例,涵盖了时钟、计数、奇偶校验和移位寄存器等内容。
AI助手已提取文章相关产品:

想深耕嵌入式?这个专辑值得收藏

MCU、FPGA、工控、传感器一站式学习,实战项目直接抄

UART

通用异步收发传输器(Universal Asynchronous Receiver/Transmitter),通常称作UART。它将要传输的资料在串行通信与并行通信之间加以转换。作为把并行输入信号转成串行输出信号的芯片,UART通常被集成于其他通讯接口的连结上。

本文详细文档完整的代码会在后面文章以文档的形式发出来

1. 硬件连接

硬件连接比较简单,仅需要3条线,注意连接时两个设备UART电平,如电平范围不一致请做电平转换后再连接,如下图所示:
在这里插入图片描述
TX:发送数据端,要接对面设备的RX
RX:接收数据端,要接对面设备的TX
GND:保证两设备共地,有统一的参考平面

2. 软件通信协议

在这里插入图片描述
空闲位:
UART协议规定,当总线处于空闲状态时信号线的状态为‘1’即高电平

起始位:
开始进行数据传输时发送方要先发出一个低电平’0’来表示传输字符的开始。因为空闲位一直是高电平所以开始第一次通讯时先发送一个明显区别于空闲状态的信号即为低电平。

数据位:
起始位之后就是要传输的数据,数据可以是5,6,7,8,9位,构成一个字符,一般都是8位。先发送最低位最后发送最高位。

奇偶校验位:
数据位传送完成后,要进行奇偶校验,校验位其实是调整个数,串口校验分几种方式:
1.无校验(no parity)
2.奇校验(odd parity):如果数据位中’1’的数目是偶数,则校验位为’1’,如果’1’的数目是奇数,校验位为’0’。
3.偶校验(even parity):如果数据为中’1’的数目是偶数,则校验位为’0’,如果为奇数,校验位为’1’。
4.mark parity:校验位始终为1
5.space parity:校验位始终为0

停止位:
数据结束标志,可以是1位,1.5位,2位的高电平。

波特率:
数据传输速率使用波特率来表示,单位bps(bits per second),常见的波特率9600bps,115200bps等等,其他标准的波特率是1200,2400,4800,19200,38400,57600。举个例子,如果串口波特率设置为9600bps,那么传输一个比特需要的时间是1/9600≈104.2us。

3. 发送具体模块介绍

(1)发送的框图:
在这里插入图片描述

(2)发送的状态转移图:
在这里插入图片描述
(3)时钟产生模块:
在这里插入图片描述
(4)计数器模块:
在这里插入图片描述
(5)奇偶校验模块:
在这里插入图片描述
(6)移位寄存器模块:
在这里插入图片描述

4.接收具体模块介绍:

(1)接收模块的框图:
在这里插入图片描述
(2)接收模块的状态转移图:
在这里插入图片描述

5.发送模块的代码

(1)状态机代码

module FSM(
    input       SysClk,
    input       rst_n,
    input       Send,
    input       NextBit,
    input       Count_finish,
    output reg  Busy,
    output reg  ResetTimer,
    output reg  Increment,
    output reg  ResetCounter,
    output reg  Shift,
    output reg  Load       
);

//-----------------------------------
//状态变量、状态编码(初始值为0的独热码)
//-----------------------------------           
    reg [3:0]CS,NS;//CS:当前状态;NS:下一状态
    parameter [3:0]
        IDLE  = 4'b0000,
        LOAD  = 4'b0001,
        COUNT = 4'b0010,
        SHIFT = 4'b0100,
        WAIT  = 4'b1000;

//-----------------------------------
//时序逻辑描述状态转移
//-----------------------------------   
    always @(posedge SysClk or negedge rst_n)
        if(!rst_n) CS <= IDLE;
        else CS <= NS;

//-----------------------------------
//组合逻辑判断状态转移条件,描述状态转移规律
//-----------------------------------
    always @(rst_n or CS or Send or NextBit or Count_finish)//敏感列表中为复位信号、当前状态和输入条件
        begin
            NS = 4'bx;//默认状态为不定态X
            case(CS)//敏感列表为当前状态
                IDLE:   begin
                            if(!Send)    NS = IDLE;
                            if(Send)     NS = LOAD;
                        end
                LOAD:   NS = COUNT;
                COUNT:  begin
                            if(!NextBit) NS = COUNT;
                            if(NextBit)  NS = SHIFT;
                        end
                SHIFT:  begin
                            if(!Count_finish) NS = COUNT;
                            if(Count_finish)  NS = WAIT;
                        end
                WAIT:   begin
                            if(Send)     NS = WAIT;
                            if(!Send)    NS = IDLE;
                        end 
                default: NS = IDLE;
            endcase
        end

//-----------------------------------
//时序逻辑描述每个状态的输出
//-----------------------------------
 always @(posedge SysClk or negedge rst_n)
        if(!rst_n) begin
            ResetCounter <= 1'b0;
            ResetTimer <= 1'b0;//复位信号高有效
            Load <= 1'b0;
            Shift <= 1'b0;
            Busy <= 1'b0;
            Increment <= 1'b0;
        end
        else begin
            case(NS)//敏感列表为下一状态
                IDLE:   begin
                            ResetCounter <= 1'b0;
                            ResetTimer <= 1'b0;
                            Load <= 1'b0;
                            Shift <= 1'b0;
                            Busy <= 1'b0;
                            Increment <= 1'b0;
                        end
                LOAD:   begin
                            ResetCounter <= 1'b1;
                            ResetTimer <= 1'b1;
                            Load <= 1'b1;
                            Shift <= 1'b0;
                            Busy <= 1'b1;
                            Increment <= 1'b0;
                        end
                COUNT:  begin
                            ResetCounter <= 1'b0;
                            ResetTimer <= 1'b0;
                            Load <= 1'b0;
                            Shift <= 1'b0;
                            Busy <= 1'b1;
                            Increment <= 1'b0;
                        end
                SHIFT:  begin
                            ResetCounter <= 1'b0;
                            ResetTimer <= 1'b0;
                            Load <= 1'b0;
                            Shift <= 1'b1;
                            Busy <= 1'b1;
                            Increment <= 1'b1;
                        end
                WAIT:   begin
                            ResetCounter <= 1'b0;
                            ResetTimer <= 1'b0;
                            Load <= 1'b0;
                            Shift <= 1'b0;
                            Busy <= 1'b0;
                            Increment <= 1'b0;
                        end
                default:begin
                            ResetCounter <= 1'b0;
                            ResetTimer <= 1'b0;
                            Load <= 1'b0;
                            Shift <= 1'b0;
                            Busy <= 1'b0;
                            Increment <= 1'b0;
                        end
            endcase
        end
endmodule

(2)计数器模块:

module Mod10_Counter(
    input       SysClk,
    input       ResetCounter,//高电平有效
    input       Increment,
    input [1:0] mode,
    output reg  Count_finish
);
    reg [3:0] count;
    reg [3:0] count_preload;
// 模式选择
    always @(posedge SysClk or negedge ResetCounter) begin 
        if(ResetCounter) begin
            count_preload <= 0;
        end else begin
                    case (mode)
                        0:  begin
                                count_preload <= 7;
                            end
                        1:  begin
                                count_preload <= 8;
                            end
                        2:  begin
                                count_preload <= 9;
                            end
                        3:  begin
                                count_preload <= 10;
                            end 
                    endcase
        end
    end
// 计数
    always @(posedge SysClk or posedge ResetCounter)
        if(ResetCounter) count <= 4'b0;
        else begin
            if(Increment) begin
                if(count == count_preload) count <= 4'b0;
                else count <= count + 1'b1;
            end
            else count <= count; 
        end

// 产生Count10
    always @(posedge SysClk or posedge ResetCounter)
            if(ResetCounter) Count_finish <= 1'b0;
            else begin
                if(count == count_preload) Count_finish <= 1'b1;
                else Count_finish <= 1'b0;
            end
endmodule
    

(3)奇偶校验

module Parity_Generator(
    input	[7:0]	Din,
    input			ParitySelect,
    output			ParityBit
);

    assign ParityBit = ParitySelect?(~(^Din)):(^Din);//ParitySelect=1,偶校验;ParitySelect=0,奇校验
                                                     //^按位异或
endmodule

(4)移位模块

module Shift_Register(
    input SysClk,
    input rst_n,
    input [7:0] Din,
    input [1:0] mode, //模式选择 5-8位情况 0-5 1-6 2-7 3-8
    input Shift,
    input Load,
    input ParityBit,//æ ¡éªŒä½?
    output wire Dout
);

    wire Start_bit;//èµ·å§‹ä½?
    wire Stop_bit; //停止�
    assign Start_bit = 1'b0;
    assign Stop_bit = 1'b1;

    reg [10:0] Data_Pack;//�帧数� 

// 数据移位
    always @(posedge SysClk or negedge rst_n)
        if(!rst_n) begin
            Data_Pack <= 10'b1111111111; //复位值全为1,避免误触发
        end
        else begin
                if(Load == 1'b1) begin
                	case (mode)
                		0:	begin
                    		Data_Pack <= {3'b111,Stop_bit,ParityBit,Din[4:0],Start_bit};
                			end
                		1:	begin
                			Data_Pack <= {2'b11,Stop_bit,ParityBit,Din[5:0],Start_bit};
                			end
                		2:	begin
                			Data_Pack <= {1'b1,Stop_bit,ParityBit,Din[6:0],Start_bit};
                			end
                		3:	begin
                			Data_Pack <= {Stop_bit,ParityBit,Din[7:0],Start_bit};
                			end 
                	endcase
                end
                else if(Shift == 1'b1) begin
                    Data_Pack <= {1'b1,Data_Pack[9:1]};
                end
                else Data_Pack <= Data_Pack;
        end

// 数据输出
    assign Dout = (!rst_n)?1'b1:Data_Pack[0];
endmodule

(5)时钟模块

//输入50MHZ
//preload   5207   3471   2603   1301
//波特率    9600   14400  19200  38400

module Timer_300Hz(
    input           SysClk,//50MHz
    input           ResetTimer,//高电平有效
    input   [13:0]  preload,
    output reg      NextBit
);
    
    reg [13:0] count;
//    assign preload = 3;//1MHz--->300Hz,每隔333个系统时钟周期发送一次NextBit

//计数
    always @(posedge SysClk or posedge ResetTimer)
        if(ResetTimer) count <= 14'b0;
        else begin
            if(count == preload) count <= 14'b0;
            else count <= count + 1'b1;
        end

// 产生NestBit
    always @(posedge SysClk or posedge ResetTimer)
        if(ResetTimer) NextBit <= 1'b0;
        else begin
            if(count == preload) NextBit <= 1'b1;
            else NextBit <= 1'b0;   
        end
endmodule

6.接收模块的代码

(1)状态转移

module RSM(
    input       SysClk,
    input       rst_n,
    input       Start_rx,
    input       NextBit,
    input       Count_finish,
    output reg  Busy,
    output reg  ResetTimer,
    output reg  Increment,
    output reg  ResetCounter,
    output reg  Shift   
);

//-----------------------------------
//状态变量、状态编码(初始值为0的独热码)
//-----------------------------------           
    reg [3:0]CS,NS;//CS:当前状态;NS:下一状态
    parameter [3:0]
        IDLE   = 4'b0000,
        COUNT  = 4'b0001,
        SHIFT  = 4'b0010,
        Finish = 4'b0100;
   //     WAIT  = 4'b1000;

//-----------------------------------
//时序逻辑描述状态转移
//-----------------------------------   
    always @(posedge SysClk or negedge rst_n)
        if(!rst_n) CS <= IDLE;
        else CS <= NS;

//-----------------------------------
//组合逻辑判断状态转移条件,描述状态转移规律
//-----------------------------------
    always @(rst_n or CS or Start_rx or NextBit or Count_finish)//敏感列表中为复位信号、当前状态和输入条件
        begin
            NS = 4'bx;//默认状态为不定态X
            case(CS)//敏感列表为当前状态
                IDLE:   begin
                            if(!Start_rx)    NS = IDLE;
                            if(Start_rx)     NS = COUNT;
                        end
                COUNT:  begin
                            if(!NextBit) NS = COUNT;
                            if(NextBit)  NS = SHIFT;
                        end
                SHIFT:  begin
                            if(!Count_finish) NS = COUNT;
                            if(Count_finish)  NS = Finish;
                        end
                Finish:   begin
                            NS = IDLE;
                        end 
                default: NS = IDLE;
            endcase
        end

//-----------------------------------
//时序逻辑描述每个状态的输出
//-----------------------------------
 always @(posedge SysClk or negedge rst_n)
        if(!rst_n) begin
            ResetCounter <= 1'b0;
            ResetTimer <= 1'b0;//复位信号高有效
            Shift <= 1'b0;
            Busy <= 1'b0;
            Increment <= 1'b0;
        end
        else begin
            case(NS)//敏感列表为下一状态
                IDLE:   begin
                            ResetCounter <= 1'b1;
                            ResetTimer <= 1'b1;
                            Shift <= 1'b0;
                            Busy <= 1'b0;
                            Increment <= 1'b0;
                        end
                COUNT:  begin
                            ResetCounter <= 1'b0;
                            ResetTimer <= 1'b0;
                            Shift <= 1'b0;
                            Busy <= 1'b1;
                            Increment <= 1'b0;
                        end
                SHIFT:  begin
                            ResetCounter <= 1'b0;
                            ResetTimer <= 1'b0;
                            Shift <= 1'b1;
                            Busy <= 1'b1;
                            Increment <= 1'b1;
                        end
                Finish: begin
                            ResetCounter <= 1'b0;
                            ResetTimer <= 1'b0;
                            Shift <= 1'b0;
                            Busy <= 1'b0;
                            Increment <= 1'b0;
                        end
                default:begin
                            ResetCounter <= 1'b0;
                            ResetTimer <= 1'b0;
                            Shift <= 1'b0;
                            Busy <= 1'b0;
                            Increment <= 1'b0;
                        end
            endcase
        end
endmodule

(2)移位模块

module Shift_Register_rx(
    input           Sysclk,
//    input   [8:0]   D_in,
    input           rst_n,
    input           Shift,
    input           Count_finish,
    input           ParitySelect,
    input   [1:0]   mode,
    input           rx_bit,
    output  [7:0]   D_out,
    output          D_out_valid,
    output          ParityBit,
    output          error
);
    wire  Sysclk;
    reg     [10:0]   reg_D_out;
    reg     [7:0]    reg_D_data;
    reg              Shift_1;
    reg              ParityBit;
    wire             error;
    reg              D_out_valid;
//将shift信号延迟一个周期
    always @(posedge Sysclk or negedge rst_n) begin
        if(~rst_n) begin
            Shift_1 <= 0;
        end else begin
            Shift_1 <= Shift;
        end
    end

// 数据移位
    always @(posedge Sysclk or negedge rst_n)
        if(!rst_n) begin
            reg_D_out <= {11{1'b0}};
        end
        else begin
            if(Shift == 1'b1) begin
                reg_D_out <= {rx_bit,reg_D_out[10:1]};
            end
            else reg_D_out <= reg_D_out;
        end

    always @(posedge Sysclk or negedge rst_n) begin
        if(~rst_n) begin
            reg_D_data <= 0;
            ParityBit <= 0;
            D_out_valid <=0 ;
        end else begin
            if( Shift_1 & Count_finish) begin
                case (mode)
                    0:  begin
                        reg_D_data <= {3'b0,reg_D_out[8:4]};
                        ParityBit  <= reg_D_out[9];
                        end
                    1:  begin
                        reg_D_data <= {2'b0,reg_D_out[8:3]};
                        ParityBit  <= reg_D_out[9];
                        end
                    2:  begin
                        reg_D_data <= {1'b0,reg_D_out[8:2]};
                        ParityBit  <= reg_D_out[9];
                        end
                    3:  begin
                        reg_D_data <= reg_D_out[8:1];
                        ParityBit  <= reg_D_out[9];
                        end 
                endcase
                D_out_valid <= 1;
            end
            else
                D_out_valid <= 0;
    end
    end

    assign error = D_out_valid?(ParityBit^(ParitySelect?(~(^reg_D_data)):(^reg_D_data))):0;

    assign D_out = reg_D_data;


endmodule

(3)时钟模块

//输入50MHZ
//preload   5207   3471   2603   1301
//波特率    9600   14400  19200  38400

module Timer_rx(
    input           SysClk,//50MHz
    input           ResetTimer,//高电平有效
    input   [13:0]  preload,
    output reg      NextBit
);
    
    reg [13:0] count;
//    assign preload = 3;//1MHz--->300Hz,每隔333个系统时钟周期发送一次NextBit

//计数
    always @(posedge SysClk or posedge ResetTimer)
        if(ResetTimer) count <= 14'b0;
        else begin
            if(count == preload) count <= 14'b0;
            else count <= count + 1'b1;
        end

// 产生NestBit
    always @(posedge SysClk or posedge ResetTimer)
        if(ResetTimer) NextBit <= 1'b0;
        else begin
            if(count == preload/2) NextBit <= 1'b1;
            else NextBit <= 1'b0;   
        end
endmodule

(4)计数模块

module Mod_Counter_rx(
    input       SysClk,
    input       ResetCounter,//高电平有效
    input       Increment,
    input  [1:0] mode,
    output reg  Count_finish
);
    reg [3:0] count;
    reg [3:0] count_preload;
// 模式选择
    always @(posedge SysClk or negedge ResetCounter) begin 
        if(ResetCounter) begin
            count_preload <= 0;
        end else begin
                    case (mode)
                        0:  begin
                                count_preload <= 7;
                            end
                        1:  begin
                                count_preload <= 8;
                            end
                        2:  begin
                                count_preload <= 9;
                            end
                        3:  begin
                                count_preload <= 10;
                            end 
                    endcase
        end
    end
// 计数
    always @(posedge SysClk or posedge ResetCounter)
        if(ResetCounter) count <= 4'b0;
        else begin
            if(Increment) begin
                if(count == count_preload) count <= 4'b0;
                else count <= count + 1'b1;
            end
            else count <= count; 
        end

// 产生Count10
    always @(posedge SysClk or posedge ResetCounter)
            if(ResetCounter) Count_finish <= 1'b0;
            else begin
                if(count == count_preload) Count_finish <= 1'b1;
                else Count_finish <= 1'b0;
            end
endmodule
    

7.整体的UART模块

(1)发送的APB模块

// Programmer's model
// 0x00     DATA   R     RXD[7:0]    Received Data
//          DATA   W     TXD[7:0]    Transmit data
module apb_uart(
		input	[7:0]	Din,
		input			Send,
		input			SysClk,
		input			rst_n,
		input	[1:0]	mode,
		input	[13:0]	preload,
		input			ParitySelect,
		output			Busy,
		output	    	Dout
);

	wire SysClk,Send,ParitySelect,rst_n,NextBit;
	wire [7:0]	Din;
	wire [13:0]	preload;
	reg  [7:0]	Din_inside;
	always @(posedge SysClk or negedge rst_n) begin
		if(~rst_n) begin
			Din_inside <= 0;
		end else begin
				    case (mode)
            		0:	begin
            			Din_inside <= {3'b000,Din[4:0]};
            			end
            		1:	begin
            			Din_inside <= {2'b00,Din[5:0]};	
            			end
            		2:	begin
            			Din_inside <= {1'b0,Din[6:0]};	
            			end
            		3:	begin
            			Din_inside <= {Din[7:0]};	
            			end 
                	endcase
				end
	end

	Mod10_Counter inst_Mod10_Counter
		(
			.SysClk       (SysClk),
			.ResetCounter (ResetCounter),
			.Increment    (Increment),
			.mode         (mode),
			.Count_finish (Count_finish)
		);

	Timer_300Hz inst_Timer_300Hz (.SysClk(SysClk), .ResetTimer(ResetTimer), .preload(preload),.NextBit(NextBit));

	Parity_Generator inst_Parity_Generator (.Din(Din_inside), .ParitySelect(ParitySelect), .ParityBit(ParityBit));

	Shift_Register inst_Shift_Register
		(
			.SysClk    (SysClk),
			.rst_n     (rst_n),
			.Din       (Din_inside),
			.mode      (mode),
			.Shift     (Shift),
			.Load      (Load),
			.ParityBit (ParityBit),
			.Dout      (Dout)
		);

	FSM inst_FSM (
			.SysClk       (SysClk),
			.rst_n        (rst_n),
			.Send         (Send),
			.NextBit      (NextBit),
			.Count_finish (Count_finish),
			.Busy         (Busy),
			.ResetTimer   (ResetTimer),
			.Increment    (Increment),
			.ResetCounter (ResetCounter),
			.Shift        (Shift),
			.Load         (Load)
		);

endmodule

(2)接收的APB模块

// Programmer's model
// 0x00     DATA   R     RXD[7:0]    Received Data
//          DATA   W     TXD[7:0]    Transmit data
module apb_uart_rx(
		input	    	Din,
		input			SysClk,
		input			rst_n,
		input	[1:0]	mode,
		input	[13:0]	preload,
		input			ParitySelect,
		output			Busy,
		output			error,
		output 			D_out_valid,
		output	[7:0]	D_out
);

	wire ParitySelect,rst_n,NextBit;
	wire [1:0]	mode;
	wire	Din,error;
	reg 	Din_1;
	reg  	Din_2; //两级同步后的数据
	reg  	Din_3;
	wire    Start_rx;
	wire [13:0]	preload;
	wire [7:0]  D_out;

//为避免亚稳态,使用两级同步
always @(posedge SysClk or negedge rst_n) begin
	if(~rst_n) begin
		Din_1 <= 0;
		Din_2 <= 0;
		Din_3 <= 0;
	end else begin
		Din_1 <= Din;
		Din_2 <= Din_1;
		Din_3 <= Din_2; 
	end
end

//取Din的下降沿信号
assign Start_rx = (~Din_2)&Din_3 ;

	Mod_Counter_rx inst_Mod_Counter_rx
		(
			.SysClk       (SysClk),
			.ResetCounter (ResetCounter),
			.Increment    (Increment),
			.mode         (mode),
			.Count_finish (Count_finish)
		);

	Timer_rx inst_Timer_rx (.SysClk(SysClk), .ResetTimer(ResetTimer), .preload(preload),.NextBit(NextBit));


	Shift_Register_rx inst_Shift_Register_rx
		(
			.Sysclk    (SysClk),
			.rst_n     (rst_n),
			.mode      (mode),
			.rx_bit    (Din_2),
			.Count_finish (Count_finish),
			.ParitySelect (ParitySelect),
			.ParityBit (ParityBit),
			.Shift     (Shift),
			.D_out_valid (D_out_valid),
			.error	   (error),
			.D_out      (D_out)
		);

	RSM inst_RSM (
			.SysClk       (SysClk),
			.rst_n        (rst_n),
			.Start_rx     (Start_rx),
			.NextBit      (NextBit),
			.Count_finish (Count_finish),
			.Busy         (Busy),
			.ResetTimer   (ResetTimer),
			.Increment    (Increment),
			.ResetCounter (ResetCounter),
			.Shift        (Shift)
		);

endmodule

(2)整个模块

`timescale 1ns/1ns
//定义寄存器的地址
//`define reg_enable  8'h00
//`define reg_mode  8'h04 
//`define reg_preload    8'h08
//`define reg_counter   8'h0c 


module apb_uart_tx_rx(
	input 		  PCLK,	    //时钟
	input		  PRESETn,   //复位
	input [15:0]  PADDR,    //地址信号
	input  		  PWRITE,   //控制信号 1:写 0:读
	input [31:0]  PWDATA,   //写数据
	input         PENABLE,  //使能信号
	input         PSEL,    //片选信号	
	input  		  RXD,
	output [31:0] PRDATA,   //读数据
	output		  TXD,
    output wire        PREADY,  // Device ready
    output wire        PSLVERR, // Device error response
    output uart_intr      //中断输出
);

  assign PREADY  = 1'b1; // Always ready
  assign PSLVERR = 1'b0; // Always okay
  reg			Send_reg;
  reg	[1:0]   mode_reg;
  reg			ParitySelect_reg;
  reg	[7:0]	Din_reg;
  reg	[13:0]	preload_reg;
  reg	[31:0]	prdata_r;
  wire			Busy_rx;
  wire	[7:0]	D_out_reg;
////	写寄存器 //////////
always @(posedge PCLK or negedge PRESETn) begin
	if(~PRESETn) begin
		Send_reg <= 0;
		mode_reg <= 0;
		preload_reg <= 0;
		ParitySelect_reg <= 0;
		Din_reg <= 0;
	end 
	else if(PSEL && PENABLE && PWRITE)
		case (PADDR[4:2])
		3'b000:  Send_reg <= PWDATA[0];
		3'b001:  mode_reg <= PWDATA[1:0];
		3'b010:  preload_reg <= PWDATA[13:0];
		3'b011:  ParitySelect_reg <= PWDATA[0];
		3'b100:  Din_reg <= PWDATA[7:0];		
		default : begin
				Send_reg <= 0;
				mode_reg <= 0;
				preload_reg <= 0;
				ParitySelect_reg <= 0;
				Din_reg <= 0;	
		end
		endcase
end

////	读寄存器 //////////
always @(posedge PCLK or negedge PRESETn) begin
	if(~PRESETn) begin
		prdata_r <= 32'b0;
	end 
	else if(PSEL && !PENABLE && !PWRITE)
		case (PADDR[4:2])
		3'b000:  prdata_r <= {31'b0,Send_reg};
		3'b001:  prdata_r <= {30'b0,mode_reg};
		3'b010:  prdata_r <= {18'b0,preload_reg};
		3'b011:  prdata_r <= {31'b0,Busy_reg};	
		3'b100:  prdata_r <= {31'b0,Busy_rx};
		3'b101:  prdata_r <= {31'b0,D_out_valid};
		3'b110:  prdata_r <= {24'b0,D_out_reg};	
		default : begin
				prdata_r <= 32'b0;	
		end
		endcase
end
	assign PRDATA = prdata_r;
	
	apb_uart inst_apb_uart_tx
		(
			.Din          (Din_reg),
			.Send         (Send_reg),
			.SysClk       (PCLK),
			.rst_n        (PRESETn),
			.mode         (mode_reg),
			.preload      (preload_reg),
			.ParitySelect (ParitySelect_reg),
			.Busy         (Busy_reg),
			.Dout         (TXD)
		);

	apb_uart_rx inst_apb_uart_rx
		(
			.Din          (RXD),
			.SysClk       (PCLK),
			.rst_n        (PRESETn),
			.mode         (mode_reg),
			.preload      (preload_reg),
			.ParitySelect (ParitySelect_reg),
			.Busy         (Busy_rx),
			.error        (error),
			.D_out_valid  (D_out_valid),
			.D_out        (D_out_reg)
		);

endmodule

您可能感兴趣的与本文相关内容

想深耕嵌入式?这个专辑值得收藏

MCU、FPGA、工控、传感器一站式学习,实战项目直接抄

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值