题解 | #数据串转并电路#

数据串转并电路

http://www.nowcoder.com/practice/6134dc3c8d0741d08eb522542913583d

题意整理

本题要求实现将6个单bit输入数据拼接之后输出。

时序图含有的信息较多,观察时序图需要注意:

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

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

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

题解主体

要实现6个单bit输入数据的拼接,要用1个寄存器将先到达的数据缓存。当上游握手成功,将输入数据进寄存器,先收到的数据放在低位;当缓存好6个输入数据,valid_b拉高,输出data_b。

需要计数器来计数接收到的数据数量,计数器在0-5之间循环。计数器初始值是0,每接收一个数据,计数器加1,当计数器再次循环到0时,表示已经接收到6个数据,可以输出拼接结果。

Verilog代码如下:


reg [5:0]       data_reg;

reg [2:0]       data_cnt;


always @(posedge clk or negedge rst_n ) begin

       if(!rst_n)

              ready_a <= 'd0;

       else

              ready_a <= 1'd1;

end

always @(posedge clk or negedge rst_n ) begin

       if(!rst_n)

              data_cnt <= 'd0;

       else if(valid_a && ready_a)

              data_cnt <= (data_cnt == 3'd5) ? 'd0 : (data_cnt + 1'd1);

end

always @(posedge clk or negedge rst_n ) begin

       if(!rst_n)

              data_reg <= 'd0;

       else if(valid_a && ready_a)

              data_reg <= {data_a, data_reg[5:1]};

end


always @(posedge clk or negedge rst_n ) begin

       if(!rst_n)begin

              valid_b <= 'd0;

              data_b <= 'd0;

       end

       else if(data_cnt == 3'd5)begin

              valid_b <= 1'd1;

              data_b <= {data_a, data_reg[5:1]};

       end

       else

              valid_b <= 'd0;

end

参考答案

`timescale 1ns/1ns
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
);
reg 	[5:0]		data_reg;
reg 	[2:0]		data_cnt;

always @(posedge clk or negedge rst_n ) begin
	if(!rst_n) 
		ready_a <= 'd0;
	else 
		ready_a <= 1'd1;
end
always @(posedge clk or negedge rst_n ) begin
	if(!rst_n) 
		data_cnt <= 'd0;
	else if(valid_a && ready_a)
		data_cnt <= (data_cnt == 3'd5) ? 'd0 : (data_cnt + 1'd1);
end
always @(posedge clk or negedge rst_n ) begin
	if(!rst_n) 
		data_reg <= 'd0;
	else if(valid_a && ready_a)
		data_reg <= {data_a, data_reg[5:1]};
end

always @(posedge clk or negedge rst_n ) begin
	if(!rst_n)begin
		valid_b <= 'd0;
		data_b <= 'd0;
	end 
	else if(data_cnt == 3'd5)begin
		valid_b <= 1'd1;
		data_b <= {data_a, data_reg[5:1]};
	end
	else
		valid_b <= 'd0;
end
endmodule
全部评论
输出的条件是不是加一个valid_a,否则当data_a不是连续输入时,valid_b不是一个时钟使能
7 回复 分享
发布于 2022-05-01 13:52
想问一下答主,根据答主的分析 data_b是在已接收到6个数据后下一个时钟产生输出;而且代码也是这么写的,但是为什么给的时序图中,data_b是接收到6个数据时的那个当前时钟输出的呀
点赞 回复 分享
发布于 2022-07-31 17:38
这testbench做的也太差了,基本的边界条件都没检查出来。输出数据需要在当前数据是valid的条件下,答主这个不太对
1 回复 分享
发布于 2022-09-21 14:07 美国
计数器的清零条件设置的有问题,应该是 always @(posedge clk or negedge rst_n) begin if(!rst_n) data_cnt <= 0; else if(data_cnt == 5) data_cnt <= 0; else if(valid_a && ready_a) data_cnt <= data_cnt + 1; end 这样可以保证计数器及时清零, 否则后面会漏数据
1 回复 分享
发布于 2022-08-07 16:22
感觉输出条件应该为data_cnt==5 && valid_a && ready_a。和你下一题写valid_b拉高时的条件一样。
点赞 回复 分享
发布于 2023-05-04 16:55 安徽
pattern用的是額外設一個reg接資料,在第六筆資料到達的瞬間傳給data_b,難怪我一直過不了70ns,因為我直接在data_b上接
点赞 回复 分享
发布于 2023-03-30 12:55 台湾
想问一下大家,就是最后给data_b赋值的时候,为啥还再一次用到拼接呢?即 data_b <= {data_a, data_reg[5:1]};前面的6个时钟后数据不是已经全部传入data_reg了吗?可以直接根据当cnt = 5的时候, data_b <= data_reg吗?
点赞 回复 分享
发布于 2022-10-06 17:36 安徽

相关推荐

评论
24
4
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务