通用异步收发传输器(Universal Asynchronous Receiver/Transmitter),通常称作UATR,是一种串行、异步、全双工的收发器。全双工的UART支持同时双向通信,是嵌入式系统必不可少的debug接口。

什么是全双工?什么是半双工?

全双工:同一时刻,两个设备都在收发数据,比如SPI。注意QSPI是半双工,因为4根线只能同时收或者发。

半双工:两设备间可以收发数据,但只能收完再发或发完再收。

单工:任何时刻只能进行一个方向的通讯,且固定一方为发送设备,一方为接收设备。

串口通信协议

图片

空闲位:不通信时,TX & RX是逻辑“1”状态,表示当前线路无数据传输。

起始位:发送“0”,表示传输开始。

数据位:起始位之后,数据位的个数可以是5、6、7、8等,一般是8bit,采用ASCII码。从最低位开始传送,根据波特率在数据bit稳定的中间位置采样。

奇偶校验位:数据位加上这一位后,使得“1”的位数为偶数,则为偶校验,使得“1”的位数为奇数则为奇校验,以次来校验数据传送的正确性。

比如一个 8 位长的有效数据为:10100101,此时总共有 4 个“ 1”,

为达到奇校验效果,校验位应为“ 1”,即有效数据和校验位中“ 1”的个数为奇数。

为达到偶校验效果,校验位应为“ 0”,即有效数据和校验位中“ 1”的个数为偶数。

注意,UART校验方法有:奇校验(odd)、偶校验(even)、0校验(space)、0校验(mark)、无校验(noparity),为了提高实际带宽,一般可省去校验位,即选择无校验,思考下为什么?

0 校验是不管有效数据是什么,校验位固定为“ 0”。1 校验是校验位固定为“ 1”。

无校验就是数据包中不包含校验位。

停止位:一个字符数据传输的结束标志,可以是1位、1.5位、2位的高电平。停止位不仅表示传输的结束,并且可提供校正时钟同步。停止位的位数越多,时钟容忍程度越大,但有效带宽就越小。

波特率

数据传输速率使用波特率来表示。单位bps(bits per second),常见的波特率9600bps、19200bps、115200bps等,如果串口波特率设置为9600bps,那么传输1bit数据需要的时间是1/9600≈104.2us。

带上校验位,传送一个字符数据实际是11个比特(1bit开始位、8bit数据位、1bit校验位、1bit停止位),有效的传输速率实际为9600*8/11= 6982bps。

不带校验位,传送一个字符数据实际是10个比特(1bit开始位、8bit数据位、1bit停止位),有效的传输速率实际为9600*8/10=7680bps。

这就是为何不传校验位,可以提高一点带宽,也就是所谓的开销。

串口Verilog代码

UART 通常是指通用异步串行收发传输器( Universal Asynchronous Receiver/Transmitter)。UART 是一种通用的数据通信总线,也是串行总线接口的总称。我们通常所说的 UART 只有两根信号线,一根是发送数据端口线(TX),一根是接收数据端口线(RX)。

发送数据:发送设备将数据转换成串行数据来传输(并转串)。

接收数据:接收设备将接收到的串行数据转换成并行数据(串转并)。

1)协议层:通信协议(包括数据格式,传输速率等);

2)物理层:接口类型,电平标准等。

图片

一帧数据由4 部分组成,

• 起始位(1bit)

• 数据位(6\7\8 bit)

• 奇偶校验位(1bit)

• 停止位(1bit\1.5bit\2bit)

数据帧格式:

图片

空闲位:

UART协议规定,当总线处于空闲状态时信号线的状态为‘1’即高电平,表示当前线路上没有数据传输。

起始位:

每开始一次通信时发送方先发出一个逻辑”0”的信号(低电平),表示传输字符的开始。因为总线空闲时为高电平所以开始一次通信时先发送一个明显区别于空闲状态的信号即低电平。

数据位:

起始位之后就是我们所要传输的数据,数据位可以是5、6、7、8,9位等,构成一个字符(一般都是8位)。如ASCII码(7位),扩展BCD码(8位)。先发送最低位,最后发送最高位,使用低电平表示‘0’高电平表示‘1’完成数据位的传输。

奇偶校验位:

