• 基于FIFO的串口发送机设计


      选题缘由:前几天在黑金时序篇的陪伴下,对FIFO进行了大致的掌握,今天看特权同学的深入浅玩转FPGA进阶实验五:基于FIFO的串口发送机设计,想自己总该动手练练,总看别人的code也能学到东西,但那终究不是自己的,当自己独自面对时,会冒出不少原本看似没有问题的问题。可喜的是这次竟然没遇到多大困难,一个小时多一点写好代码,解决问题不到十分钟,然后搞定!难道自己水平有所提高了,哈哈!

      本实验RTL图:

      本实验实现如下功能:Data_gene模块每隔1s产生一个递增的8位数(在助手里边以16进制方式显示),然后每隔1s wrreq发送一个高电平,写入FIFO,本实验FIFO采用8 wide,256deepth,但是这个深度似乎是没有作用的,后边再解释。受黑金大大影响,发送模块采用仿顺序写法,并引出了Start_sig和Done_sig,Start_sig和FIFO的empty相连,一旦FIFO不为空,则启动串口发送过程,一旦完成发送则马上使能读FIFO,因此FIFO里边的数据就是进来一个马上发送出去的过程,因此深度在这里是无意义的……再说FIFO,FIFO是用向导生成的,在第一页选了同步读写时钟,第二页选择保留empty输出,第四页选择关闭电路保护,上面说“如不需要,数据溢出以及数据不足将不会被检查,如此以提高系统性能”,不明白的是,如果不检查下溢,怎么会输出empty?目前实验没问题,就先不纠结了。确实有时候很多细节要理清头绪,需要花太多的时间。

      “时序分析”:起始时刻--FIFO为空,empty输出为1,232模块停止,1s时刻在,wrreq赋值为1,Data_out赋值为1,下一个CLk时刻,wrreq赋值为0,但非阻塞赋值的特性使得FIFO写入一个Data_out的值,即1。此时FIFO不再为空,empty为0,232模块开始运行,但由于此刻FIFO没有输出,所以232模块运行但无发送数据,232发送完,Send_done产生一个高电平,读FIFO使能,此刻,FIFO有输出,但empty输出变为1(FIFO空),232模块停止,Q一直保持第一次的输出数据:1。约1s后,数据生成模块产生新的数据2读进FIFO,empty为0,232模块使能,将1发送出去,产生完成信号。。如此往复。也即:232模块发出Send_done后,离下次真正232发送数据的间隔为1s。

      下面给出2个.v文件及顶层的纯组合.v文件(FIFO文件就不给了):

     1 module Data_gene(Clk,Rstn,wrreq,Data_out);
     2 
     3 input Clk,Rstn;
     4 output wrreq;
     5 output [7:0] Data_out;
     6 
     7 parameter T1s=26'd49_999_999;
     8 
     9 reg [25:0] i;
    10 reg [7:0] Data;
    11 reg wrreq;
    12 always@(posedge Clk or negedge Rstn)
    13 if(!Rstn)
    14     begin
    15     Data<=1'b0;
    16     wrreq<=1'b0;
    17     end
    18 else if(i==T1s)
    19     begin
    20     wrreq<=1'b1;
    21     i<=1'b0;
    22     Data<=Data+1'b1;
    23     end
    24 else
    25     begin
    26     i<=i+1'b1;
    27     wrreq<=1'b0;
    28     end
    29     
    30 assign Data_out=Data;
    31 endmodule 
    Data_gene

      刚连接好各模块后进行的第一次实验时,发现串口助手并非接收到的是每隔1s的一个递增的2位16进制数,后来看RTL图,猛然意识到自己在程序中始终赋予wrreq为1,那么FIFO以及发送模块都是在系统Clk的拍子下,不停的读入FIFON多个相同的数,然后在发送模块不停的发送N多个相同的数……果断在一秒时赋予wrreq值为1,其他时刻均为0,问题完美解决!

     1 module rx_232(Clk,Rstn,Data_in,Start_sig,Done_sig,Send_data);
     2 
     3 input Clk,Rstn,Start_sig;
     4 input [7:0] Data_in;
     5 output Done_sig,Send_data;
     6 
     7 reg isDone,Send_out;
     8 
     9 /**********************************************/
    10 parameter Bps_9600=13'd5208;
    11 reg [12:0] count;
    12 always@(posedge Clk or negedge Rstn)
    13 if(!Rstn)
    14     count<=1'b0;
    15 else if(!Start_sig)
    16     if(count==Bps_9600)
    17         count<=1'b0;
    18     else
    19         count<=count+1'b1;
    20 else
    21     count<=1'b0;
    22 /**********************************************/
    23 reg [3:0] i;
    24 
    25 always@(posedge Clk or negedge Rstn)
    26 if(!Rstn)
    27 begin
    28     i<=1'b0;
    29     Send_out<=1'b0;
    30     isDone<=1'b0;
    31 end
    32 else
    33     case(i)
    34         0:if(count==Bps_9600) i<=i+1'b1;//Idle
    35             else Send_out<=1'b1;
    36         1:if(count==Bps_9600) i<=i+1'b1;//Startbit
    37             else Send_out<=1'b0;
    38         2,3,4,5,6,7,8,9:
    39           if(count==Bps_9600) i<=i+1'b1;//Zerobit to Sevenbit
    40             else Send_out<=Data_in[i-2];
    41         
    42         10:if(count==Bps_9600) i<=i+1'b1;//Checkout random
    43             else Send_out<=1'b0;
    44         11:if(count==Bps_9600) i<=i+1'b1;//Stopbit
    45             else Send_out<=1'b1;
    46         12:begin isDone<=1'b1;i<=i+1'b1;end
    47         13:begin isDone<=1'b0;i<=1'b0;end
    48     endcase 
    49     
    50 /**********************************************/
    51 assign Done_sig=isDone;
    52 assign Send_data=Send_out;
    53 
    54 endmodule 
    55 
    56 
    57     
    rx_232

      波特率为9600bps,含有一位校验位。

     1 module FIFO_232(Clk,Rstn,Send_data);
     2 input Clk,Rstn;
     3 output Send_data;
     4 
     5 wire wrreq;
     6 wire [7:0] Data_out;
     7 
     8 Data_gene U1(
     9     .Clk(Clk),
    10     .Data_out(Data_out),
    11     .Rstn(Rstn),
    12     .wrreq(wrreq)
    13 );
    14 
    15 wire Done_sig,Start_sig;
    16 wire [7:0]Data_in;
    17 
    18 FIFO U2(
    19     .clock ( Clk ),
    20     .data ( Data_out ),
    21     .rdreq ( Done_sig ),
    22     .wrreq ( wrreq ),
    23     .empty ( Start_sig ),
    24     .q ( Data_in )
    25 );
    26 
    27 rx_232 U3(
    28 .Clk(Clk),
    29 .Rstn(Rstn),
    30 .Data_in(Data_in),
    31 .Start_sig(Start_sig),
    32 .Done_sig(Done_sig),
    33 .Send_data(Send_data)
    34 );
    35 
    36 endmodule 
    FIFO_232

      这个真的是纯组合模块…… 由于实例化的时候,不是实例化了一个文件,而是涉及多个模块之间的相互连接,那么wire连接线类型在这里边体现的淋漓尽致……

      最后给出串口助手图,下边的tx就像是秒针那样加一……

        

     

     

      这些都是基础的、粗略的、思路简单的…… 要走的路还有很长,离1W小时还有很远,但不放弃,终有一天可达到……

      ↖(^ω^)↗

  • 相关阅读:
    Mysql:FAQ:A.5 Triggers
    Mysql:Where are stored {procedures | functions | triggers} ? (例程)存储过程、函数、触发器,存在哪儿?
    Mysql:5.7:all triggers are 【FOR EACH ROW】
    Mysql:FAQ:A.4 Stored Procedures and Functiions
    ANSI SQL 2003:美国国家标准:SQL-2003:该规范并不是free获取——你得花钱!
    Mysql:可恨又可怜Query Cache特性:已死!莫用!
    Mysql:Innodb Cluster【It's not NDB】:Based On Group Replication
    Android -- 补间动画和属性动画
    Android -- Android广播
    Android -- Android数据存储
  • 原文地址:https://www.cnblogs.com/fkl523/p/3422728.html
Copyright © 2020-2023  润新知