Verilog手撕代码(5)串转并、并转串

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

串转并

常规转换

用一个计数器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

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

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

结合握手机制的串转并

实现串并转换电路,输入端输入单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

并转串

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

在输入数据有效的时候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

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

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

  • 5
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
这段代码是一个Verilog的函数,用于判断输入向量是否为onehot编码。引用中的SystemVerilog代码定义了一个自动的函数is_onehot,它接受一个输入向量sig,函数内部使用一个名为parity的逻辑向量来计算输入向量的奇偶校验位。函数中的for循环用于遍历输入向量的每一个位,并使用异或操作符^将每个位与前一个位的奇偶校验位进行异或运算。最后,函数使用逻辑与运算符&和逻辑或运算符|对奇偶校验位进行比较,以判断输入向量是否为onehot编码。如果所有条件都满足,则函数返回true,否则返回false。 引用中的代码也是一个Verilog的函数,名为is_onehot,它使用类似的方法来判断输入向量是否为onehot编码。函数内部的逻辑和运算符&&被用于检查奇偶校验位的条件。与中的代码相比,这段代码多了一个向量前导1检测器的注释,但实际上代码内容是相同的。 总结来说,这段Verilog代码定义了一个用于判断输入向量是否为onehot编码的函数,它使用奇偶校验位和逻辑运算符来实现。这种编码的一大特点是,在输入向量的每一位中,只有一个位被置为1,其他位均为0。这种编码方式在一些应用中具有重要意义,例如多路选择器、优先编码器等。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [Verilog代码(11)1检测(统计个数、独热码检测、1的位置检测)](https://blog.csdn.net/m0_51965113/article/details/131374816)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* [暑期实习准备——牛客Verilog刷题(完结)](https://blog.csdn.net/diamond_biu/article/details/129207228)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值