数据位加上这一位后,使得“1”的位数应为偶数(偶校验)或奇数(奇校验),以此来校验数据传送的正确性。校验位其实是调整个数,以下是奇偶校验两种方式:

奇校验(odd parity):如果数据位中“1”的数目是偶数,则校验位为“1”,如果“1”的数目是奇数,校验位为“0”。

偶校验(even parity):如果数据为中“1”的数目是偶数,则校验位为“0”,如果为奇数,校验位为“1”。

在代码设计中我们采用一位异或,将每两位相邻数据位异或后得到一位数据,再根据设置的奇校验偶校验来判断校验位的值。

停止位:

它是一个字符数据的结束标志。可以是1位、1.5位、2位的高电平。

串口发送:

图片


moduletx_bps_module(CLK,RSTn,Count_Sig,BPS_CLK);inputCLK;inputRSTn;inputCount_Sig;outputBPS_CLK;/***************************/reg[12:0]Count_BPS;always@ ( posedge CLK or negedge RSTn )if(!RSTn )Count_BPS<= 13'd0;elseif( Count_BPS == 13'd5207 )Count_BPS<= 13'd0;elseif( Count_Sig )Count_BPS<= Count_BPS + 1'b1;elseCount_BPS<= 13'd0;/********************************/assignBPS_CLK = ( Count_BPS == 13'd2604 ) ? 1'b1 : 1'b0;/*********************************/endmodule
moduletx_control_module(    CLK, RSTn,     TX_En_Sig, TX_Data, BPS_CLK,    TX_Done_Sig, TX_Pin_Out);    input CLK;     input RSTn;     input TX_En_Sig;     input [7:0]TX_Data;     input BPS_CLK;     output TX_Done_Sig;     output TX_Pin_Out;/********************************************************/     reg [3:0]i;     reg rTX;     reg isDone;     always @ ( posedge CLK or negedge RSTn )if( !RSTn )begin                  i <= 4'd0;                     rTX <= 1'b1;                     isDone     <= 1'b0;                end                          else if( TX_En_Sig )              case ( i )                   4'd0 :if( BPS_CLK ) begin i <= i + 1'b1; rTX <= 1'b0; end4'd1, 4'd2, 4'd3, 4'd4, 4'd5, 4'd6, 4'd7, 4'd8 :if( BPS_CLK ) begin i <= i + 1'b1; rTX <= TX_Data[ i - 1 ]; end                     4'd9 :if( BPS_CLK ) begin i <= i + 1'b1; rTX <= 1'b1; end4'd10 :                     if( BPS_CLK ) begin i <= i + 1'b1; rTX <= 1'b1; end                                 4'd11 :if( BPS_CLK ) begin i <= i + 1'b1; isDone <= 1'b1; end4'd12 :                     begin i <= 4'd0; isDone <= 1'b0; end                            endcase                    /********************************************************/                                     assign TX_Pin_Out = rTX;     assign TX_Done_Sig = isDone;     /*********************************************************/                            endmodule

