IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> MCU_DESIGN_04MUC外设APB_UART -> 正文阅读

[嵌入式]MCU_DESIGN_04MUC外设APB_UART

1.UART了解

①说白了就是串口,包括RX、TX两端,用来进行低速的通信

RX时序

在这里插入图片描述
具体的时序描述可以参考Verilog RTL 代码实战 06——RS232串口接收模块

TX时序

在这里插入图片描述
具体的时序描述可以参考Verilog RTL 代码实战 07——RS232串口发送模块

2.APB_UART结构

①结构组成

  • 写缓存:对APB送过来的数据进行缓存,串口的传输速度没有APB传的快,因此需要容器缓存防止数据丢失
  • 读缓存:同上理
  • 波特率生成:控制传输的速度,单位bps(bit/s)
  • 移位并转串:将8位数据以为一位拆开
  • 移位串转并:将一位一位数据合成8位数据
  • TX状态机:TX相应时序的完成
  • RX状态机:RX相应时序的完成

在这里插入图片描述
②因为结构比较简单,所以可以由一个模块完成其功能,模块端口如下图:

在这里插入图片描述
③设计要点

  • APB接口寄存器配置(控制和数据)
  • 读写数据存储和移位
  • 波特率的产生
  • 数据移位控制状态机
  • 外部输入的异步处理和滤波
  • 中断控制和处理

3.寄存器

在这里插入图片描述

4.RTL代码

4.1端口

①PCLKG 门控时钟

②ECOREVNUM 协议管理,和UART本身无关

③相比普通的UART,多加了一些中断信号(INT后缀)

module cmsdk_apb_uart (

  input  wire        PCLK,     // Clock
  input  wire        PCLKG,    // Gated Clock
  input  wire        PRESETn,  // Reset

  input  wire        PSEL,     // Device select
  input  wire [11:2] PADDR,    // Address
  input  wire        PENABLE,  // Transfer control
  input  wire        PWRITE,   // Write control
  input  wire [31:0] PWDATA,   // Write data

  input  wire [3:0]  ECOREVNUM,// Engineering-change-order revision bits

  output wire [31:0] PRDATA,   // Read data
  output wire        PREADY,   // Device ready
  output wire        PSLVERR,  // Device error response

  input  wire        RXD,      // Serial input
  output wire        TXD,      // Transmit data output
  output wire        TXEN,     // Transmit enabled
  output wire        BAUDTICK, // Baud rate (x16) Tick

  output wire        TXINT,    // Transmit Interrupt
  output wire        RXINT,    // Receive Interrupt
  output wire        TXOVRINT, // Transmit overrun Interrupt
  output wire        RXOVRINT, // Receive overrun Interrupt
  output wire        UARTINT); // Combined interrupt

4.2 内部信号

①读写控制信号:寄存器的写使能

// Signals for read/write controls
wire          read_enable;
wire          write_enable;
wire          write_enable00; // Write enable for data register
wire          write_enable04; // Write enable for Status register
wire          write_enable08; // Write enable for control register
wire          write_enable0c; // Write enable for interrupt status register
wire          write_enable10; // Write enable for Baud rate divider
reg     [7:0] read_mux_byte0; // Read data multiplexer for lower 8-bit
reg     [7:0] read_mux_byte0_reg; // Register read data for lower 8-bit
wire   [31:0] read_mux_word;  // Read data multiplexer for whole 32-bit

②寄存器信号

// Signals for Control registers
reg     [6:0] reg_ctrl;       // Control register
reg     [7:0] reg_tx_buf;     // Transmit data buffer
reg     [7:0] reg_rx_buf;     // Receive data buffer
reg    [19:0] reg_baud_div;   // Baud rate setting

③波特率分频信号

// Internal signals
// Baud rate divider
reg    [15:0] reg_baud_cntr_i; // baud rate divider counter i (integer)
wire   [15:0] nxt_baud_cntr_i;
reg     [3:0] reg_baud_cntr_f; // baud rate divider counter f (fraction)
wire    [3:0] nxt_baud_cntr_f;
wire    [3:0] mapped_cntr_f;   // remapped counter f value 
reg           reg_baud_tick;   // Register baud rate tick (16 times of baud rate)
reg           baud_updated;    // baud rate value has bee updated from APB
wire          reload_i;        // baud rate divider counter i reload
wire          reload_f;        // baud rate divider counter f reload
wire          baud_div_en;     // enable baud rate counter

