基础项目(7)串行转并行程序设计及讲解

写在前面的话

串并/并串转换是FPGA设计过程中的一个重要技巧,经常被用在高速数据流处理中,特别是在通信接口方面尤为重要。如UART串口协议SPI串口协议、IIC串口协议都需要用到串并/并串转换。本节,梦翼师兄和大家一起来学习串并/并串转换的实现方法。

需求分析

并转串的设计思想是这样的:首先准备好一组寄存器,把需要发送的数据(并行数据)放到这个寄存器组里面,然后通过位拼接的移位方式把这个并行数据一位一位地发送给接收端,同时拉高标志信号en,当全部数据发送完之后,在把标志信号en拉低。

顶层框架设计

 

 

顶层模块端口介绍

端口名

端口说明

clk

系统50MHz时钟输入

rst_n

系统低电平复位

en

数据转换标志信号

sda

输出的串行数据

代码实现

/****************************************************          

 *   Engineer      :   梦翼师兄

 *   QQ             :   761664056

 *   The module function : 转串模块

*****************************************************/

01  module para_serial(

02              //系统输入

03              clk,    //50M系统时钟输入

04              rst_n,  //系统复位

05              //系统输出

06              sda,    //串行数据总线

07              en      //数据转换标志信号

08            );

09  //-------------系统输入--------------

10  input clk;  //50M系统时钟输入

11  input rst_n;//系统复位

12  //-------------系统输出--------------

13  output reg sda; //串行数据总线

14  output reg en;  //数据转换标志信号

15  //------------寄存器定义-------------

16  reg [7:0]sda_buf;   //并行数据寄存器

17  reg [3:0]counter;   //移位计数器

18  //-----------并串转换逻辑------------

19  always@(posedge clk or negedge rst_n)

20      begin

21          if(!rst_n)

22              begin

23                  sda<=0; //串行数据总线赋初值

24                  sda_buf<=8'b1001_1101; //并行数据寄存器赋初值

25                  counter<=0; //移位计数器赋初值

26                  en<=0; //数据转换标志信号赋初值

27              end

28          else

29              begin

30                  if(counter<8)//控制移位次数

31                      begin

32                          en<=1;  //转换使能打开

33                          counter<=counter+1'b1;

                            //通过位拼接方式实现并串转换

34                          sda_buf<={sda_buf[6:0],sda_buf[7]}; 

35                          sda<=sda_buf[7]; //sda_buf一位位的发送出去

36                      end

37                  else

38                      begin

39                          counter<=0;//移位结束,计数器清零

40                          sda<=0;

41                          en<=0;     //转换完成

42                      end

43              end 

44      end 

45      

46  endmodule

代码分析我们首先定义了一个8数据寄存器sda_buf和一个控制移位的计数器counter,然后在电路复位的时候给sda_buf写入了一个8的并行数据8’b1001_1101;第30~35行,我们拉高数据转换标志信号en,把并行数据sda_buf的最高位输出到sda同时sda_buf进行左移操作,sda_buf中的数据就会以串行的方一位一位的发送出去39~41移位结束同时,计数器清零,数据转换标志信号en变为低电平,完成了一次数据并行数据的转换

编写的测试代码如下:

/****************************************************          

 *   Engineer      :   梦翼师兄

 *   QQ             :   761664056

 *   The module function : 转串测试模块

*****************************************************/

01  `timescale 1ns/1ps 

02  module tb;

03

04  //------------被测试模块输入------------

05  reg clk;    //50M系统时钟输入

06  reg rst_n;  //系统复位

07  //------------被测试模块输出-------------

08  wire sda;  //串行数据总线

09  wire en;   //数据转换标志信号

10  //------------设置测试激励---------------

11  initial

12      begin

13          clk=0;

14          rst_n=0;

15          # 1000.1 rst_n=1;

16      end 

17      

18  always #10 clk=~clk; //周期为20ns的时钟

19

20  //-------------模块实例化----------------

21  para_serial para_serial  (

22              .clk(clk),

23              .rst_n(rst_n),

24              .sda(sda),

25              .en(en)

26            );

27  endmodule

仿真波形如下所示:

观察波形可以看到当数据转换标志信号en为高电平的时候,sda_buf中的数据从最高位开始输出,也就是sda开始输出串行数据,当sda_buf的全部数据输出后的同时,数据转换标志信号en变为低电平。

接下来,我们来学习串行数据转换成并行数据的设计实现技巧,由于我们已经有一个并转串的模块来输出串行数据,所以我们可以巧妙的利用这个模块。

我们在测试代码中加入一个串行数据转换成并行数据的模块,它部件架构图如下(下面测试代码第24~41行):

修改后的测试代码如下:

 

/****************************************************          

 *   Engineer      :   梦翼师兄

 *   QQ             :   761664056

 *   The module function :转并测试模块

*****************************************************/

01  `timescale 1ns/1ns 

02  module tb;

03

04  //------------被测试模块输入------------

05  reg clk;    //50M系统时钟输入

06  reg rst_n;  //系统复位

07  //------------被测试模块输出-------------

08  wire sda;  //串行数据总线

09  wire en;   //数据转换标志信号

10  //------------设置测试激励---------------

11  initial

12      begin

13          clk=0;

14          rst_n=0;

15          # 1000 rst_n=1;

16      end 

17      

18  always #10 clk=~clk; //周期为20ns的时钟

19

20  //------------串并转换模块---------------

21  reg [7:0]sda_reg;   //串行数据接收寄存器

22  wire en;

23

24  always@(posedge clk or negedge rst_n)

25      begin

26          if(!rst_n)

27              begin

28                  sda_reg<=0;

29              end

30          else

31              begin

32                  if(en)    //检测到数据转换标志信号为高电平

33                      begin //将输入的串行数据sda转换为并行数据sda_reg

34                          sda_reg<={sda_reg[6:0],sda}; 

35                      end 

36                  else    //检测到en为低电平,不采取任何操作

37                      begin

38                          sda_reg<=0;

39                      end 

40              end 

41      end

42  //-------------模块实例化----------

43  para_serial para_serial  (

44              .clk(clk),

45              .rst_n(rst_n),

46              .sda(sda),

47              .en(en)

48            );

49  endmodule

 

代码分析:我们首先定义了一个串行数据接收寄存sda_reg,检测数据转换标志信号en有效时,sda_reg通过位拼接的方式依次将并转串模块输出的串行数据sda移入到sda_reg的每一位(从低位到高位),从而实现串行数据向并行数据的转换。

 

仿真波形如下所示:

 

 

 

观察波形可以看到当数据转换标志信号en为高电平的时候,sda_reg开始串行数据sda当数据转换标志信号en为低电平的时数据向并行数据的转换刚好结束,我们可以出转换得到的并行数据sda_reg和发送的并行数据sda_buf是完全相同的,说明我们设计是正确的。

 

posted @ 2019-09-15 07:34  梦翼师兄  阅读(2207)  评论(0编辑  收藏  举报