天天看點

通信總線----UART(有詳細代碼)

UART

通用異步收發傳輸器(Universal Asynchronous Receiver/Transmitter),通常稱作UART。它将要傳輸的資料在串行通信與并行通信之間加以轉換。作為把并行輸入信号轉成串行輸出信号的晶片,UART通常被內建于其他通訊接口的連結上。

本文詳細文檔和完整的代碼會在後面文章以文檔的形式發出來

1. 硬體連接配接

硬體連接配接比較簡單,僅需要3條線,注意連接配接時兩個裝置UART電平,如電平範圍不一緻請做電平轉換後再連接配接,如下圖所示:

通信總線----UART(有詳細代碼)

TX:發送資料端,要接對面裝置的RX

RX:接收資料端,要接對面裝置的TX

GND:保證兩裝置共地,有統一的參考平面

2. 軟體通信協定

通信總線----UART(有詳細代碼)

空閑位:

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)發送的框圖:

通信總線----UART(有詳細代碼)

(2)發送的狀态轉移圖:

通信總線----UART(有詳細代碼)

(3)時鐘産生子產品:

通信總線----UART(有詳細代碼)

(4)計數器子產品:

通信總線----UART(有詳細代碼)

(5)奇偶校驗子產品:

通信總線----UART(有詳細代碼)

(6)移位寄存器子產品:

通信總線----UART(有詳細代碼)

4.接收具體子產品介紹:

(1)接收子產品的框圖:

通信總線----UART(有詳細代碼)

(2)接收子產品的狀态轉移圖:

通信總線----UART(有詳細代碼)

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
           

繼續閱讀