④状态信号

  // Status
wire    [3:0] uart_status;     // UART status
reg           reg_rx_overrun;  // Receive overrun status register
wire          rx_overrun;      // Receive overrun detection
reg           reg_tx_overrun;  // Transmit overrun status register
wire          tx_overrun;      // Transmit overrun detection
wire          nxt_rx_overrun;  // next state for reg_rx_overrun
wire          nxt_tx_overrun;  // next state for reg_tx_overrun

⑤中断信号

// Interrupts
reg           reg_txintr;      // Transmit interrupt register
reg           reg_rxintr;      // Receive interrupt register
wire          tx_overflow_intr;// Transmit overrun/overflow interrupt
wire          rx_overflow_intr;// Receive overrun/overflow interrupt
wire    [3:0] intr_state;      // UART interrupt status
wire    [1:0] intr_stat_set;   // Set TX/RX interrupt
wire    [1:0] intr_stat_clear; // Clear TX/RX interrupt

⑥tx传输信号

// transmit
	reg     [3:0] tx_state;    // Transmit FSM state
	reg     [4:0] nxt_tx_state;
	wire          tx_state_update;
	wire          tx_state_inc; // Bit pulse
	reg     [3:0] tx_tick_cnt;  // Transmit Tick counter
	wire    [4:0] nxt_tx_tick_cnt;
	reg     [7:0] tx_shift_buf;      // Transmit shift register
	wire    [7:0] nxt_tx_shift_buf;  // next state    for tx_shift_buf
	wire          tx_buf_ctrl_shift; // shift control for tx_shift_buf
	wire          tx_buf_ctrl_load;  // load  control for tx_shift_buf
	reg           tx_buf_full;  // TX Buffer full
	reg           reg_txd;      // Tx Data
	wire          nxt_txd;      // next state of reg_txd
	wire          update_reg_txd; // update reg_txd
	wire          tx_buf_clear; // Clear buffer full status when data is load into TX shift register

⑦rx传输信号

 // Receiver
reg     [3:0] rx_state;   // Receiver FSM state
reg     [4:0] nxt_rx_state;
wire          rx_state_update;
reg     [3:0] rx_tick_cnt; // Receiver Tick counter
wire    [4:0] nxt_rx_tick_cnt;
wire          update_rx_tick_cnt;
wire          rx_state_inc;// Bit pulse
reg     [6:0] rx_shift_buf;// Receiver shift data register
wire    [6:0] nxt_rx_shift_buf;
reg           rx_buf_full;  // Receive buffer full status
wire          nxt_rx_buf_full;
wire          rxbuf_sample; // Sample received data into receive data buffer
wire          rx_data_read; // Receive data buffer read by APB interface
wire    [7:0] nxt_rx_buf;

⑧异步处理信号

reg           rxd_sync_1;  // Double flip-flop syncrhoniser
reg           rxd_sync_2;  // Double flip-flop syncrhoniser

⑨滤波信号

 // Receive data sync and filter
reg     [2:0] rxd_lpf;     // Averaging Low Pass Filter
wire    [2:0] nxt_rxd_lpf;
wire          rx_shift_in; // Shift Register Input

4.3 寄存器及读写使能

①0x00 读写的数据

②0x04 读写的状态,有无 overrun

③0x08 读写的控制,读写使能、中断使能

④0x0C 中断状态

⑤0x10 波特率设置

// 0x00 R     RXD[7:0]    Received Data
//      W     TXD[7:0]    Transmit data
// 0x04 RW    STAT[3:0]
//              [3] RX buffer overrun (write 1 to clear)
//              [2] TX buffer overrun (write 1 to clear)
//              [1] RX buffer full (Read only)
//              [0] TX buffer full (Read only)
// 0x08 RW    CTRL[3:0]   TxIntEn, RxIntEn, TxEn, RxEn
//              [6] High speed test mode Enable
//              [5] RX overrun interrupt enable
//              [4] TX overrun interrupt enable
//              [3] RX Interrupt Enable
//              [2] TX Interrupt Enable
//              [1] RX Enable
//              [0] TX Enable
// 0x0C R/Wc  intr_status/INTCLEAR
//              [3] RX overrun interrupt
//              [2] TX overrun interrupt
//              [1] RX interrupt
//              [0] TX interrupt
// 0x10 RW    BAUDDIV[19:0] Baud divider
//            (minimum value is 16)



