目的:
入出力ポートには2次元配列を使用できない為、2次元配列を1次元配列にアサインする。
記述例:
内部信号
reg [P_BW-1:0] r_rise_pos[0:6] ;
を 1次元の配列
wire [P_BW*7-1:0] w_rise_pos ;
に アサイン する場合の記述例を以下に示す。
例1 :
assign w_rise_pos = {r_rise_pos[6], r_rise_pos[5],r_rise_pos[4],r_rise_pos[3],
r_rise_pos[2], r_rise_pos[1],r_rise_pos[0] } ;
例2 :
generate
for (i=0; i<7; i=i+1)
begin : asin_1d
assign w_rise_pos[(i+1)*P_BW-1:i*P_BW] = r_rise_pos[i] ;
end
endgenerate
回路例:
この回路例は、レジスタブロック(pgen_reg)とパルス生成ブロック(pgen_plsgen)で構成。
7組の 立ち上げタイミング(r_rise_pos)と立ち下げタイミング(r_fall_pos)レジスタを持ち、スタートビット(r_cntstart) に '1' をライトする事で、設定したタイミングで ON/OFF する7つのパルスを出力する。
立ち上げ/たち下げタイミングを 2次元配列とし、ブロック間 を1次元配列として接続している。
RTL (Verilog)
レジスタブロック : 2次元配列→1次元配列 のアサインに 上述の 例1 と 例2 を使用。
// ----------------------------------------------------- // 2d-array Sample module // // Module Name : pgen_reg // Version : 0.00 // ----------------------------------------------------- module pgen_reg #( // Module name : test parameter P_BW = 8 // parameter list ) ( // clr, // port list clk, adr, we, data, rd_data, cntstart, cntmax, rise_pos, fall_pos ) ; // ====== port declaration ================ input clr ; input clk ; input [3:0] adr ; input we ; input [P_BW-1:0] data ; output [P_BW-1:0] rd_data ; output cntstart ; output [P_BW-1:0] cntmax ; output reg [7*P_BW-1:0] rise_pos ; output reg [7*P_BW-1:0] fall_pos ; // ====== parameter declaration =========== parameter DLY = 1 ; // ====== internal signal declaration ===== wire [15:0] sel ; wire [15:0] reg_wen ; wire [7*P_BW-1:0] w_rise_pos ; wire [7*P_BW-1:0] w_fall_pos ; reg r_cntstart ; reg [P_BW-1:0] r_cntmax ; reg [P_BW-1:0] r_rise_pos[0:6] ; reg [P_BW-1:0] r_fall_pos[0:6] ; // variable for generate ---------- genvar i ; // ====== logical description ============= // address decode ------------------------- assign sel = 16'd1 << adr ; // write enable --------------------------- assign reg_wen = sel & {16{we}} ; // register ------------------------------- // cntstart reg ----------------------- always @(posedge clk or posedge clr) if (clr) r_cntstart <= #DLY 1'b0 ; else if (reg_wen[0]) r_cntstart <= #DLY data[0] ; // cntmax reg ------------------------- always @(posedge clk or posedge clr) if (clr) r_cntmax <= #DLY {P_BW{1'b0}} ; else if (reg_wen[1]) r_cntmax <= #DLY data ; // rise_pos, fall_pos reg ------------- generate for (i=0; i<7; i=i+1) begin : pos_reg always @(posedge clk or posedge clr) if (clr) r_rise_pos[i] <= #DLY {P_BW{1'b0}} ; else if (reg_wen[i*2+2]) r_rise_pos[i] <= #DLY data ; always @(posedge clk or posedge clr) if (clr) begin r_fall_pos[i] <= #DLY {P_BW{1'b0}} ; end else if (reg_wen[i*2+3]) r_fall_pos[i] <= #DLY data ; end endgenerate // read data select ----------------------- assign rd_data = (sel[0]) ? {{(P_BW-1){1'b0}},r_cntstart} : (sel[1]) ? r_cntmax : (sel[2]) ? r_rise_pos[0] : (sel[3]) ? r_fall_pos[0] : (sel[4]) ? r_rise_pos[1] : (sel[5]) ? r_fall_pos[1] : (sel[6]) ? r_rise_pos[2] : (sel[7]) ? r_fall_pos[2] : (sel[8]) ? r_rise_pos[3] : (sel[9]) ? r_fall_pos[3] : (sel[10]) ? r_rise_pos[4] : (sel[11]) ? r_fall_pos[4] : (sel[12]) ? r_rise_pos[5] : (sel[13]) ? r_fall_pos[5] : (sel[14]) ? r_rise_pos[6] : (sel[15]) ? r_fall_pos[6] : {P_BW{1'b1}} ; // 2d_array -> 1d_array -------------------- // EX.1 ------------ assign w_rise_pos = { r_rise_pos[6], r_rise_pos[5], r_rise_pos[4], r_rise_pos[3], r_rise_pos[2], r_rise_pos[1], r_rise_pos[0] } ; // EX.2 ------------ generate for (i=0; i<7; i=i+1) begin : asin_1d assign w_fall_pos[(i+1)*P_BW-1:i*P_BW] = r_fall_pos[i] ; end endgenerate // output signal --------------------------- assign cntstart = r_cntstart ; assign cntmax = r_cntmax ; always @(posedge clk or posedge clr) if (clr) rise_pos <= #DLY {(7*P_BW){1'b0}} ; else rise_pos <= #DLY w_rise_pos ; always @(posedge clk or posedge clr) if (clr) fall_pos <= #DLY {(7*P_BW){1'b0}} ; else fall_pos <= #DLY w_fall_pos ; endmodule
パルス生成ブロック : 1次元配列→2次元配列 のアサインに 上述の 例2 と同様の記述を使用。
// ----------------------------------------------------- // 2d-array Sample module // // Module Name : pgen_plsgen // Version : 0.00 // ----------------------------------------------------- module pgen_plsgen #( // Module name : test_plsgen parameter P_BW = 8 // parameter list ) ( // clr, // port list clk, cntstart, cntmax, rise_pos, fall_pos, pls_0, pls_1, pls_2, pls_3, pls_4, pls_5, pls_6 ) ; // ====== port declaration ================ input clr ; input clk ; input cntstart ; input [P_BW-1:0] cntmax ; input [7*P_BW-1:0] rise_pos ; input [7*P_BW-1:0] fall_pos ; output pls_0 ; output pls_1 ; output pls_2 ; output pls_3 ; output pls_4 ; output pls_5 ; output pls_6 ; // ====== parameter declaration =========== parameter DLY = 1 ; // ====== internal signal declaration ===== wire w_start_pls ; wire [P_BW-1:0] w_rise_pos[0:6] ; wire [P_BW-1:0] w_fall_pos[0:6] ; wire w_pls[0:6] ; wire w_valid ; reg r_start_dl ; reg [P_BW-1:0] r_count ; reg r_pls[0:6] ; // variable for generate ---------- genvar i ; // ====== logical description ============= // input array -> 2d array assign --------- generate for (i=0; i<7; i=i+1) begin : asin_2d assign w_rise_pos[i] = rise_pos[(i+1)*P_BW-1:i*P_BW] ; assign w_fall_pos[i] = fall_pos[(i+1)*P_BW-1:i*P_BW] ; end endgenerate // generate start pulse ------------------- always @(posedge clk or posedge clr) if (clr) r_start_dl <= #DLY 1'b0 ; else r_start_dl <= #DLY cntstart ; assign w_start_pls = cntstart & ~r_start_dl ; // pulse counter ------------------------- always @(posedge clk or posedge clr) if (clr) r_count <= #DLY {P_BW{1'b0}}; else if (w_start_pls) r_count <= #DLY {{(P_BW-1){1'b0}},1'b1} ; else if ((r_count > 0) && (r_count < cntmax) ) r_count <= #DLY r_count + 1 ; else if (r_count == cntmax) r_count <= #DLY {P_BW{1'b0}} ; assign r_valid = r_count != 0 ; // pulse generate ------------------------- generate for (i=0; i<7; i=i+1) begin : pos_reg assign w_pls[i] = (w_rise_pos[i] <= r_count) && (r_count < w_fall_pos[i]) && r_valid ; always @(posedge clk or posedge clr) if (clr) r_pls[i] <= #DLY {P_BW{1'b0}} ; else r_pls[i] <= #DLY w_pls[i] ; end endgenerate // output signal --------------------------- assign pls_0 = r_pls[0] ; assign pls_1 = r_pls[1] ; assign pls_2 = r_pls[2] ; assign pls_3 = r_pls[3] ; assign pls_4 = r_pls[4] ; assign pls_5 = r_pls[5] ; assign pls_6 = r_pls[6] ; endmodule
トップブロック : レジスタブロックとパルス生成ブロックの上位ブロック
// ----------------------------------------------------- // 2d-array Sample module // // Module Name : pgen // Version : 0.00 // ----------------------------------------------------- module pgen( clr, // port list clk, adr, we, data, rd_data, pls_0, pls_1, pls_2, pls_3, pls_4, pls_5, pls_6 ) ; // ====== port declaration ================ input clr ; input clk ; input [3:0] adr ; input we ; input [ 7:0] data ; output [ 7:0] rd_data ; output pls_0 ; output pls_1 ; output pls_2 ; output pls_3 ; output pls_4 ; output pls_5 ; output pls_6 ; // ====== internal signal declaration ===== wire cntstart ; wire [ 7:0] cntmax ; wire [7*8 -1:0] rise_pos ; wire [7*8 -1:0] fall_pos ; // ====== logical description ============= pgen_reg #( .P_BW (8) )i_test_reg( .clr ( clr ), .clk ( clk ), .adr ( adr ), .we ( we ), .data ( data ), .rd_data ( rd_data ), .cntstart ( cntstart ), .cntmax ( cntmax ), .rise_pos ( rise_pos ), .fall_pos ( fall_pos ) ) ; pgen_plsgen #( .P_BW (8) )i_test_plsgen( .clr ( clr ), .clk ( clk ), .cntstart ( cntstart ), .cntmax ( cntmax ), .rise_pos ( rise_pos ), .fall_pos ( fall_pos ), .pls_0 ( pls_0 ), .pls_1 ( pls_1 ), .pls_2 ( pls_2 ), .pls_3 ( pls_3 ), .pls_4 ( pls_4 ), .pls_5 ( pls_5 ), .pls_6 ( pls_6 ) ) ; endmodule
シミュレーション用のテストベンチ
// ---------------------------------------------------------- // test bench // // for pgen.v // ---------------------------------------------------------- `timescale 1ns / 1ps module testbench ; // testbench logic ------------------- logic clr; logic clk; logic [ 3:0] adr ; logic we ; logic [ 7:0] data ; logic [ 7:0] rd_data ; logic pls_0 ; logic pls_1 ; logic pls_2 ; logic pls_3 ; logic pls_4 ; logic pls_5 ; logic pls_6 ; // parameter ------------------------- parameter MAX_SIM_TIME = 20000 ; // target module --------------------- pgen i_pgen ( .clr ( clr ), .clk ( clk ), .adr ( adr ), .we ( we ), .data ( data ), .rd_data ( rd_data ), .pls_0 ( pls_0 ), .pls_1 ( pls_1 ), .pls_2 ( pls_2 ), .pls_3 ( pls_3 ), .pls_4 ( pls_4 ), .pls_5 ( pls_5 ), .pls_6 ( pls_6 ) ) ; // clock, reset generate ------------- initial begin clk = 0 ; clr = 1 ; #10 clr = 0 ; forever begin #10 clk = ~clk ; end end // scenario -------------------------- initial begin $dumpfile("wave.vcd"); $dumpvars(0,testbench) ; adr = 4'h0 ; we = 1'b0 ; data = 8'h0 ; #MAX_SIM_TIME $display(" SIM TIME OUT !!") ; $finish ; end // include test patteern ------------ initial begin $display (" ") ; #200 @(posedge clk) #1 adr = 4'h2 ; // rise_pos 0 data = 8'h10 ; we = 1'b1 ; @(posedge clk) #1 we = 1'b0 ; @(posedge clk) #1 @(posedge clk) #1 adr = 4'h3 ; // fall_pos 0 data = 8'h14 ; we = 1'b1 ; @(posedge clk) #1 we = 1'b0 ; @(posedge clk) #1 adr = 4'h4 ; // rise_pos 1 data = 8'h20 ; we = 1'b1 ; @(posedge clk) #1 we = 1'b0 ; @(posedge clk) #1 @(posedge clk) #1 adr = 4'h5 ; // fall_pos 1 data = 8'h28 ; we = 1'b1 ; @(posedge clk) #1 we = 1'b0 ; @(posedge clk) #1 adr = 4'h6 ; // rise_pos 2 data = 8'h30 ; we = 1'b1 ; @(posedge clk) #1 we = 1'b0 ; @(posedge clk) #1 @(posedge clk) #1 adr = 4'h7 ; // fall_pos 2 data = 8'h3f ; we = 1'b1 ; @(posedge clk) #1 we = 1'b0 ; @(posedge clk) #1 adr = 4'h8 ; // rise_pos 3 data = 8'h12 ; we = 1'b1 ; @(posedge clk) #1 we = 1'b0 ; @(posedge clk) #1 @(posedge clk) #1 adr = 4'h9 ; // fall_pos 3 data = 8'h38 ; we = 1'b1 ; @(posedge clk) #1 we = 1'b0 ; @(posedge clk) #1 adr = 4'ha ; // rise_pos 4 data = 8'h3e ; we = 1'b1 ; @(posedge clk) #1 we = 1'b0 ; @(posedge clk) #1 @(posedge clk) #1 adr = 4'hb ; // fall_pos 4 data = 8'h3f ; we = 1'b1 ; @(posedge clk) #1 we = 1'b0 ; @(posedge clk) #1 adr = 4'hc ; // rise_pos 5 data = 8'h0f ; we = 1'b1 ; @(posedge clk) #1 we = 1'b0 ; @(posedge clk) #1 @(posedge clk) #1 adr = 4'hd ; // fall_pos 5 data = 8'h10 ; we = 1'b1 ; @(posedge clk) #1 we = 1'b0 ; @(posedge clk) #1 adr = 4'he ; // rise_pos 6 data = 8'h20 ; we = 1'b1 ; @(posedge clk) #1 we = 1'b0 ; @(posedge clk) #1 @(posedge clk) #1 adr = 4'hf ; // fall_pos 7 data = 8'h21 ; we = 1'b1 ; @(posedge clk) #1 we = 1'b0 ; @(posedge clk) #1 adr = 4'h1 ; // count max data = 8'h50 ; we = 1'b1 ; @(posedge clk) #1 we = 1'b0 ; @(posedge clk) #1 @(posedge clk) #1 adr = 4'h0 ; // count start on data = 8'h01 ; we = 1'b1 ; @(posedge clk) #1 we = 1'b0 ; @(posedge clk) #1 @(posedge clk) #1 adr = 4'h0 ; // count start off data = 8'h00 ; we = 1'b1 ; @(posedge clk) #1 we = 1'b0 ; repeat(100) @(posedge clk) ; $display ("test_END"); $finish ; end // include assertion bind list ------- //`include "bind.list" //`include "bind_sva.sv" //`include "sva_1.sv" endmodule
シミュレーション結果を以下に示す。
コマンドラインからの VCD出力では 2次元配列の信号が表示されなかった為、vivado GUI でのシミュレーション波形を表示。pls0 のみ レジスタブロックとパルス生成ブロックの2次元配列を表示。(他は パルス生成ブロックのみ)
0 件のコメント:
コメントを投稿