VL30 数据串转并电路

文章描述了一个串并转换电路的设计,使用valid-ready和valid-only握手协议,通过计数器控制6位数据的输出,当接收到6个输入数据后,将它们合并并输出。设计包括计数器、移位寄存器和同步时钟控制逻辑。
摘要由CSDN通过智能技术生成
题目描述:

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

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

 

 个人理解:

从题目和波形图可看出,valid_a默认为低电平,当valid_a拉高时data_a的输入有效。先输入的data_a为data_b的低位。串并转换需要设置一个计数器,当计数个数为6个时valid_b拉高的同时data_b输出数据。ready_a=1默认模块有效,这里拉高就行了。

PS:

l  data_b是在已接收到6个数据后下一个时钟产生输出;

l  本模块与上游采用valid_ready握手机制,当valid_a拉低,表示与上游握手未成功,则此时data_a的数据无效,不存入本模块当中;

l  本模块与下游采用valid_only握手机制,这是一种单向指示性握手机制,已接收到6个数据后,valid_b拉高一个时钟周期,指示输出数据有效性

代码:

`timescale 1ns / 1ns

module test(
	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
);
    //计数
    reg [2:0]cnt;
    always@(posedge clk or negedge rst_n)begin
        if(!rst_n)
            cnt<=0;
        else begin
            //if(!valid_b)begin
                if(valid_a&&ready_a)begin
                    if(cnt>=5)
                        cnt<=0;
                    else
                        cnt<=cnt+1;
                end
                else
                    cnt<=cnt;
                //end
           // else 
           //     cnt<=0;
        end
    end
    
    //使用移位寄存器实现串转并
    reg [5:0] data_reg;
    always@(posedge clk or negedge rst_n)begin
        if(!rst_n)
            data_reg<=0;
        else begin
            //if(!valid_b)begin
                if(valid_a&&ready_a)
                    data_reg<={data_a,data_reg[5:1]}; 
                else
                    data_reg<=data_reg;
                end
            //else
             //   data_reg<=data_reg;
        end
    end 
    
    always@(posedge clk or negedge rst_n)begin
        if(!rst_n)
            valid_b<=0;
        else
            valid_b<=(cnt==5)?1:0;
    end 
     
    always@(posedge clk or negedge rst_n)begin
        if(!rst_n)
            data_b<=0;
        else begin
            if(cnt==5)
                data_b<={data_a,data_reg[5:1]};
            else
                data_b<=data_b;
        end
    end 
    
    always@(posedge clk or negedge rst_n)begin
        if(!rst_n)
            ready_a<=0;
        else
            ready_a<=1;
    end
    
endmodule

tb:

`timescale 1ns / 1ns
`define CLK_PERIOD_100M 10	
module test_tb();

//声明接口
reg clk;
reg rst_n;
reg valid_a;
reg data_a;

wire ready_a;
wire valid_b;
wire 	[5:0]	data_b;
	
//例化待测试模块
	test inst_s_to_p
		(
			.clk     (clk),
			.rst_n   (rst_n),
			.valid_a (valid_a),
			.data_a  (data_a),
			.ready_a (ready_a),
			.valid_b (valid_b),
			.data_b  (data_b)
		);
	


//产生复位和时钟
	//对复位和时钟进行初始化
initial begin
	clk <= 0;
	rst_n <= 0;
	#1000;
	rst_n <= 1;
end

	//产生时钟
always #(`CLK_PERIOD_100M/2) clk = ~clk;

//定义二维数组

//读取文本文件到二维数组



//产生测试激励信号
initial begin
	valid_a <= 0;
	data_a <= 0;
	@(posedge rst_n);
	@(posedge clk);
	gen_data101010();
	@(posedge clk);
	gen_data111000();
	@(posedge clk);
	gen_data000111();
	gen_data101010();
	gen_data111000();
	#1000;
	$fclose("file_goden");
	$fclose("file_test");
	$stop;	
end

//定义task
task gen_data101010;
	begin
		valid_a <= 1;
		data_a <= 1;
		@(posedge clk);
		data_a <= 0;
		@(posedge clk);
		data_a <= 1;
		@(posedge clk);
		data_a <= 0;
		@(posedge clk);
		data_a <= 1;
		@(posedge clk);
		data_a <= 0;
		@(posedge clk);
		valid_a <= 0;
	end
endtask

task gen_data111000;
	begin
		valid_a <= 1;
		data_a <= 1;
		@(posedge clk);
		data_a <= 1;
		@(posedge clk);
		data_a <= 1;
		@(posedge clk);
		data_a <= 0;
		@(posedge clk);
		data_a <= 0;
		@(posedge clk);
		data_a <= 0;
		@(posedge clk);
		valid_a <= 0;
	end
endtask

task gen_data000111;
	begin
		valid_a <= 1;
		data_a <= 0;
		@(posedge clk);
		data_a <= 0;
		@(posedge clk);
		data_a <= 0;
		@(posedge clk);
		data_a <= 1;
		@(posedge clk);
		data_a <= 1;
		@(posedge clk);
		data_a <= 1;
		@(posedge clk);
		valid_a <= 0;
	end
endtask

//打开文件
integer file_goden,file_test;
initial file_goden = $fopen("./output_file/file_goden.txt","w");
initial file_test = $fopen("./output_file/file_test.txt","w");

//写入数据
always@(posedge clk) begin
	if(valid_a)								$fwrite(file_goden,"%b\n",data_a);
end

always@(posedge clk) begin
	if(valid_b)begin
		$fwrite(file_test,"%b\n",data_b[5]);
		$fwrite(file_test,"%b\n",data_b[4]);
		$fwrite(file_test,"%b\n",data_b[3]);
		$fwrite(file_test,"%b\n",data_b[2]);
		$fwrite(file_test,"%b\n",data_b[1]);
		$fwrite(file_test,"%b\n",data_b[0]);
	end								
end



//对比数据打印结果

endmodule

仿真波形:

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
VL671是一款集成了丰富功能的电子元件,它具有广泛的应用领域,如通信、消费电子、工业控制和汽车电子等。VL671数据手册是为了帮助用户更好地了解和使用VL671而编写的技术资料。 VL671数据手册详细记录了VL671的各项技术规格和性能参数,以及操作说明和使用提示。手册的内容主要包括以下几个方面: 1. 产品概述:介绍了VL671的基本特性和产品结构,包括尺寸、引脚功能和电路构成等信息。 2. 电气特性:详细列出了VL671的电气参数,如工作电源电压范围、最大电流和功耗等,以及输入和输出特性,如电压范围、电流容限和开关时间等。 3. 功能描述:说明了VL671的各项功能和工作原理,包括数字信号处理、模拟信号转换和数据缓存等功能,帮助用户了解VL671的具体应用场景和优势。 4. 应用示例:给出了一些实际应用案例,展示了VL671在不同领域的应用方式和效果,以便用户参考和借鉴。 5. 使用注意事项:提供了使用VL671时需要特别注意的事项,如静电防护、温度处理和封装要求等,以确保使用过程中的安全性和稳定性。 总体而言,VL671数据手册是VL671的技术参考指南,用户可以通过学习手册中的内容,更好地了解和应用VL671,从而在自己的项目中发挥VL671的优势和功能。无论是初学者还是有经验的工程师,都可以通过VL671数据手册中的内容得到所需的技术支持和指导。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值