comparator
図のようにモジュールを何度もインスタンス化する 1 つのモジュールが必要だと思います。最高の柔軟性を得るには、パラメーターによって制御される幅の配列 (私のソリューションでは 2 次元) が必要です。generate
ブロック内ではfor-loops
andif-else
ステートメントを使用して接続を行います。私のソリューションは、配列のスライスを使用します+:
。
これは IEEE Std (1800-2009) に準拠しており、IEEE Std (1800-2005) にも当てはまるはずです。
module comparator_list #(parameter int SIZE=10) (input logic [7:0] in [SIZE-1:0], output logic [7:0] out [SIZE-1:0]);
generate
if (SIZE==1) begin : pass_through
always_comb out = in;
end : pass_through
else if (SIZE==2) begin : simple
comparator c0 ( .max(out[0]), .min(out[1]), .in0(in[0]), .in1(in[1]) );
end : simple
else if (SIZE%2==1) begin : odd_list
logic [7:0] in_buf [SIZE:0];
logic [7:0] out_buf [SIZE:0];
always_comb begin : link_in
foreach(in[idx]) in_buf[idx] = in[idx];
in_buf[SIZE] = 8'h00; // force last entry to 'h0 if unasigned, 'h80 if signed
end : link_in
always_comb begin : link_out
foreach(out[idx]) out[idx] = out_buf[idx];
// Note: out_buf[SIZE] is don't care
end : link_out
comparator_list #(SIZE+1) cl (.in(in_buf), .out(out_buf));
end : odd_list
else begin : even_list
logic [(SIZE/2)*8-1:0] top [SIZE+1];
logic [(SIZE/2)*8-1:0] bot [SIZE+1];
for(genvar idx=0; idx<SIZE/2; idx+=1) begin : map
always_comb {top[0][idx*8+:8],bot[0][idx*8+:8]} = {in[2*idx],in[2*idx+1]};
always_comb {out[2*idx],out[2*idx+1]} = {top[SIZE][idx*8+:8],bot[SIZE][idx*8+:8]};
end : map
for(genvar stage=0; stage<SIZE; stage++) begin : link
if(stage%2==0) begin : even
comparator c0[SIZE/2-1:0] (
.max(top[stage+1][0+:(SIZE/2)*8]), .in0(top[stage][0+:(SIZE/2)*8]),
.min(bot[stage+1][0+:(SIZE/2)*8]), .in1(bot[stage][0+:(SIZE/2)*8]) );
end : even
else begin : odd
assign top[stage+1][7:0] = top[stage][7:0];
comparator c1[SIZE/2-2:0] (
.max(bot[stage+1][0+:(SIZE/2-1)*8]),
.min(top[stage+1][8+:(SIZE/2-1)*8]),
.in0(bot[stage][0+:(SIZE/2-1)*8]),
.in1(top[stage][8+:(SIZE/2-1)*8])
);
assign bot[stage+1][(SIZE/2-1)*8+:8] = bot[stage][(SIZE/2-1)*8+:8];
end : odd
end : link
end : even_list
endgenerate
endmodule : comparator_list