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

数据串转并电路

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

简析

输入信号:valid_a, data_a
输出信号:ready_a,valid_b,data_b

valid_a信号拉高时,输入有效,并且每接收到6个有效数据才更新一次输出。所以首先设置一个数据移位寄存器data_r。从题目给的波形图可以看出,移位寄存器应是右移的。

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

然后设置一个仅在输入数据有效时工作的计数器cnt,用来指示有效数据的个数。

reg [2:0] cnt;
always@(posedge clk or negedge rst_n) begin
    if(~rst_n)
        cnt <= 0;
    else
        cnt <= ~ready_a||~valid_a? cnt:
               cnt     ==       5? 0  :
               cnt+1;
end

当有效数据达到6个时,输出数据有效信号valid_b拉高一个时钟周期。

always@(posedge clk or negedge rst_n) begin
    if(~rst_n)
      valid_b <= 0;
    else
      valid_b <= cnt==5;
end

当有效数据达到6个时,同时更新输出data_r

always@(posedge clk or negedge rst_n) begin
    if(~rst_n)
      	data_r <= 6'b0;
    else
    	data_r <= valid_a&&ready_a? {data_a, data_r[5:1]}: data_r;
end

根据题目要求ready_a始终拉高。

always@(posedge clk or negedge rst_n) begin
    if(~rst_n)
        ready_a <= 0;
    else
        ready_a <= 1;
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_r;
    reg [2:0] cnt;

    always@(posedge clk or negedge rst_n) begin
        if(~rst_n)
            cnt <= 0;
        else
            cnt <= ~ready_a||~valid_a? cnt:
                   cnt      ==      5? 0  :
                   cnt+1;
    end
    
    always@(posedge clk or negedge rst_n) begin
        if(~rst_n)
            data_r <= 6'b0;
        else
            data_r <= ready_a&&valid_a? {data_a, data_r[5:1]}: data_r;
    end
    
    always@(posedge clk or negedge rst_n) begin
        if(~rst_n)
            data_b <= 6'b0;
        else
            data_b <= cnt==5&&valid_a? {data_a, data_r[5:1]}: data_b;
    end
    
    always@(posedge clk or negedge rst_n) begin
        if(~rst_n)
            valid_b <= 0;
        else
            valid_b <= cnt==5;
    end
    
    always@(posedge clk or negedge rst_n) begin
        if(~rst_n)
            ready_a <= 0;
        else
            ready_a <= 1;
    end
endmodule
Verilog篇题解 文章被收录于专栏

本人对牛客网verilog篇题目一些理解

全部评论
你这个代码有漏洞。当计数器刚好记到5的时候,valid_a变为0,这个时候在后面几个cycle的并行输出位置的输出会一直变化。虽然没有具体输出出来,但是每一位上的数据都在移位。不完善。建议在输出的时候判断语句要加上valid_a有效。这样才能保证输入有效的数据,同时这个数据会在确定的输出位上。
2 回复 分享
发布于 2022-04-23 10:54
这个代码没有考虑到valid_a不连续的情况,有BUG。
点赞 回复 分享
发布于 2022-04-25 17:00
您好,请问第36行,为什么不考虑【ready_a==1】的情况呢?
点赞 回复 分享
发布于 2023-03-10 17:34 江苏

相关推荐

11 2 评论
分享
牛客网
牛客企业服务