moduletx_module(    CLK, RSTn,     TX_Data, TX_En_Sig,     TX_Done_Sig, TX_Pin_Out);     input CLK;      input RSTn;      input [7:0]TX_Data;      input TX_En_Sig;      output TX_Done_Sig;      output TX_Pin_Out;/********************************/      wire BPS_CLK;tx_bps_module U1(          .CLK( CLK ),            .RSTn( RSTn ),            .Count_Sig( TX_En_Sig ),    // input - from U2            .BPS_CLK( BPS_CLK )         // output - to U2      );/*********************************/tx_control_module U2(          .CLK( CLK ),            .RSTn( RSTn ),            .TX_En_Sig( TX_En_Sig ),    // input - from top            .TX_Data( TX_Data ),        // input - from top            .BPS_CLK( BPS_CLK ),        // input - from U2            .TX_Done_Sig( TX_Done_Sig ),  // output - to top            .TX_Pin_Out( TX_Pin_Out )     // output - to top      );/***********************************/endmodule

串口接收

图片

图片

    moduledetect_module(CLK,RSTn,RX_Pin_In,H2L_Sig);inputCLK;inputRSTn;inputRX_Pin_In;outputH2L_Sig;/******************************/regH2L_F1;regH2L_F2;always@ ( posedge CLK or negedge RSTn )if(!RSTn )beginH2L_F1<= 1'b1;H2L_F2<= 1'b1;endelsebeginH2L_F1<= RX_Pin_In;H2L_F2<= H2L_F1;end/***************************************/assignH2L_Sig = H2L_F2 & !H2L_F1;/***************************************/endmodule

    modulerx_control_module(CLK,RSTn,H2L_Sig,RX_Pin_In, BPS_CLK, RX_En_Sig,Count_Sig,RX_Data, RX_Done_Sig);inputCLK;inputRSTn;inputH2L_Sig;inputRX_En_Sig;inputRX_Pin_In;inputBPS_CLK;outputCount_Sig;output[7:0]RX_Data;outputRX_Done_Sig;/********************************************************/reg[3:0]i;reg[7:0]rData;regisCount;regisDone;always@ ( posedge CLK or negedge RSTn )if(!RSTn )begini<= 4'd0;rData<= 8'd0;isCount<= 1'b0;isDone<= 1'b0;endelseif( RX_En_Sig )case( i )4'd0 :if(H2L_Sig ) begin i <= i + 1'b1; isCount <= 1'b1; end         /*进入第0位,同时驱动bps_module开始计数。又以bps_module驱动状态1~11*/4'd1 :if(BPS_CLK ) begin i <= i + 1'b1; end                          /*第0位中部,BPS_CLK发出第一个脉冲,忽略第0位*/4'd2,4'd3, 4'd4, 4'd5, 4'd6, 4'd7, 4'd8, 4'd9 :if(BPS_CLK ) begin i <= i + 1'b1; rData[ i - 2 ] <= RX_Pin_In; end4'd10 :if(BPS_CLK ) begin i <= i + 1'b1; end4'd11 :if(BPS_CLK ) begin i <= i + 1'b1; end4'd12 :begini <= i + 1'b1; isDone <= 1'b1; isCount <= 1'b0; end4'd13 :begini <= 4'd0; isDone <= 1'b0; end    endcase/********************************************************/assignCount_Sig = isCount;assignRX_Data = rData;assignRX_Done_Sig = isDone;/*********************************************************/endmodule​​​​​​​
    modulerx_bps_module(CLK,RSTn,Count_Sig,BPS_CLK);inputCLK;inputRSTn;inputCount_Sig;outputBPS_CLK;/***************************/reg[12:0]Count_BPS;always@ ( posedge CLK or negedge RSTn )if(!RSTn )Count_BPS<= 13'd0;elseif( Count_BPS == 13'd5207 )Count_BPS<= 13'd0;elseif( Count_Sig )Count_BPS<= Count_BPS + 1'b1;elseCount_BPS<= 13'd0;/********************************/assignBPS_CLK = ( Count_BPS == 12'd2604 ) ? 1'b1 : 1'b0;            /*周期中间开始采集数据*//*********************************/endmodule
    modulerx_module(    CLK, RSTn,    RX_Pin_In, RX_En_Sig,     RX_Done_Sig, RX_Data);    input CLK;     input RSTn;     input RX_Pin_In;     input RX_En_Sig;     output [7:0]RX_Data;     output RX_Done_Sig;/**********************************/     wire H2L_Sig;detect_module U1(         .CLK( CLK ),          .RSTn( RSTn ),          .RX_Pin_In( RX_Pin_In ),    // input - from top          .H2L_Sig( H2L_Sig )         // output - to U3     );/**********************************/     wire BPS_CLK;rx_bps_module U2(         .CLK( CLK ),          .RSTn( RSTn ),          .Count_Sig( Count_Sig ),   // input - from U3          .BPS_CLK( BPS_CLK )        // output - to U3     );/**********************************/     wire Count_Sig;rx_control_module U3(         .CLK( CLK ),          .RSTn( RSTn ),          .H2L_Sig( H2L_Sig ),      // input - from U1          .RX_En_Sig( RX_En_Sig ),  // input - from top          .RX_Pin_In( RX_Pin_In ),  // input - from top          .BPS_CLK( BPS_CLK ),      // input - from U2          .Count_Sig( Count_Sig ),    // output - to U2          .RX_Data( RX_Data ),        // output - to top          .RX_Done_Sig( RX_Done_Sig ) // output - to top     );/************************************/endmodule

    通常调试或编程MCU时,数据首先被封装为 USB 数据包。然后,PC 通过 USB 接口将这些数据包发送到桥接器。桥接器将 USB 数据包分解为 UART 数据,UART 数据作为异步流到达MCU,然后根据应用程序进行处理。但是注意,USB通常比UART快得多,需要FIFO缓冲区来弥补差异并避免数据丢失。然后,桥接器必须正确配置波特率满足MCU的通信需求,。

    MCU还可以通过相同的 USB/UART 桥接器向另一个方向发送数据,从而对 PC 做出响应。然后,桥接器会将这些 UART 数据转换回 USB 数据包,然后再将其传输到 PC。USB 和 UART 之间的转换可能会引入时序或流程错误。FTDI 或 CP210x 等组件具有内置错误处理机制,可确保可靠的通信。具体通信过程如下:

    图片

    01

    SoC设计实战课背景

    景芯团队专家老师1v1辅导、终身辅导,通过景芯HD6850项目实战让您快速超越同龄人!我们本着对学员负责任的态度,提供终身辅导,也希望学员成为各个公司的中流砥柱后,给景芯团队介绍design servie业务,共同进步!

    景芯训练营主打文档+服务器实战,我们不卖视频,只提供免费导学视频!和学员终身绑定是景芯训练营+design service的核心。我们选取景芯HD6850项目中的橙色域子系统(下图橙色部分)进行全流程实战培训,实战内容包括设计、验证、中端、后端全流程。

    图片

    橙色子系统采用Cortex-M0+RISC-V双核异构架构,全部自研实现了AXI总线、AHB总线、ISP-Lite、NPU-lite、MIPI DPHY软核、SRAM、DMA、UART、I2C、QSPI/SPI等常用IP,项目架构图如下:

    图片

    景芯橙色域子系统分为三个subchip子系统,包括media_wrapper、amba_wrapper、cpu_wrapper三个subchip,每个subchip的功能简要描述如下:

    1. media wrapper负责MIPI图像输入、DPV图像输入、异步处理、ISP图像处理。

    2. amba wrapper负责接收media wrapper传递过来的经过ISP预处理过的图像,通过专用DMA搬运数据到amba wrapper系统主存SRAM,DMA搬运完成后,CPU配置NPU搬运系统主存SRAM的图像数据去做矩阵运算(卷积)。

    3. cpu wrapper负责RISC-V CPU、TCM、自研AXI总线矩阵的译码、仲裁、AXI2AHB总线桥、中断系统、低功耗PMU管理等功能。NPU卷积完成后,RISC-V CPU执行WFI指令进入休眠模式。通过isolate信号和retain信号进行时钟门控、电源门控。

    为了满足不同经验的学员需求,景芯团队设计老师开发了两套环境分别作为进阶课和基础课,带您一起手搓AXI总线、AHB总线、ISP-Lite、NPU-lite、MIPI DPHY软核、SRAM、DMA、UART、I2C、QSPI/SPI等常用IP,让您快速掌握架构、总线协议、接口协议、图像算法、软硬件协同验证等设计核心,让您快速超越同龄人!

    02

    设计实战基础课目录

    Part.01

    设计实战基础课  

    终身辅导、一对一辅导是景芯SoC全流程训练营的特色!景芯SoC设计实战基础课最新课表如下:

    Part.02

    设计实战进阶课 

    景芯SoC设计实战进阶课最新课表如下(买进阶课、送基础课)

    景芯SoC芯片全流程实战附属【知识星球】,一个包括设计、验证、DFT、后端全流程技术的交流平台,也是景芯学员的答疑平台!若您和我一样渴求技术,那欢迎扫下面二维码加入星球,共同进步!

    图片

    Part.06

    课程报名微信,扫描咨询我们吧

    图片

    03

     景芯团队Design Service提供哪些服务?

    景芯主营业务是design service+一对一芯片终身辅导培训!景芯团队将持续打磨芯片全流程技术,边缘AI时代,景芯团队一定成!景芯团队提供的芯片Design Service设计服务包括:

    • 提供SoC、MCU、ISP、CIS等芯片设计、验证、DFT、后端服务

    • 提供DDR/PCIE/MIPI/ISP/NPU/VPU/CAN/USB/ETH等复杂IP设计

    • 提供7nm、12nm、28nm、40nm、55nm、65nm、90nm等后端设计

    • 提供高校、企业定制化芯片设计服务、设计培训业务

    • 景芯团队为客户定制了数款A55、A7系列SoC芯片,皆一版成功!

    • 景芯团队为客户定制了数款M7、M3/4、M0系列MCU芯片!

    • 景芯团队为客户定制了数款RISC-V系列MCU芯片!

    • 景芯团队为客户定制了数款CIS芯片以及ISP模块化设计!

    景芯SoC芯片全流程实战附属【知识星球】,一个包括设计、验证、DFT、后端全流程技术的交流平台,也是景芯学员的答疑平台!若您和我一样渴求技术,那欢迎扫下面二维码加入星球,共同进步!

    图片

    04

    景芯SoC训练营项目有什么亮点?

    亮点1:景芯SoC自研MIPI解码

    数字电路中经典设计:多条通信数据Lane Merging设计实现

    数字电路中经典设计:多条通信数据Lane Distribution实现

    亮点2: 景芯SoC自研ISP图像处理

       

    dpc - 坏点校正

    blc - 黑电平校正 

    bnr - 拜耳降噪

    dgain - 数字增益 

    demosaic - 去马赛克

    wb - 白平衡增益 

    ccm - 色彩校正矩阵 

    csc - 色彩空间转换 (基于整数优化的RGB2YUV转换公式)

    gamma - Gamma校正 (对亮度基于查表的Gamma校正)

    ee - 边缘增强

    stat_ae - 自动曝光统计 

    stat_awb - 自动白平衡统计

    【景芯SoC学员ISP算法实现的作品】:

    亮点3:景芯SoC自研NPU

    支持手写数字的AI识别:

    仿真结果:仿真识别上图7、2、1、0、4、1、4、9

    亮点4:景芯SoC UPF低功耗设计

    全芯片UPF低功耗设计(含DFT设计)

    景芯SoC训练营培训项目,低功耗设计前,功耗为27.9mW。

    低功耗设计后,功耗为0.285mW,功耗降低98.9%!

    电压降检查:

    低功耗检查:

    低功耗设计的DRC/LVS,芯片顶层的LVS实践价值极高,具有挑战性!业界独一无二的经验分享。

    06

    景芯SoC训练营好评如潮

    十分感谢景芯学员们对景芯的信任和支持,景芯团队一定更努力精心打磨景芯SoC实战课,让大家无论资深还是资浅都能从景芯训练营获得成长!

    最近学员纷纷咨询小编offer选择的问题,看到大家通过景芯培训提升后拿到心仪的offer了,非常开心,祝贺大家都拿到心仪offer了!

    另外,小编的一个景芯VIP学员,成都某985,硕士7年经验,之前通过景芯培训提升后拿到心仪的offer了,这3个offer我看了都眼红!上次发起了投票,今天公布下结果。先来看下三个offer情况:

    1、 某GPU公司,月薪5.8w,年终4个月合计23.2万,年薪92.8万,岗位是SoC前端设计,公积金12%;

    2、多媒体SOC厂商JC,月薪6.5w,年终奖2个月合计13万,年薪91万,岗位是SoC芯片设计工程师,公积金12%;

    3、 国企X微电子,月薪5.5W,年终奖4个月合计22万,年薪88万,担任数字ic设计工程师,主要从事SOC芯片设计,公积金10%

    这里补充发布上次大家的投票结果公布:

    从结果可以看出,市场行情不好,大家都看好国企军工的稳定性了,GPU仍然是技术首选,虽然GPU公司都在厮杀,但是仍有前景,但是IPC SOC反而得票最低,内卷同时没有太大增量市场。

    另外,景芯资深老学员告诉我,留学X国的硕士去外企某芯片巨头薪资是20万+美金!折合RMB超过140万,才25岁左右的小伙子!薪资超140万!努力学习技术吧 骚年。

    课程报名微信:

    Logo

    DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

    更多推荐