题解 | #数据累加输出#

数据累加输出

https://www.nowcoder.com/practice/956fa4fa03e4441d85262dc1ec46a3bd

这里使用状态机实现,先确定输出逻辑使用时序逻辑还是组合逻辑实现,然后分析输出的控制逻辑(由输入与状态决定)。

`timescale 1ns/1ns

module valid_ready(
    input 				clk 		,   
    input 				rst_n		,
    input		[7:0]	data_in		,
    input				valid_a		,
    input	 			ready_b		,
    
    output		 		ready_a		,   //组合逻辑实现,立即输出变化,无气泡
    output	reg		    valid_b		,   //时序逻辑
    output  reg [9:0] 	data_out        //时序逻辑
);

reg [2:0] state,next_state;

always@(*)begin
	case(state)
        0:  	next_state = 1; //复位后进入初始态
        1:		next_state = valid_a ? 2 : 1;   //等待valid_a有效,接收第一位数据
        2:		next_state = valid_a ? 3 : 2;   //valid_a有效,接收第二位数据
        3:		next_state = valid_a ? 4 : 3;   //valid_a有效,接收第三位数据
        4:		next_state = valid_a ? 5 : 4;   //valid_a有效,接收第四位数据
		5:		next_state = valid_a&&ready_b ? 2 : 5;   //等待ready_b有效
		default:next_state = 0;
	endcase
end

always@(posedge clk,negedge rst_n)begin
	if(!rst_n)begin
		state <= 0;
	end
	else begin
		state <= next_state;
	end
end

always@(posedge clk,negedge rst_n)begin
	if(!rst_n)begin
		data_out <= 0;
	end
	else begin
        case (state)
            1:      data_out <= (valid_a) ? data_in             : data_out;
            2:      data_out <= (valid_a) ? data_out + data_in  : data_out;
            3:      data_out <= (valid_a) ? data_out + data_in  : data_out;
            4:      data_out <= (valid_a) ? data_out + data_in  : data_out;//此处需要判断valid_a有效
            5:      data_out <= ready_b   ? (valid_a?data_in:0) : data_out;//下游模块握手后判断valid_a有效
            default:data_out <= data_out;
        endcase
	end
end

always @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
        valid_b <= 0;
    end
    else begin
        valid_b <= ((state==4)&&valid_a)||((state==5)&&!ready_b&&valid_a);  
		//输出时拉高,直到下游模块处理好(ready_b=1)。
    end
end

assign ready_a = !((state==5)&&!ready_b);   //下游模块一准备好立即拉高

endmodule

顺便附上部分测试用例:

//~ `New testbench
`timescale  1ns / 1ps

module tb_valid_ready;

// valid_ready Parameters
parameter PERIOD  = 10;


// valid_ready Inputs
reg   clk                                  = 0 ;
reg   rst_n                                = 0 ;
reg   [7:0]  data_in                       = 0 ;
reg   valid_a                              = 0 ;
reg   ready_b                              = 0 ;

// valid_ready Outputs
wire  ready_a                              ;
wire  valid_b                              ;
wire  [9:0]  data_out                      ;


initial
begin
    forever #(PERIOD/2)  clk=~clk;
end

initial
begin
    $dumpfile ("HDL_bit_wave.vcd");
    $dumpvars;
    #(PERIOD*2) rst_n  =  1;
end

valid_ready  u_valid_ready (
    .clk                     ( clk             ),
    .rst_n                   ( rst_n           ),
    .data_in                 ( data_in   [7:0] ),
    .valid_a                 ( valid_a         ),
    .ready_b                 ( ready_b         ),

    .ready_a                 ( ready_a         ),
    .valid_b                 ( valid_b         ),
    .data_out                ( data_out  [9:0] )
);

initial
begin
    #(PERIOD*1.5+0.01);
    #(PERIOD)   data_in = 8'd1;valid_a = 1;
    #(PERIOD)   data_in = 8'd2;
    #(PERIOD)   data_in = 8'd3;
    #(PERIOD)   data_in = 8'd4;
    #(PERIOD)   data_in = 8'd5;
    #(PERIOD*2) ready_b = 1;
    #(PERIOD)   data_in = 8'd2;
    #(PERIOD)   data_in = 8'd3;
    #(PERIOD)   data_in = 8'd4;valid_a = 0;
    #(PERIOD)   data_in = 8'd5;valid_a = 1;
    #(PERIOD)   data_in = 8'd6;
    #(PERIOD)   ready_b = 1;
    #(PERIOD*2) ready_b = 0;
    $finish;
end

endmodule

以及对应的仿真波形:

全部评论

相关推荐

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