// Read and write control signals
assign  read_enable  = PSEL & (~PWRITE); // assert for whole APB read transfer
assign  write_enable = PSEL & (~PENABLE) & PWRITE; // assert for 1st cycle of write transfer
assign  write_enable00 = write_enable & (PADDR[11:2] == 10'h000);
assign  write_enable04 = write_enable & (PADDR[11:2] == 10'h001);
assign  write_enable08 = write_enable & (PADDR[11:2] == 10'h002);
assign  write_enable0c = write_enable & (PADDR[11:2] == 10'h003);
assign  write_enable10 = write_enable & (PADDR[11:2] == 10'h004);

4.4 写操作

①数据放入寄存器,这个电路很经典

  // Transmit data register
  always @(posedge PCLKG or negedge PRESETn)
  begin
    if (~PRESETn)
      reg_tx_buf <= {8{1'b0}};
    else if (write_enable00)
      reg_tx_buf <= PWDATA[7:0];
  end

②rx、tx的overrun:nxt_rx_overrun的组合逻辑实现了PWDATA[3]写1清零,同理nxt_tx_overrun也是

// Status register overrun registers
  assign nxt_rx_overrun = (reg_rx_overrun & (~((write_enable04|write_enable0c) & PWDATA[3]))) | rx_overrun;
  assign nxt_tx_overrun = (reg_tx_overrun & (~((write_enable04|write_enable0c) & PWDATA[2]))) | tx_overrun;

  // RX OverRun status
  always @(posedge PCLK or negedge PRESETn)
  begin
    if (~PRESETn)
      reg_rx_overrun <= 1'b0;
    else if (rx_overrun | write_enable04 | write_enable0c)
      reg_rx_overrun <= nxt_rx_overrun;
  end

  // TX OverRun status
  always @(posedge PCLK or negedge PRESETn)
  begin
    if (~PRESETn)
      reg_tx_overrun <= 1'b0;
    else if (tx_overrun | write_enable04 | write_enable0c)
      reg_tx_overrun <= nxt_tx_overrun;
  end

③控制寄存器:7位,和上面的reg_tx_buf 电路结构类似

  // Control register
  always @(posedge PCLKG or negedge PRESETn)
  begin
    if (~PRESETn)
      reg_ctrl <= {7{1'b0}};
    else if (write_enable08)
      reg_ctrl <= PWDATA[6:0];
  end

④波特率分频

  // Baud rate divider - integer
  always @(posedge PCLKG or negedge PRESETn)
  begin
    if (~PRESETn)
      reg_baud_div <= {20{1'b0}};
    else if (write_enable10)
      reg_baud_div <= PWDATA[19:0];
  end

4.5 读操作

①uart状态:使用几个信号的拼接

assign uart_status = {reg_rx_overrun, reg_tx_overrun, rx_buf_full, tx_buf_full};

②读操作的第一个阶段:用PADDR确定read_mux_byte0的值,后面PID是芯片有关的程序,和UART无关,然后将read_mux_byte0存到read_mux_byte0_reg中

  // First level of read mux
 always @(*)
  begin
   if (PADDR[11:5] == 7'h00) begin
     case (PADDR[4:2])
     3'h0: read_mux_byte0 =  reg_rx_buf;
     3'h1: read_mux_byte0 =  {{4{1'b0}},uart_status};
     3'h2: read_mux_byte0 =  {{1{1'b0}},reg_ctrl};
     3'h3: read_mux_byte0 =  {{4{1'b0}},intr_state};
     3'h4: read_mux_byte0 =  reg_baud_div[7:0];
     3'h5, 3'h6, 3'h7: read_mux_byte0 =   {8{1'b0}};     //default read out value
     default:  read_mux_byte0 =   {8{1'bx}};// x propogation
     endcase
   end
   else if (PADDR[11:6] == 6'h3F) begin
     case  (PADDR[5:2])
       4'h0, 4'h1,4'h2,4'h3: read_mux_byte0 =   {8{1'b0}}; //default read out value
   // ID register - constant values
       4'h4: read_mux_byte0 = ARM_CMSDK_APB_UART_PID4; // 0xFD0 : PID 4
       4'h5: read_mux_byte0 = ARM_CMSDK_APB_UART_PID5; // 0xFD4 : PID 5
       4'h6: read_mux_byte0 = ARM_CMSDK_APB_UART_PID6; // 0xFD8 : PID 6
       4'h7: read_mux_byte0 = ARM_CMSDK_APB_UART_PID7; // 0xFDC : PID 7
       4'h8: read_mux_byte0 = ARM_CMSDK_APB_UART_PID0; // 0xFE0 : PID 0  APB UART part number[7:0]
       4'h9: read_mux_byte0 = ARM_CMSDK_APB_UART_PID1; // 0xFE0 : PID 1 [7:4] jep106_id_3_0. [3:0] part number [11:8]
       4'hA: read_mux_byte0 = ARM_CMSDK_APB_UART_PID2; // 0xFE0 : PID 2 [7:4] revision, [3] jedec_used. [2:0] jep106_id_6_4
       4'hB: read_mux_byte0 = {ECOREVNUM[3:0],pid3_value[3:0]};
                                                       // 0xFE0 : PID 3 [7:4] ECO revision, [3:0] modification number
       4'hC: read_mux_byte0 = ARM_CMSDK_APB_UART_CID0; // 0xFF0 : CID 0
       4'hD: read_mux_byte0 = ARM_CMSDK_APB_UART_CID1; // 0xFF4 : CID 1 PrimeCell class
       4'hE: read_mux_byte0 = ARM_CMSDK_APB_UART_CID2; // 0xFF8 : CID 2
       4'hF: read_mux_byte0 = ARM_CMSDK_APB_UART_CID3; // 0xFFC : CID 3
       default : read_mux_byte0 = {8{1'bx}}; // x propogation
      endcase
    end
    else begin
       read_mux_byte0 =   {8{1'b0}};     //default read out value
    end
  end
  // Register read data
  always @(posedge PCLKG or negedge PRESETn)
  begin
    if (~PRESETn)
      read_mux_byte0_reg      <= {8{1'b0}};
    else if (read_enable)
      read_mux_byte0_reg      <= read_mux_byte0;
  end

③读的第二个阶段:给32位的read_mux_word赋值并传到APB总线上

 // Second level of read mux
  assign read_mux_word[ 7: 0] = read_mux_byte0_reg;
  assign read_mux_word[19: 8] = (PADDR[11:2]==10'h004) ? reg_baud_div[19:8] : {12{1'b0}};
  assign read_mux_word[31:20] = {12{1'b0}};

  // Output read data to APB
  assign PRDATA[31: 0] = (read_enable) ? read_mux_word : {32{1'b0}};
  assign PREADY  = 1'b1; // Always ready
  assign PSLVERR = 1'b0; // Always okay

4.6 波特率的产生

①使能:由reg_ctrl信号决定分频使能

  // Baud rate generator enable
  assign baud_div_en    = (reg_ctrl[1:0] != 2'b00);

②减一计数器:处理高16位的波特率信号,剩下的4位看③

  // Reload Integer divider
  assign reload_i      = (baud_div_en &  (reg_baud_cntr_i[15:0] == {16{1'b0}}));

  // Next state for Baud rate divider
  assign nxt_baud_cntr_i = (baud_updated | reload_i) ? reg_baud_div[19:4] :(reg_baud_cntr_i - 16'h0001);
  
  // Update at reload or decrement
  always @(posedge PCLK or negedge PRESETn)
  begin
    if (~PRESETn)
      reg_baud_cntr_i   <= {16{1'b0}};
    else if (baud_updated | baud_div_en)
      reg_baud_cntr_i   <= nxt_baud_cntr_i;
  end

③又一个减一计数器:处理低4位的波特率信号,这些计数器的效果就是为了实现分频从而改变脉冲生成的频率,进而改变波特率

 // Reload fraction divider
  assign reload_f      = baud_div_en & (reg_baud_cntr_f==4'h0) &
                        reload_i;
  // Next state for fraction part of Baud rate divider
  assign nxt_baud_cntr_f =
                        (reload_f|baud_updated) ? 4'hF :
                        (reg_baud_cntr_f - 4'h1);

  // Update at reload or decrement
  always @(posedge PCLK or negedge PRESETn)
  begin
    if (~PRESETn)
      reg_baud_cntr_f   <= {4{1'b0}};
    else if (baud_updated | reload_f | reload_i)
      reg_baud_cntr_f   <= nxt_baud_cntr_f;
  end

④波特率更新信号:由write_enable10决定

  // Generate control signal to update baud rate counters
  always @(posedge PCLK or negedge PRESETn)
  begin
    if (~PRESETn)
      baud_updated    <= 1'b0;
    else if (write_enable10 | baud_updated)
      // Baud rate updated - to load new value to counters
      baud_updated    <= write_enable10;
  end

⑤波特率的外部测试BAUDTICK = reg_baud_tick

  // Generate Tick signal for external logic
  always @(posedge PCLK or negedge PRESETn)
  begin
    if (~PRESETn)
      reg_baud_tick    <= 1'b0;
    else if (reload_i | reg_baud_tick)
      reg_baud_tick    <= reload_i;
  end

  // Connect to external
  assign BAUDTICK = reg_baud_tick;

4.7 tx传输

①buff满信号:由write_enable00 和tx_buf_clear决定拉高和拉低

  // Buffer full status
  always @(posedge PCLK or negedge PRESETn)
  begin
    if (~PRESETn)
      tx_buf_full     <= 1'b0;
    else if (write_enable00 | tx_buf_clear)
      tx_buf_full     <= write_enable00;
  end

②tx_tick_cnt 计数器:

  // Increment TickCounter
  assign nxt_tx_tick_cnt = ((tx_state==4'h1) & reg_baud_tick) ? {5{1'b0}} :
                        tx_tick_cnt + {{3{1'b0}},reg_baud_tick};

  // Registering TickCounter
  always @(posedge PCLK or negedge PRESETn)
  begin
    if (~PRESETn)
      tx_tick_cnt     <= {4{1'b0}};
    else if (reg_baud_tick)
      tx_tick_cnt     <= nxt_tx_tick_cnt[3:0];
  end

③tx自加状态和buf清理

  // Increment state (except Idle(0) and Wait for Tick(1))
  assign tx_state_inc   = (((&tx_tick_cnt)|(tx_state==4'h1)) & reg_baud_tick)|reg_ctrl[6];
          // state increment every cycle of high speed test mode is enabled
  // Clear buffer full status when data is load into shift register
  assign tx_buf_clear   = ((tx_state==4'h0) & tx_buf_full) |
                        ((tx_state==4'hB) & tx_buf_full & tx_state_inc);

④tx状态机

各个值对应的状态:

0 = Idle
1 = Wait for Tick
2 = Start bit
3 = D0

10 = D7
11 = Stop bit

  always @(tx_state or tx_buf_full or tx_state_inc or reg_ctrl)
  begin
  case (tx_state)
    0: begin
       nxt_tx_state = (tx_buf_full & reg_ctrl[0]) ? 5'h01 : 5'h00;  // New data is written to buffer
       end
    1,                         // State 1   : Wait for next Tick
    2,3,4,5,6,7,8,9,10: begin  // State 2-10: Start bit, D0 - D7
       nxt_tx_state = tx_state + {3'b000,tx_state_inc};
       end
    11: begin // Stop bit , goto next start bit or Idle
       nxt_tx_state = (tx_state_inc) ? ( tx_buf_full ? 5'h02:5'h00) : {1'b0, tx_state};
       end
    default:
       nxt_tx_state = {5{1'bx}};
  endcase
  end

  assign tx_state_update = tx_state_inc | ((tx_state==4'h0) & tx_buf_full & reg_ctrl[0]) | (tx_state>4'd11);

  // Registering outputs
  always @(posedge PCLK or negedge PRESETn)
  begin
    if (~PRESETn)
      tx_state        <= {4{1'b0}};
    else if (tx_state_update)
      tx_state        <= nxt_tx_state[3:0];
  end

⑤tx移位

  // Load/shift TX register
  assign tx_buf_ctrl_load  = (((tx_state==4'h0) & tx_buf_full) |
                              ((tx_state==4'hB) & tx_buf_full & tx_state_inc));
  assign tx_buf_ctrl_shift =  ((tx_state>4'h2) & tx_state_inc);

  assign nxt_tx_shift_buf = tx_buf_ctrl_load ? reg_tx_buf : {1'b1,tx_shift_buf[7:1]};

  // Registering TX shift register
  always @(posedge PCLK or negedge PRESETn)
  begin
    if (~PRESETn)
      tx_shift_buf    <= {8{1'b0}};
    else if (tx_buf_ctrl_shift | tx_buf_ctrl_load)
      tx_shift_buf    <= nxt_tx_shift_buf;
  end

⑥数据输出

  // Data output
  assign nxt_txd = (tx_state==4'h2) ? 1'b0 :
                   (tx_state>4'h2) ? tx_shift_buf[0] : 1'b1;

  assign update_reg_txd = (nxt_txd != reg_txd);

  // Registering outputs
  always @(posedge PCLK or negedge PRESETn)
  begin
    if (~PRESETn)
      reg_txd         <= 1'b1;
    else if (update_reg_txd)
      reg_txd         <= nxt_txd;
  end

  // Generate TX overrun error status
  assign tx_overrun = tx_buf_full & (~tx_buf_clear) & write_enable00;

  // Connect to external
  assign TXD  = reg_txd;
  assign TXEN = reg_ctrl[0];

4.8 异步处理

不同时钟域高速转低速可以用打两拍处理

  // Doubling Flip-flop synxt_rx_tick_cntnchroniser
  always @(posedge PCLK or negedge PRESETn)
  begin
    if (~PRESETn)
      begin
      rxd_sync_1 <= 1'b1;
      rxd_sync_2 <= 1'b1;
      end
    else if (reg_ctrl[1]) // Turn off synchronizer if receive is not enabled
      begin
      rxd_sync_1 <= RXD;
      rxd_sync_2 <= rxd_sync_1;
      end
  end

4.9 低通滤波(去毛刺)

 // Averaging low pass filter
  assign nxt_rxd_lpf = {rxd_lpf[1:0], rxd_sync_2};
  // Registering stage for low pass filter
  always @(posedge PCLK or negedge PRESETn)
  begin
    if (~PRESETn)
      rxd_lpf <= 3'b111;
    else if (reg_baud_tick)
      rxd_lpf <= nxt_rxd_lpf;
  end

  // Averaging values
  assign rx_shift_in = (rxd_lpf[1] & rxd_lpf[0]) |
                       (rxd_lpf[1] & rxd_lpf[2]) |
                       (rxd_lpf[0] & rxd_lpf[2]);

4.10 rx传输

①rx计数器

  // Increment TickCounter
  assign nxt_rx_tick_cnt = ((rx_state==4'h0) & (~rx_shift_in)) ? 5'h08 :
                        rx_tick_cnt + {{3{1'b0}},reg_baud_tick};

  assign update_rx_tick_cnt = ((rx_state==4'h0) & (~rx_shift_in)) | reg_baud_tick;

  // Registering other register
  always @(posedge PCLK or negedge PRESETn)
  begin
    if (~PRESETn)
      rx_tick_cnt    <= {4{1'b0}};
    else if (update_rx_tick_cnt)
      rx_tick_cnt    <= nxt_rx_tick_cnt[3:0];
  end

②rx的一些信号:自加状态、buf满信号、读数据信号、读overrun信号

 // Increment state
  assign rx_state_inc   = ((&rx_tick_cnt) & reg_baud_tick);
  // Buffer full status
  assign nxt_rx_buf_full = rxbuf_sample | (rx_buf_full & (~rx_data_read));

  // Sample shift register when D7 is sampled
  assign rxbuf_sample  = ((rx_state==4'h9) & rx_state_inc);

  // Reading receive buffer (Set at 1st cycle of APB transfer
  // because read mux is registered before output)
  assign rx_data_read   = (PSEL & (~PENABLE) & (PADDR[11:2]==10'h000) & (~PWRITE));
  // Generate RX overrun error status
  assign rx_overrun = rx_buf_full & rxbuf_sample & (~rx_data_read);

③rx状态机

0 = Idle
1 = Start of Start bit detected
2 = Sample Start bit
3 = D0

10 = D7
11 = Stop bit
11, 12, 13, 14, 15: illegal/unused states

  always @(rx_state or rx_shift_in or rx_state_inc or reg_ctrl)
  begin
  case (rx_state)
    0: begin
       nxt_rx_state = ((~rx_shift_in) & reg_ctrl[1]) ? 5'h01 : 5'h00;  // Wait for Start bit
       end
    1,                      // State 1  : Wait for middle of start bit
    2,3,4,5,6,7,8,9: begin  // State 2-9: D0 - D7
       nxt_rx_state = rx_state + {3'b000,rx_state_inc};
       end
    10: begin // Stop bit , goto back to Idle
       nxt_rx_state = (rx_state_inc) ? 5'h00 : 5'h0A;
       end
    default:
       nxt_rx_state = {5{1'bx}};
  endcase
  end

  assign rx_state_update = rx_state_inc |  ((~rx_shift_in) & reg_ctrl[1]);

  // Registering rx_state
  always @(posedge PCLK or negedge PRESETn)
  begin
    if (~PRESETn)
      rx_state       <= {4{1'b0}};
    else if (rx_state_update)
      rx_state       <= nxt_rx_state[3:0];
  end

④buff处理

  // Buffer full status
  always @(posedge PCLK or negedge PRESETn)
  begin
    if (~PRESETn)
      rx_buf_full     <= 1'b0;
    else if (rxbuf_sample | rx_data_read)
      rx_buf_full     <= nxt_rx_buf_full;
  end

  // Sample receive buffer
  assign nxt_rx_buf     = {rx_shift_in, rx_shift_buf};
  // Registering receive data buffer
  always @(posedge PCLK or negedge PRESETn)
  begin
    if (~PRESETn)
      reg_rx_buf      <= {8{1'b0}};
    else if  (rxbuf_sample)
      reg_rx_buf      <= nxt_rx_buf;
  end

⑤rx移位

  // Shift register
  assign nxt_rx_shift_buf= {rx_shift_in, rx_shift_buf[6:1]};
  // Registering shift buffer
  always @(posedge PCLK or negedge PRESETn)
  begin
    if (~PRESETn)
      rx_shift_buf    <= {7{1'b0}};
    else if (rx_state_inc)
      rx_shift_buf    <= nxt_rx_shift_buf;
  end

4.11 中断

①中断set信号

  // Set by event
  assign intr_stat_set[1] = reg_ctrl[3] & rxbuf_sample; // A new receive data is sampled
  assign intr_stat_set[0] = reg_ctrl[2] & reg_ctrl[0] & tx_buf_full & tx_buf_clear;
                            // Falling edge of buffer full

②中断清除寄存器

  // Clear by write to IntClear register
  assign intr_stat_clear[1:0] = {2{write_enable0c}} & PWDATA[1:0];

③txrx中断寄存器输出

  // Registering outputs
  always @(posedge PCLK or negedge PRESETn)
  begin
    if (~PRESETn)
      reg_txintr    <= 1'b0;
    else if (intr_stat_set[0] | intr_stat_clear[0])
      reg_txintr    <= intr_stat_set[0];
  end

  always @(posedge PCLK or negedge PRESETn)
  begin
    if (~PRESETn)
      reg_rxintr    <= 1'b0;
    else if (intr_stat_set[1] | intr_stat_clear[1])
      reg_rxintr    <= intr_stat_set[1];
  end

④中断状态intr_state ,并与端口连接

  assign rx_overflow_intr = reg_rx_overrun & reg_ctrl[5];
  assign tx_overflow_intr = reg_tx_overrun & reg_ctrl[4];

  // Interrupt status for read back
  assign intr_state = {rx_overflow_intr, tx_overflow_intr, reg_rxintr, reg_txintr};

  // Connect to external
  assign TXINT    = reg_txintr;
  assign RXINT    = reg_rxintr;
  assign TXOVRINT = tx_overflow_intr;
  assign RXOVRINT = rx_overflow_intr;
  assign UARTINT  = reg_txintr | reg_rxintr | tx_overflow_intr | rx_overflow_intr;
  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2022-06-04 00:04:22  更:2022-06-04 00:04:32 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 1:44:19-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码