FPGA串并转换的实现

串并转换原理

   串并转换,简单来说,就是一个时钟或者多个时钟进来一个数据,将N个位宽为Data_Width的数据拼接成一个数据宽度为N*Data_Width的单个数据。那么其时序应该如下图所示(对于小模块的代码编写,在设计程序前,可以画一下时序图,更容易个人理解与代码的编写,个人观点,不喜勿喷)。
在这里插入图片描述

Verilog程序代码

module serial_parallel
#(
	parameter	Data_Width = 8,		//单个数据宽度
	parameter	Data_Number= 8		//进行串并转换的数据个数
)
(
	input												clk		,	//系统时钟信号
	input												rst_n	,	//复位信号
	input												start	,	//开始串并转换信号
	input				[Data_Width-1:0]				data_in	,	//串行输出的数据
				
	output		reg										finish	,	//串并转换结束信号
	output		reg		[Data_Number*Data_Width-1:0]	data_out	//并行输出的数据
);

//======================================
// 内部变量声明
//======================================
reg		[$clog2(Data_Number)-1:0]	cnt;
reg		start_reg;

//======================================
// 内部程序
//======================================
//start_reg
always @(posedge clk or negedge rst_n)
	if(!rst_n)
		start_reg <= 1'b0;
	else if(start)
		start_reg <= 1'b1;
	else if(finish)
		start_reg <= 1'b0;
	else
		start_reg <= start_reg;

//counter
always @(posedge clk or negedge rst_n)
	if(!rst_n)
		cnt <= 0;
	else if(start_reg) begin
		if(cnt == Data_Number-1) begin
			cnt <= 0;
		end
		else begin
			cnt <= cnt + 1'b1;
		end		
	end
	else if(finish)
		cnt <= 0;
	else
		cnt <= cnt;				

//finish signal
always @(posedge clk or negedge rst_n)
	if(!rst_n)
		finish <= 1'b0;
	else if(cnt == Data_Number-2)
		finish <= 1'b1;
	else
		finish <= 1'b0;

//or
// assign finish = (Data_Number-1) ? (1'b1) : (1'b0);
			
//======================================
// 数据拼接
//======================================
always @(posedge clk or negedge rst_n)
	if(!rst_n)
		data_out <= 0;
	else if(start_reg)
		data_out[cnt*Data_Width+:Data_Width] <= data_in;
	else
		data_out <= data_out;

endmodule

Test_Bench

module tb_serial_parallel();
parameter	Data_Width = 2;
parameter	Data_Number= 4;

reg		clk,rst_n,start;
wire	finish;
reg		[Data_Width-1:0]	data_in;
wire	[Data_Number*Data_Width-1:0]	data_out;

initial begin
	clk = 1;
	start = 0;
	data_in = 0;
	rst_n = 0;
	#60
	rst_n = 1;
	#20
	start = 1'b1;
	data_in <= 2'b01;
	#20
	start = 1'b0;
	data_in <= 2'b10;
	#20
	data_in <= 2'b11;
	#20
	data_in <= 2'b00;
	
end

always #10 clk = ~clk;

serial_parallel
#(
	.Data_Width (Data_Width ),	
	.Data_Number(Data_Number)	
)
serial_parallel_inst
(
	.clk		(clk		),	
	.rst_n		(rst_n		),	
	.start		(start		),
	.data_in	(data_in	),
				
	.finish		(finish		),
	.data_out   (data_out   )
);

endmodule

仿真结果

  仿真如下图所示,第一个时钟输入二进制数值01,此时计数器cnt=0,将01填入data_out的低2位,于是在第二个时钟的上升沿处得到输出数值data_out=00000001;在第二个时钟输出二进制数值10,此时计数器cnt=1,将10填入data_out的第4位和第3位,于是在第三个时钟的上升沿处得到输出数值data_out=00001001;…,以此类推,在第五个时钟的上升沿处得到串并转换完成的输出数值data_out=00111001。
在这里插入图片描述
  在这里有一点需要注意的是,串并转换完成信号(finish)需要在计数器cnt计数到Data_Number-2(Data_Number表示数据个数,即几个数据进行串并转换)的时候,拉高为高电平,表示一组数据进行串并转换结束。
  所以,在设计过程中,当需要进行数据串并转换时,可以将start信号拉高一个时钟周期,表示开始进行串并转换,而完成了数据的串并转换后,又输出串并转换结束信号finish。

备注:以上仅为个人学习笔记,如有问题,欢迎探讨交流,如有帮助,给个赞吧!

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值