当前位置:   article > 正文

Verilog手撕代码(5)串转并、并转串_verilog并行数据转串行数据

verilog并行数据转串行数据

串转并的使用环境非常多,在接口处用到最多,在某些模块的输入仅允许串行输入时,而总线上的数时并行的,那就需要通过串并转换,把并行的数据转换成串行的数据,包括在输出的时候,需要把串行的数据转换成并行的数据,才能送到总线中,使用方法都是用一个计数器来计数实现 。

串转并

常规转换

用一个计数器count,每输入8个数,就输出一次,每周期dout_temp左移一位,然后再将输入的1bit串行据存入dout_temp的最低位。

module serial_to_parallel(
	input clk,
	input rst_n,
	input din_serial,
	input din_valid,
	output reg [7:0]dout_parallel,
	output reg dout_valid
);

	reg[7:0]din_tmp;
	reg[3:0]cnt;
	
	always@(posedge clk or negedge rst_n)begin
		if(!rst_n)
			cnt <= 0;
		else if(din_valid)
			cnt <= (cnt == 4'd8)?0:cnt+1'b1;
		else	
			cnt <= 0;
	end
	
	always@(posedge clk or negedge rst_n)begin
		if(!rst_n)
			din_tmp <= 8'b0;
		else if(din_valid && cnt <= 4'd7)
			din_tmp <= {din_tmp[6:0],din_serial};
	
	end 
	
	always@(posedge clk or negedge rst_n)begin
		if(!rst_n)begin
			dout_valid <= 1'b0;
			dout_parallel <= 8'b0;
		end
		else if(cnt == 4'd8)begin
			dout_valid <= 1'b1;
			dout_parallel <= din_tmp;
		end
		else begin
			dout_valid <= 1'b0;
		end
	end 
	
endmodule
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44

Testbench:

module serial_to_parallel_tb();
	reg clk,rst_n;
	reg din_serial,din_valid;
	wire dout_valid;
	wire[7:0]dout_parallel;
 
	always #5 clk = ~clk;
 
	initial begin
		clk  <= 1'b0;
		rst_n <= 1'b0;
		#15
		rst_n <= 1'b1;
		din_valid  <= 1'b1;
		din_serial <= 1'b1; #10
		din_serial <= 1'b1; #10
		din_serial <= 1'b1; #10
		din_serial <= 1'b1; #10
	
		din_serial <= 1'b0; #10
		din_serial <= 1'b0; #10
		din_serial <= 1'b0; #10
		din_serial <= 1'b0; #10
		din_valid  <= 1'b0;
		#30
		din_valid  <= 1'b1;
		din_serial <= 1'b1; #10
		din_serial <= 1'b1; #10
		din_serial <= 1'b0; #10
		din_serial <= 1'b0; #10
	
		din_serial <= 1'b0; #10
		din_serial <= 1'b0; #10
		din_serial <= 1'b1; #10
		din_serial <= 1'b1; #20
		din_valid  <= 1'b0;
		#50
		$stop;
	end 
	serial_to_parallel u0(
    .clk           (clk)           ,
    .rst_n          (rst_n)          ,
    .din_serial    (din_serial)    ,
    .dout_parallel (dout_parallel) ,
    .din_valid     (din_valid)     ,
    .dout_valid    (dout_valid)
	);  
endmodule
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48

仿真结果:
在这里插入图片描述

结合握手机制的串转并

实现串并转换电路,输入端输入单bit数据,每当本模块接收到6个输入数据后,输出端输出拼接后的6bit数据。本模块输入端与上游的采用valid-ready双向握手机制,输出端与下游采用valid-only握手机制。数据拼接时先接收到的数据放到data_b的低位。

电路的接口如下图所示。valid_a用来指示数据输入data_a的有效性,valid_b用来指示数据输出data_b的有效性;ready_a用来指示本模块是否准备好接收上游数据,本模块中一直拉高;clk是时钟信号;rst_n是异步复位信号。

在这里插入图片描述

在这里插入图片描述
代码:

module s_to_p(
	input clk,
	input rst_n,
	input valid_a,
	input data_a,
	
	output reg ready_a,
	output reg valid_b,
	output reg [5:0]data_b
);
always@(posedge clk or negedge rst_n)begin
	if(!rst_n)
		ready_a <= 1'b0;
	else
		ready_a <= 1'b1;
end

re[2:0]cnt;
always@(posedge clk or negeedge rst_n)begin
	if(!rst_n)
		cnt <= 3'd0;
	else if(valid_a && ready_a)
		cnt <= cnt == 3'd5 ? 3'd0 : cnt + 1'b1;
	else
		cnt <= cnt;
end

reg [5:0]data_r;
always@(posedge clk or negedge rst_n)begin
	if(!rst_n)
		data_r <= 6'd0;
	esle if(valid_a && ready_a)
		data_r <= {data_a,data_r[5:1]};
end

always@(posedge clk or negedge rst_n)begin
	if(!rst_n)begin
		valid_b <= 1'b0;
		data_b <= 6'd0;
	end
	else if(cnt == 3'd5)begin
		data_b <= {data_a,data_r[5:1]};
		valid_b <= 1'b1;
	end
	else
		valid_b <= 1'b0;
end

endmodule
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49

并转串

并转串的原理和串转并差不多,都是用一个计数器来技术,根据串行和并行之间的关系来决定计数器计数的上下限。

在输入数据有效的时候din_valid为高时,把输入的数据寄存一下,寄存到din_parallel_temp中,然后再用一个计数器去检测输出,当计数器处在1~8的范围内时,让输出的串行数据等于输入的并行数据的最高位,然后每周期让并行数据左移一bit。这样,八周期后,就实现了并转串。

代码:

module parallel_to_serial(
	input clk,
	input rst_n,
	input [7:0] din_parallel,
	input din_valid,
	output reg dout_serial,
	output reg dout_valid
);

	reg[7:0]din_parallel_tmp;
	reg [3:0]cnt;
	
	always@(posedge clk or negedge rst_n)begin
		if(!rst_n)
			cnt <= 0;
		else if(din_valid)
			cnt <= cnt + 1'b1;
		else
			cnt <= 0;		
	end
	
	always@(posedge clk or negedge rst_n)begin
		if(!rst_n)begin
			din_parallel_tmp <= 8'b0;	
			dout_serial <= 1'b0;
			dout_valid <= 1'b0;
		end
		else if(din_valid && cnt == 0)begin
			din_parallel_tmp <= din_parallel;
		end
		else if((cnt >= 4'd1) && (cnt <= 4'd8))begin
			dout_serial <= din_parallel_tmp[7];
			din_parallel_tmp <= din_parallel_tmp << 1;
			dout_valid <= 1'b1;
		end
		else begin
			dout_serial <= 1'b0;
			dout_valid <= 1'b0;
		end
	end
	
endmodule
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42

Testbench:

module parallel_to_serial_tb();
reg clk, rst_n;
reg [7:0] din_parallel;
reg din_valid;
 
wire dout_valid,dout_serial;
 
always #5 clk = ~clk;
 
initial begin
    clk <= 1'b0;
    rst_n <= 1'b0;
    #15
    rst_n <= 1'b1;   
    din_valid <= 1'b1;
    din_parallel <= 8'b11110000;
    #80
    din_valid <= 1'b0;
    #40
    din_valid <= 1'b1;
    din_parallel <= 8'b10100011;
    #80
    din_valid <= 1'b0;
    #50
    $stop();
end
parallel_to_serial u_parallel_to_serial(
    .clk           (clk)          ,    
    .rst_n         (rst_n)         ,    
    .din_parallel  (din_parallel) ,
    .din_valid     (din_valid)    ,
    .dout_serial   (dout_serial)  ,
    .dout_valid    (dout_valid)
);
endmodule
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35

仿真结果:
在这里插入图片描述

本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号