题解 | #数据累加输出#
数据累加输出
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
以及对应的仿真波形: