用Verilog实现串并和并串转换

1,125 阅读2分钟

用Verilog实现串并和并串转换

  1. 首先我们先了解并串和串并转换的原理

串行数据输出是将组成数据和字符的码元按时序逐位予以传输,并行数据传输是将固定位数(通常为8位或16位等)的数据和字符码元同时传输至接收端,串并转换是完成这两种传输方式之间转换的技术。

例如:需要传输的数据有32bit,用串行传输则需要32个时钟周期完成传输,如果用8位并行传输,则32bit数据只需要4个时钟周期就可以完成传输。

并串转换:
并转串电路主要由时钟(clk)、复位信号(rst)、并行输入信号(pdin)、串行输出信号(sdout)和使能信号(en)组成。使能信号表示开始执行并转串操作,由于并转串是移位操作,先将八位数据暂存于一个八位寄存器器中,然后左移输出到一位输出端口,通过一个“移位”来实现,当一次并转串完成后,需要重新载入待转换的并行数据时,使能信号要再起来一次。

串并转换:
新输入的位值成为原来数据的最低位,将原来数据的最高位舍去,这里可以通过一个简单的“连接符”来实现。

  1. 转换可以采用两种方式实现
    一:lsb优先 Least Significant Bit,最低比特,最低位优先
    二:msb优先 Most Significant Bit,最高比特,最高位优先

通过位拼接运算符来进行高位舍去,实现左移

module Deserialize(
    input           clk,
    input           rst_n,
    input         data_i,
    output   reg [7:0] data_o
    );

//lsb first

always @(posedge clk or negedge rst_n)begin
    if(rst_n == 1'b0)begin
        data_o <= 8'b0;
    end
    else begin
        data_o <= {data_o[6:0], data_i}; //去掉了高位,让data_i来代替高位,相当于左移一位
    end
end
endmodule

补充: 截取数据的不同位数进行拼接:

 例:    data1 = 0101_1101
         data2 = 1011_0011
         data = {data1[3:0],data2[7:4]}
        则可得:data = 1101_1011

testbench仿真

`timescale 1ns/1ns
`define clock_period 20

module Deserialize_tb;
   reg clk;
	reg rst_n;
	reg data_i;
	
wire [7:0] data_o;


Deserialize  Deserialize_0(
  .clk(clk),
  .rst_n(rst_n),
  .data_i(data_i),
  .data_o(data_o)
  );

  initial clk = 1;
  
  always #(`clock_period/2) clk = ~clk;
  
  
  initial begin
	   rst_n=0;
		data_i=0;
	
 #(`clock_period*200)
   rst_n=1;
 #(`clock_period*200)
  data_i=1;
  #(`clock_period*200)
   data_i=0;
  # (`clock_period*200)
  data_i=1;
  # (`clock_period*200)
  data_i=0;
  # (`clock_period*200)
  data_i=1;
  # (`clock_period*200)
  data_i=0;
  # (`clock_period*200)
  data_i=1;
  # (`clock_period*200)
  data_i=0;
  # (`clock_period*200)
  data_i=1;
  # (`clock_period*200)
  data_i = 0;
  # (`clock_period*200)
  data_i = 0;
  # (`clock_period*200)
  data_i = 0;
  # (`clock_period*200)
  data_i = 1;
  # (`clock_period*200)
  data_i = 1;
  # (`clock_period*200)
  data_i = 1;
  # (`clock_period*200)
  data_i = 0;
  # (`clock_period*200)
  $stop;
  end
  
  endmodule 

波形图
在这里插入图片描述
分析:每当clk上升沿且rst_n=1时变化,开始时data_i=0,此时data_o=0000_0000,当data_i=1时,则 data_o <= {data_o[6:0], data_i};data_o=0000_0001,实现了高位舍弃,低位用data_i作为新输入的数据来成为data_o的最低位。

在这里插入图片描述


msb优先

  //msb first
module Deserialize(
    input           clk,
    input           rst_n,
    input         data_i,
    output   reg [7:0] data_o
    );

	  reg  [2:0] cnt;
  
  always @(posedge clk or negedge rst_n)begin
	 if(rst_n == 1'b0)begin
		 data_o <= 8'b0;
		  cnt <= 3'd0;   //三位十进制
	end
	 else if(cnt == 3'b111) 
	    cnt <= 3'd0;
	else begin
		  data_o[7 - cnt] <= data_i;   //用计数来进行7-0的移位操作  
		  cnt <= cnt + 1'b1;
	 end
end

endmodule

testbench仿真

`timescale 1ns/1ns
`define clock_period 20

module Deserialize_tb;
   reg clk;
	reg rst_n;
	reg data_i;
	reg [2:0] cnt;
	
	wire [7:0] data_o;


Deserialize  Deserialize_0(
  .clk(clk),
  .rst_n(rst_n),
  .data_i(data_i),
  .data_o(data_o)
  );
  
  
  
  initial clk = 1;
  
  always #(`clock_period/2) clk = ~clk;
  
   always @(posedge clk or negedge rst_n)begin
	  if(rst_n == 1'b0)
			  cnt <= 3'd0;   //三位十进制
	
		 else if(cnt == 3'b111) 
		    cnt <= 3'd0;
		else 
		   //用计数来进行7-0的移位操作  
			  cnt <= cnt + 1'b1;
	end
  initial begin
	   rst_n=0;
		data_i=0;
	  #(`clock_period*200)
	   rst_n=1;

     #(`clock_period*200)

	  data_i=1;
	  #(`clock_period*200)

	  data_i=1;
	  # (`clock_period*200)

	  data_i=1;
	  # (`clock_period*200)

	  data_i=1;
	  # (`clock_period*200)

	  data_i=1;
	  # (`clock_period*200)

	  data_i=1;
	  
	  # (`clock_period*200)
	  data_i=1;
	  # (`clock_period*200)
	  data_i=1;
	  # (`clock_period*200)
	  data_i=1;
	  # (`clock_period*200)
	  data_i = 0;
	  # (`clock_period*200)
	  data_i = 0;
	  # (`clock_period*200)
	  data_i = 0;
	  # (`clock_period*200)
	  data_i = 1;
	  # (`clock_period*200)
	  data_i = 1;
	  # (`clock_period*200)
	  data_i = 1;
	  # (`clock_period*200)
	  data_i = 1;
	  # (`clock_period*200)
	  data_i = 1;
	  # (`clock_period*200)
	  data_i = 1;
	  # (`clock_period*200)
	  data_i = 1;
	  # (`clock_period*200)
	  data_i = 1;
	  # (`clock_period*200)
	  data_i = 1;
	  # (`clock_period*200)
	  $stop;
  end
  
  endmodule 

波形图
在这里插入图片描述
在这里插入图片描述