verilog 串并转换电路

数字电路中的串并转换主要设计思想来源于用面积换速度,对数据流进行管理。实现串并转换的主要方式有双口RAM,FIFO,移位寄存器等,对于数据量较大的一般使用双口RAM或者FIFO实现,数据量较小的使用移位寄存器实现。

一、串转并

1位串行数据转8位并行数据

module serial2parallel(
    input           clk,
    input           rst_n,
    input           data_valid_i,
    input           data_in,   //一位输入
    output   reg    data_valid_o,
    output   reg [7:0] data_out	//8位并行输出
    );

always @(posedge clk or negedge rst_n) begin
	if (rst_n == 1'b0)
		data_out <= 8'b0;
    //这里假设
	else if (data_valid_i == 1'b1)begin
        data_out <= {data_out[6:0], data_in};	//低位先赋值
		//data_out <= {data_in,data_out[7:1]};	//高位先赋值
        data_valid_o <= 1'b1;
    end
	else begin
        data_valid_o <= 1'b0;
        data_out <= data_out;
    end
		
end
endmodule

仿真结果

//~ `New testbench
`timescale  1ns / 1ps        

module tb_serial2parallel;   

// serial2parallel Parameters
parameter PERIOD  = 10;      


// serial2parallel Inputs    
reg   clk                                  = 0 ;
reg   rst_n                                = 0 ;
reg   data_valid_i                         = 0 ;
reg   data_in                              = 0 ;

// serial2parallel Outputs
wire  data_valid_o                         ;
wire  [7:0]  data_out                      ;


initial
begin
    forever #(PERIOD/2)  clk=~clk;
end

initial
begin
    #(PERIOD*2) rst_n  =  1;
end

serial2parallel  u_serial2parallel (
    .clk                     ( clk                 ),
    .rst_n                   ( rst_n               ),
    .data_valid_i            ( data_valid_i        ),
    .data_in                 ( data_in             ),

    .data_valid_o            ( data_valid_o        ),
    .data_out                ( data_out      [7:0] )
);

always @(posedge clk or negedge rst_n) begin
    if(!rst_n)begin
        data_valid_i <= 0;
        data_in <= 0;
    end
    else begin
        data_valid_i <= 1;
        data_in <= {$random} % 2;
    end
    
end

endmodule

在这里插入图片描述

二、并转串

8位并行数据转1位串行数据

module parallel2serial(
    input clk,
    input rst_n,
    input data_valid_i,
    input [7:0]data_in,//输入的8位并行数据
    output   reg    data_valid_o,
    output   reg    data_out//输出的1位串行数据
);
reg[7:0]data;
reg [3:0]cnt;
always @(posedge clk or negedge rst_n)
    begin
        if(!rst_n)begin
            data <= 8'b0;
            data_out <= 1'b0;
            data_valid_o <= 1'b0;
        end
            
        else if(data_valid_i && (cnt == 4'b0))begin
            data <= data_in;
        end
            
        else if((4'b0001<= cnt)&&(cnt <= 4'b1000))begin
            data <= data << 1;
            data_out <= data[7];
            data_valid_o <= 1'b1;
        end
        else begin
            data <= 8'b0;
            data_out <= 1'b0;
            data_valid_o <= 1'b0;
        end
            
    end

always @(posedge clk or negedge rst_n) begin
    if(!rst_n)
        cnt <= 4'b0;
    else if(data_valid_i)
        cnt <= cnt + 1'b1;
    else 
        cnt <= 1'b0;
end
endmodule

仿真结果

//~ `New testbench
`timescale  1ns / 1ps

module tb_parallel2serial;

// parallel2serial Parameters
parameter PERIOD  = 10;


// parallel2serial Inputs
reg   clk                                  = 0 ;
reg   rst_n                                = 0 ;
reg   data_valid_i                         = 0 ;
reg   [7:0]  data_in                       = 0 ;

// parallel2serial Outputs
wire  data_valid_o                         ;
wire  data_out                             ;


initial
begin
    forever #(PERIOD/2)  clk=~clk;
end

initial
begin
    #(PERIOD*2) rst_n  =  1;
end

parallel2serial  u_parallel2serial (
    .clk                     ( clk                 ),
    .rst_n                   ( rst_n               ),
    .data_valid_i            ( data_valid_i        ),
    .data_in                 ( data_in       [7:0] ),

    .data_valid_o            ( data_valid_o        ),
    .data_out                ( data_out            )
);

initial
begin
    #25 data_valid_i = 1;data_in = 8'b11011100;
    #(PERIOD*8) data_valid_i = 0;data_in = 8'b00000000;
    #20 data_valid_i = 1;data_in = 8'b11101001;
    #(PERIOD*8) data_valid_i = 0;data_in = 8'b00000000;
    #20 data_valid_i = 1;data_in = 8'b11110000;
    #(PERIOD*8) data_valid_i = 0;data_in = 8'b00000000;
    $finish;
end

endmodule

在这里插入图片描述

注意无论是串转并还是并转串,都要根据源数据实际的时序来修改代码逻辑。但是核心逻辑基本上是一样的,就是使用移位寄存器。

posted @ 2021-09-24 19:59  耐心的小黑  阅读(1120)  评论(0编辑  收藏  举报