UART 通信逻辑协议设计(2)

来源:互联网 发布:window 安装ubuntu 编辑:程序博客网 时间:2024/06/07 22:37

5 . 各模块详细设计
1)波特率发生器模块:假定系统时钟为50M,波特率为115200,则传输每一位所需的时间为8.6805us,而将其分频至波特率的16倍则需计数则在系统时钟下当计数值为27时则将Baud16Tick置为1,其他时间都为0。要得到波特率脉冲时则在Baud16Tick节拍下计数至16时将BaudTick置为1,其他值时为0。程序如下:

  always @(posedge clk )      begin      if (rst)        begin                OverSampleCnt <=8'b0;                Baud16Tick <= 1'b0;         end      elseif(OverSampleCnt== OverSampleCntnum)        OverSampleCnt <= 1'b0;      else         OverSampleCnt <=OverSampleCnt+1;      case(OverSampleCnt== OverSampleCntnum/2)          OverSampleCntnum/2:Baud16Tick <= 1'b1;        default:Baud16Tick <= 1'b0;  endcase     End always @(posedge clk or negedge rst)begin  if (rst)    begin        BaudTick <= 1'b0;         BaudTickCnt <= 4'b0000 ;    end  else if (Baud16Tick&&BaudTick_EN)  BaudTickCnt = BaudTickCnt +1 ;  elseif((BaudTickCnt== 4’b1111)  BaudTickCnt <= 4'b0000 ;    case(BaudTickCnt)   4'b1000:BaudTick <= 1'b1;  default:BaudTick <= 1'b0;   endcaseend

2)数据发送器模块:在Baud16Tick的节拍下捕捉TXD_start的下降沿,之后将din8的数据存入缓冲器tbr中,再启动BaudTick脉冲并计数,在计数为4’b0000时发送停止位0,在4’b0001至4’b1000时发送数据位,并在之后两位发送奇偶校验位和停止位。没有发送是则发送空闲位1。校验每发一位就将parity进行异或数据位得到其值并发送。当发送停止位后,即将发送完成标志位TXD_done置1.程序如下:

always@(posedge clk)    begin        if(rst)            begin                {TxD_start0,TxD_start1} <= {1'b0,1'b0};            end        else             TxD_start0 <= TxD_start;            TxD_start1 <= TxD_start0;       endassign start = TxD_start1&!TxD_start0;always@(posedge clk or posedge rst)    begin         if(rst)             tbr<= 8'b0;        else if(BaudTick_EN&&BaudTick)            tbr <= TxD_data;    end always @(posedge clk or posedge rst)    begin        if (rst)            BaudTick_EN <= 1'b0;        else if (start)                   BaudTick_EN <= 1'b1 ;        else if (no_bits_tran == 4'b1100)            BaudTick_EN <= 1'b0 ;  endalways @(posedge clk or negedge rst )    begin        if (rst)            no_bits_tran <= 4'b0000;        else if (BaudTick&&Baud16Tick)          no_bits_tran <= no_bits_tran + 1 ;        else if (no_bits_tran ==4'b1100)            no_bits_tran <= 4'b0000 ;   endalways @(posedge clk or negedge rst)     if (rst)       begin         TxD <= 1'b1;          tbr <= 8'b0 ;         tsr <= 8'b0 ;          parity <= 1'b0 ;          TxD_done <= 1'b0;      end     else       begin             if(BaudTick)                begin                    case (no_bits_tran)                        4'b0000: begin                                     TxD <= 1'b0;                                     tsr <= tbr;                                     parity <= ^tsr ;                                     TxD_done <= 1'b0;                                end                        4'b0001: begin TxD <= tsr[0]; end                        4'b0010: begin TxD <= tsr[1]; end                        4'b0011: begin TxD <= tsr[2]; end                        4'b0100: begin TxD <= tsr[3]; end                        4'b0101: begin TxD <= tsr[4]; end                        4'b0110: begin TxD <= tsr[5]; end                        4'b0111: begin TxD <= tsr[6]; end                        4'b1000: begin TxD <= tsr[7]; end                        4'b1001: begin TxD <= parity; end                        4'b1010: begin TxD <= 1'b1; end                        4'b1011: begin                                   TxD_done <= 1'b1;                                end                        default: TxD_done <= 1'b0 ;                    endcase                end        end  

3)数据接收器模块:首先利用波特率16的采样脉冲对发送模块发送过来的串行数据进行下降沿采样,若采集到下降沿则开始启动BaudTick,并开启计数使能。在BaudTick的脉冲下进行计数并逐位读取发送端发过来的数据位,奇偶校验在case值为4’b0001至4’b1000时进行,当计数为4’b1001时发送判断校验位和检测停止位,在4’b1010时将奇偶校验和帧检查结果发送到端口中。程序如下所示:

always@(posedge clk or negedge rst)    begin        if(rst)            begin                {TxD_start0,TxD_start1} <= {1'b0,1'b0};            end        else             TxD_start0 <= TxD_start;            TxD_start1 <= TxD_start0;       endassign start = TxD_start1&!TxD_start0;always @(posedge clk or negedge rst )    begin        if (rst)            no_bits_tran <= 4'b0000;        else if (BaudTick&&Baud16Tick)          no_bits_tran <= no_bits_tran + 1 ;        else if (no_bits_tran ==4'b1100)            no_bits_tran <= 4'b0000 ;    Endalways@(posedge clk or posedge rst)    begin         if(rst)             tbr<= 8'b0;        else if(BaudTick_EN&&BaudTick)            tbr <= TxD_data;    end always @(posedge clk or negedge rst )    begin        if (rst)            no_bits_tran <= 4'b0000;        else if (BaudTick&&Baud16Tick)            no_bits_tran <= no_bits_tran + 1 ;        else if (no_bits_tran ==4'b1100)            no_bits_tran <= 4'b0000 ;    endalways @(posedge clk or negedge rst)     if (rst)    begin      TxD <= 1'b1; tbr <= 8'b0 ;      tsr <= 8'b0 ; parity <= 1'b0 ;       TxD_done <= 1'b0;      end     else       begin             if(BaudTick)                begin                    case (no_bits_tran)                        4'b0000: begin                             TxD <= 1'b0; tsr <= tbr; parity <= ^tsr ;TxD_done <= 1'b0;                                end                        4'b0001: begin TxD <= tsr[0]; end                        4'b0010: begin TxD <= tsr[1]; end                        4'b0011: begin TxD <= tsr[2]; end                        4'b0100: begin TxD <= tsr[3]; end                        4'b0101: begin TxD <= tsr[4]; end                        4'b0110: begin TxD <= tsr[5]; end                        4'b0111: begin TxD <= tsr[6]; end                        4'b1000: begin TxD <= tsr[7]; end                        4'b1001: begin TxD <= parity; end                        4'b1010: begin TxD <= 1'b1; end                        4'b1011: begin                                  TxD_done <= 1'b1;                                end                        default: TxD_done <= 1'b0 ;                    endcase                end        end

3)顶层文件设计:两模块之间用wire类型连接,公共端用分别在两个模块中连接。顶层端口定义最终需要的端口即可。顶层模块如下:

TxD_Module u1(            .clk(clk_sys),            .rst(rst_N),            .TxD_data(din8),            .TxD_done(TxDdne_rdn),            .TxD(TxD_RxD),            .TxD_start(TxD_start_in)            );RxD_Module u2 (            .clk(clk_sys),            .rst(rst_N),            .rdn(TxDdne_rdn),            .RxD(TxD_RxD),            .RxD_data(dout8),            .parity_error(parity_err_out),            .framing_error(frame_err_out),            .RxD_data_ready(RxD_data_rdy)            );

6.Modelsim仿真验证
1)测试激励:高电平初始化后进行发送递加的数据,并观察输入输出数据的差异,以及奇偶校验位和帧检查的正确性。

initial         begin            clk_sys = 0;            rst_N = 1;            din8 = 0;            TxD_start_in = 0;            #100;               rst_N = 0;            repeat(100) begin            #   86800;            TxD_start_in = 1;            # 86800;            TxD_start_in = 0;        end      end   always #10  clk_sys = ~clk_sys;      always @(posedge TxD_start_in)    begin         din8 = din8 + 8'd1;    end 

2)输入输出结果。激励文件和输出结果如下:http://blog.csdn.net/shanyuan007/article
3) 结果分析:由上图可知
  1 整个联合模块的并行输入与并行输出结果相同,接发送和接收正确。
  2 奇偶校验位发现当数据为01010010时校验的结果为1,当数据为01010011时校验结果为0;由此可知奇偶校验正确
  3 检查帧结果显示一致为0,而发送端的数据均为8位且停止位都为1。所以帧检查结果正确。

0 0
原创粉丝点击