Written on the front of the words
Serial / parallel to serial conversion is an important skill FPGA design process, is often used in high-speed data stream processing, especially important aspects of the communication interface. The UART serial protocol , the SPI serial port protocol, IIC serial protocols need to use serial / parallel to serial conversion. In this section, we dream wing brothers and learn together serial implementation / parallel-serial conversion.
demand analysis
And forwarding string design is as follows: First prepare a set of registers, the data (parallel data) needs to be sent into the register set inside, and then by splicing the shift mode bit parallel data to one bit of this sent to the receiver, while pulled flag signal en, when after completion of all the data transmitted in the flag signal en down.
Top frame design
Top-level module port description
Port Name |
Port Description |
clk |
50MHz system clock input |
rst_n |
System Reset Low |
in |
Data conversion flag signal |
sda |
Serial data output |
Code
/**************************************************** * Engineer: Dream Brother Wing * QQ : 761664056 * The module function: and -serial module *****************************************************/ 01 module para_serial( 02 // system input CLK 03 , // 50M system clock input Rst_n 04 , // system reset 05 // system output Sda 06 , // serial data bus 07 en // data conversion flag signal 08 ); 09 // ------------- system input -------------- 10 INPUT CLK ; // 50M system clock input . 11 INPUT RST_N ; // reset 12 // ------------- system output -------------- 13 is Output REG SDA ; // serial data bus 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是完全相同的,说明我们的设计是正确的。