目的:
入出力ポートには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次元配列を表示。(他は パルス生成ブロックのみ)