- sync_rtl/common/: skid_buffer, pipeline_reg, defines (valid/ready) - sync_rtl/mod_add/: modular adder example with Verilator C++ TB - test_framework/: Python-driven Verilator compile/sim/compare pipeline - test_framework/modules/mod_add/: 50-vector test plan, full鏈路 PASS - .trellis/spec/: RTL and test_framework conventions documented
74 lines
2.3 KiB
Verilog
74 lines
2.3 KiB
Verilog
// skid_buffer.v - 2-entry skid buffer with valid/ready handshake
|
|
//
|
|
// When valid_i && ready_o, capture data_i. Output via valid_o && ready_i.
|
|
// Stores one extra entry in skid register. Pure combinational ready_o path.
|
|
//
|
|
// Parameters:
|
|
// DW = data width (default 12)
|
|
//
|
|
// Interface:
|
|
// clk, rst_n - clock, active-low reset
|
|
// data_i, valid_i, ready_o - input side
|
|
// data_o, valid_o, ready_i - output side
|
|
|
|
module skid_buffer #(parameter DW = 12) (
|
|
input clk,
|
|
input rst_n,
|
|
input [DW-1:0] data_i,
|
|
input valid_i,
|
|
output ready_o,
|
|
output [DW-1:0] data_o,
|
|
output valid_o,
|
|
input ready_i
|
|
);
|
|
|
|
// Internal state
|
|
reg skid_valid; // skid register has valid data
|
|
reg [DW-1:0] skid_data; // skid register data
|
|
|
|
// Output register (pipeline stage)
|
|
reg out_valid;
|
|
reg [DW-1:0] out_data;
|
|
|
|
// ready_o is combinational: ready when output slot is empty
|
|
// (either out_valid is 0, or ready_i is high and we can accept new data)
|
|
assign ready_o = !out_valid || ready_i;
|
|
|
|
// valid_o drives from output register
|
|
assign valid_o = out_valid;
|
|
assign data_o = out_data;
|
|
|
|
always @(posedge clk or negedge rst_n) begin
|
|
if (!rst_n) begin
|
|
skid_valid <= 1'b0;
|
|
skid_data <= {DW{1'b0}};
|
|
out_valid <= 1'b0;
|
|
out_data <= {DW{1'b0}};
|
|
end else begin
|
|
if (out_valid && ready_i) begin
|
|
// Output consumed: load from skid if available
|
|
if (skid_valid) begin
|
|
out_data <= skid_data;
|
|
out_valid <= 1'b1;
|
|
skid_valid <= 1'b0;
|
|
end else begin
|
|
out_valid <= 1'b0;
|
|
end
|
|
end
|
|
|
|
if (valid_i && ready_o) begin
|
|
if (!out_valid || (out_valid && ready_i && !skid_valid)) begin
|
|
// Output slot free: go directly to output
|
|
out_data <= data_i;
|
|
out_valid <= 1'b1;
|
|
end else begin
|
|
// Output slot occupied: store in skid
|
|
skid_data <= data_i;
|
|
skid_valid <= 1'b1;
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
endmodule
|