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