遅延可変シフトレジスタ(Verilog)
概要
遅延サイクルと幅を設定可能なシフトレジスタです。
意外とネットに記述が見当たらないので作成しました。
FF生成は本モジュールをパラメーターを変えて使いまわすと楽そう。
ModelSimで動作確認し、Quartus13.1にて実装確認を行いました。
LUTでやることをRTLで記述しFFは必要なときに入れると、FPGA(LUT&FF)ライクなソースコードになるような気がします。(根拠あんまり無し)
ソースコード
shift_reg.v
// shift_reg.v // author:manaka // date:19/01/04 // Description:First // History // v0.1 create new // module shift_reg #( parameter SHIFT_CYCLE = 5 ,parameter SHIFT_WIDTH = 12 ) ( input rst // reset ,input clk // clock ,input [SHIFT_WIDTH-1:0] data_in // data_input ,output[SHIFT_WIDTH-1:0] data_out // data_output ); genvar reg_lp ; // reg loop variable genvar wire_lp ; // wire loop variable reg [SHIFT_WIDTH-1:0] data_ff_r[SHIFT_CYCLE:1] ; // shift_reg wire [SHIFT_WIDTH-1:0] data_ff [SHIFT_CYCLE:0] ; // shift_wire /* shift register */ generate for(reg_lp = 0; reg_lp < SHIFT_CYCLE; reg_lp = reg_lp + 1) begin : gen_reg_lp always @(posedge clk or posedge rst) begin if(rst)begin data_ff_r[reg_lp+1] <= {SHIFT_WIDTH{1'b0}}; end else begin data_ff_r[reg_lp+1] <= data_ff[reg_lp]; end end end endgenerate generate for( wire_lp = 0; wire_lp < SHIFT_CYCLE; wire_lp = wire_lp + 1) begin : gen_wire_lp assign data_ff[wire_lp+1] = data_ff_r[wire_lp+1]; end endgenerate /* external port */ assign data_ff[0] = data_in ; assign data_out = data_ff[SHIFT_CYCLE] ; endmodule
検証環境
- shift_reg_tb.v
- shift_reg_top.v TOPからパラメーターでデータ幅とサイクル数を定義
- S1.shift_reg.v width:12 cycle数: 5
- S2.shift_reg.v width:32 cycle数:11
- S3.shift_reg.v width: 1 cycle数:22
- shift_reg_top.v TOPからパラメーターでデータ幅とサイクル数を定義
shift_reg_top.v
// shift_reg_tb.v // author:manaka // date:19/01/04 // Description:First // History // v0.1 create new // module shift_reg_top ( input RST // reset ,input CLK // clock ,input [11:0] DATA_1_IN // data_input ,output[11:0] DATA_1_OUT // data_output ,input [31:0] DATA_2_IN // data_input ,output[31:0] DATA_2_OUT // data_output ,input [0:0] DATA_3_IN // data_input ,output [0:0] DATA_3_OUT // data_output ); //------------------------------------ // shift_reg module //------------------------------------ defparam S1.SHIFT_CYCLE = 5 ; defparam S1.SHIFT_WIDTH = 12 ; shift_reg S1( .rst (RST) ,.clk (CLK) ,.data_in (DATA_1_IN) ,.data_out (DATA_1_OUT) ); defparam S2.SHIFT_CYCLE = 11 ; defparam S2.SHIFT_WIDTH = 32 ; shift_reg S2( .rst (RST) ,.clk (CLK) ,.data_in (DATA_2_IN) ,.data_out (DATA_2_OUT) ); defparam S3.SHIFT_CYCLE = 22; defparam S3.SHIFT_WIDTH = 1; shift_reg S3( .rst (RST) ,.clk (CLK) ,.data_in (DATA_3_IN) ,.data_out (DATA_3_OUT) ); endmodule
shift_reg_tb.v
// shift_reg_tb.v // author:manaka // date:19/01/04 // Description:First // History // v0.1 create new // `timescale 1ps/1ps module shift_reg_tb(); reg CLK ; reg RST ; reg [11:0] DATA_1_IN ; wire [11:0] DATA_1_OUT ; reg [31:0] DATA_2_IN ; wire [31:0] DATA_2_OUT ; reg [0:0] DATA_3_IN ; wire [0:0] DATA_3_OUT ; //------------------------------------ // shift_reg module //------------------------------------ shift_reg_top top_inst( .RST (RST ) ,.CLK (CLK ) ,.DATA_1_IN (DATA_1_IN ) ,.DATA_1_OUT (DATA_1_OUT ) ,.DATA_2_IN (DATA_2_IN ) ,.DATA_2_OUT (DATA_2_OUT ) ,.DATA_3_IN (DATA_3_IN ) ,.DATA_3_OUT (DATA_3_OUT ) ); //------------------------------------ // Clock generator //------------------------------------ parameter CLK_PERIOD = 20000; // ps 20ns initial begin CLK = 1'b0; end always #(CLK_PERIOD/2) begin CLK <= ~CLK; end //------------------------------------ // Reset generator //------------------------------------ initial begin RST = 1 ; repeat(20) @(negedge CLK); RST = 0 ; end //------------------------------------ // Test //------------------------------------ initial begin DATA_1_IN= {12{1'b0}}; DATA_2_IN= {32{1'b0}}; DATA_3_IN= {1{1'b0}}; @(negedge CLK); while(RST==0) @(negedge CLK); repeat(50) @(negedge CLK); DATA_1_IN= {12{1'b1}}; DATA_2_IN= {32{1'b1}}; DATA_3_IN= {1{1'b1}}; repeat(100) @(negedge CLK); DATA_1_IN= {12{1'b0}}; DATA_2_IN= {32{1'b0}}; DATA_3_IN= {1{1'b0}}; repeat(100) @(negedge CLK); $stop; end endmodule
検証結果
シミュレーション検証
TOPで宣言したモジュールがパラメーターにより遅延されることを確認。
- 12bit 5サイクル
- 32bit 11サイクル
- 1bit 22サイクル
ツール合成(Quartus13.1)
RTL viewer
Quartusで合成し、RTLViewerを確認。FFが125サイクルと3211サイクルと1*22サイクル生成されている。
テクノロジーマップ viewer
ロジックのFFが使用されると思っていたが、テクノロジーマップではRAMが使われている。
たくさんのシフトレジスタに各CellのFFを使うとLUTや配線リソースを効率的に使いづらくなる。そのため、RAMを使うようにツール側でつくられている。
FPGAリソースを効率的に使うために、ツール側が対応しているようだ。
(※この辺の特許はXilinxがLUTメモリはFFに使う方法をおさえているため、もしかしてRAM方法がとられているのか?VHDL編参照。)