微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 嵌入式设计讨论 > FPGA,CPLD和ASIC > 之四:UART接收器模块设计

之四:UART接收器模块设计

时间:10-02 整理:3721RD 点击:
很遗憾很遗憾,中间放了个暑假时间拖到了试用期结束,这篇之后马上到小处理器。
一、UART接收器
写了三四遍的verilog代码,总是觉得有种必须得写成状态机形式的感觉。写了几遍加上sigaltap都调不好,最后无奈画出了一个方框图,按照图才出了一个有效的uart接收器代码。之所以要写一个接收器,是因为如果要对一个MCU编程的话,通过uart串口很简便。框图如下。


二、图中的异步复位触发器
异步复位触发器的写法一般是:
always@(posedge clk or negedge rst)
begin
if(~rst) q<=0;
else q<=d;
end
这个看起来很像是边沿触发来复位:加入rst一直为低,q并不会被复位成0.但是实际上由于上电时D触发器的输出一般是低电平,所以rst一直为低的情况也可以认为是电平复位;而如果复位将q变成1,这就不是一个正确的电平异步复位了:上电开始时,rst为0,q也为0,不满足复位条件。
三、框图含义
由于uart的协议是先发一个起始位,然后发送8位数据。在9600波特率的要求下,使用FPGA的时钟源325分频出16倍于9600bit/s的时钟送入到uart模块中。
首先是边沿检测,图中电路保证一个下降沿来临之后,其余电路开始工作,即开始记录比特位;同时将这个边沿检测电路的输入屏蔽掉。
在计数到8位有效位都读出之后,counter输出变为0,将边沿检测部分复位,counter失去时钟源。另外,counter输出的0经过两个延时之后将自己复位,输出重新变为1,这个负脉冲经过反相器即可作为对外部的通知信号:来读取串口数据吧。
四、verilog源代码
module newart(
        input dat,
        input clk,
        output ex0,
        output reg [7:0]bufout);
       
        reg ck;
        reg [7:0]buftmp;
        reg [7:0]count;
        reg enout;
        reg enout2;
        reg enout3;
        wire ck1;
        wire rst0;
        reg rst1;
        reg [8:0]count1;//325 freq divide;
        reg [7:0]count2;//180 times,make the ck high;
        wire dat0;
       
        assign rst0=enout2;
       
        always@(posedge clk)
        begin
                count1<=count1+1;
                count2<=count2+1;
                if(count1==0)begin
                        ck<=0;
                        count2<=0;
                        end
                else begin
                        if(count1==324) count1<=0;
                        if(count2==180) begin ck<=1;count2<=0;end
                        end
        end
       
        always@(negedge rst0 or negedge dat0)//it seems that it is a edge detect,however it is a level driven.
        begin
                if(~rst0)enout<=0;
                else enout<=1;
        end
       
        assign ck1=ck&enout;
        assign dat0=enout|dat;
       
        always@(posedge ck1 or negedge rst1)
        begin
                if(~rst1)begin enout2<=1;count<=0;end
                else begin
                                count<=count+1;
                                case(count)
                                24:buftmp[0]<=dat;
                                40:buftmp[1]<=dat;
                                56:buftmp[2]<=dat;
                                72:buftmp[3]<=dat;
                                88:buftmp[4]<=dat;
                                104:buftmp[5]<=dat;
                                120:buftmp[6]<=dat;
                                136:buftmp[7]<=dat;//the above get 8 bit;
                                152:begin enout2<=0;bufout<=buftmp;end
                                endcase
                        end
        end
       
        always@(posedge ck)
        begin
                enout3<=enout2;
                rst1<=enout3;
        end
       
        assign ex0=~rst1;
       
        endmodule
将上述代码作为一个模块嵌入到下面的代码中:
//this uart only can receive info from master,used as uart program!
//this test module detects A,B,C,D,E;
module comuart(
        input clk,
        input dat,
        output reg led1,
        output reg led2,
        output reg led3,
        output reg led4,
        output reg led5,
        output led6
);
wire ex0;
wire [7:0]bufout;
newart u1(dat,clk,ex0,bufout);
//how does the sub module attach to top module?
//the sub module must be connected to a wire.
always@(posedge ex0)
begin
        case(bufout)
        65:begin led1<=0;
                         led2<=1;
                         led3<=1;
                         led4<=1;
                         led5<=1;
                end
       
        66:begin led1<=1;
                         led2<=0;
                         led3<=1;
                         led4<=1;
                         led5<=1;
                end
       
        67:begin led1<=1;
                         led2<=1;
                         led3<=0;
                         led4<=1;
                         led5<=1;
                end
               
        68:begin led1<=1;
                         led2<=1;
                         led3<=1;
                         led4<=0;
                         led5<=1;
                end
               
        69:begin led1<=1;
                         led2<=1;
                         led3<=1;
                         led4<=1;
                         led5<=0;
                end
        default:begin led1<=1;
                         led2<=1;
                         led3<=1;
                         led4<=1;
                         led5<=1;
                end
        endcase
end

assign led6=dat;//led6 is tested alone for the uartin.
endmodule
五、结果及最后的工作
结果见下述小视频:
http://v.youku.com/v_show/id_XMzA0NzE1MzU4NA==.html?spm=a2hzp.8253869.0.0
通过串口发送A/B/C/D/E,会点亮对应的灯。如果应用于准备写的超低端处理器中,就是一条一条的指令了。
最后,再次对没有按时完成计划表示道歉。

不错的资料分享     

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top