FC2ブログ

[NEEK][動画再生]NiosIIカスタム命令を組み込みたい(1)

Qsysで環境作れたあと、リセット効かない問題は未解決だが、次は、カスタム命令を組み込みたい。
SOPC Builderの時もやったが、出来てない。とんずら雑記Rさんの所から頂いたYRV2RGBの命令
を組み込んで、ACM画像のデコードを高速化したい。

とんずらさんの所からそのままではなく、少し修正しているが(なんで修正したかおいおい思い出そう)、
とにかく今使用している、カスタム命令のロジックが以下。

// Verilog Custom Instruction Template File for Internal Register Logic

module custom_inst_yuv2rgb (
clk, // CPU system clock (required for multi-cycle or extended multi-cycle)
reset, // CPU master asynchronous active high reset (required for multi-cycle or extended multicycle)
clk_en, // Clock-qualifier (required for multi-cycle or extended multi-cycle)
start, // Active high signal used to specify that inputs are valid (required for multi-cycle or extended multi-cycle)
done, // Active high signal used to notify the CPU that result is valid (required for variable multi-cycle or extended variable multi-cycle)
dataa, // Operand A (always required)
datab, // Operand B (optional)
result // Result (always required)
);

// INPUTS
input clk;
input reset;
input clk_en;
input start;
input [31:0] dataa; // Y(0.255)
input [31:0] datab; // u(-128..127), v(-128..127)

// OUTPUTS
output reg done;
output reg [31:0] result;



// temporary regs.
reg signed [17:0] calc_R, calc_G, calc_B ;

// to refer parameter
wire signed [8:0] dy_i ;
wire signed [8:0] du_i, dv_i ;

// internal regs/wires
reg [3:0] conv_state ;

wire signed [17:0] d_Rv1, d_Rv2 ;
wire signed [17:0] d_Gu1, d_Gv2 ;
wire signed [17:0] d_Bu1, d_Bu2 ;

localparam STAT_IDLE = 4'b0001;
localparam STAT_STEP1 = 4'b0010;
localparam STAT_STEP2 = 4'b0100;
localparam STAT_FINISH = 4'b1000;

assign dy_i = { 1'b0, dataa[ 7: 0] } ; // unsigned 0..255
assign du_i = { datab[15], datab[15: 8] } ; // signed -128..127
assign dv_i = { datab[7], datab[ 7: 0] } ; // signed -128..127


always @ (posedge reset or posedge clk) begin
if (reset) begin
conv_state <= STAT_IDLE ;
done <= 1'b0 ;
result <= 32'h00000000 ;
calc_R <= 18'h0;
calc_G <= 18'h0;
calc_B <= 18'h0;
end
else begin
if (clk_en) begin
case (conv_state)
STAT_IDLE: begin
if (start) begin
// calc_R[17:0] <= {1'b0, dy_i[8:0], 8'h0000 } ;
// calc_G[17:0] <= {1'b0, dy_i[8:0], 8'h0000 } ;
// calc_B[17:0] <= {1'b0, dy_i[8:0], 8'h0000 } ;
calc_R[17:0] <= {1'b0, dy_i[8:0], 8'h00 } ;
calc_G[17:0] <= {1'b0, dy_i[8:0], 8'h00 } ;
calc_B[17:0] <= {1'b0, dy_i[8:0], 8'h00 } ;
conv_state <= STAT_STEP1 ;
end
else begin
done <= 1'b0 ;
end
end
STAT_STEP1: begin
calc_R <= calc_R + d_Rv1 ;
calc_G <= calc_G + d_Gu1 ;
calc_B <= calc_B + d_Bu1 ;
conv_state <= STAT_STEP2 ;
end
STAT_STEP2: begin
calc_R <= calc_R + d_Rv2 ;
calc_G <= calc_G + d_Gv2 ;
calc_B <= calc_B + d_Bu2 ;
conv_state <= STAT_FINISH ;
end
STAT_FINISH: begin
done <= 1'b1 ;
result[31:24] <= 8'h0 ;

if (calc_R[17]==1'b1)
result[23:16] <= 8'h0 ;
else if (calc_R[16]==1'b1)
result[23:16] <= 8'hFF ;
else
result[23:16] <= calc_R[15:8] ;

if (calc_G[17]==1'b1)
result[15: 8] <= 8'h0 ;
else if (calc_G[16]==1'b1)
result[15: 8] <= 8'hFF ;
else
result[15: 8] <= calc_G[15:8] ;

if (calc_B[17]==1'b1)
result[ 7: 0] <= 8'h0 ;
else if (calc_B[16]==1'b1)
result[ 7: 0] <= 8'hFF ;
else
result[ 7: 0] <= calc_B[15:8] ;

conv_state <= STAT_IDLE ;
end
endcase
end
end
end




assign d_Rv1 = { dv_i[8], dv_i[8:0], 8'h00 }; // v x 256
MUL_9x9 MUL_RV_inst ( // 9'h067;
.clken ( clk_en ),
.clock ( clk ),
.dataa ( dv_i ),
.datab ( 9'h067 ), // add 2011.2.16
.result ( d_Rv2 )
);

//MUL_GU MUL_GU_inst( // 9'hfa8;
MUL_9x9 MUL_GU_inst( // 9'hfa8;
.clken ( clk_en ),
.clock ( clk ),
.dataa ( du_i ) ,
.datab ( 9'hfa8 ), // add 2011.2.16 → SOPC BuilderでWarning:datab信号幅=9bit以上の数値になってる。
.result ( d_Gu1 )
);

//MUL_GV MUL_GV_inst( // 9'hf49;
MUL_9x9 MUL_GV_inst( // 9'hf49;
.clken ( clk_en ),
.clock ( clk ),
.dataa ( dv_i ) ,
.datab ( 9'hf49 ), // add 2011.2.16 → SOPC BuilderでWarning:datab信号幅=9bit以上の数値になってる。
.result ( d_Gv2 )
);


assign d_Bu1 = {du_i[8], du_i[8:0], 8'h00 }; // u x 256
//MUL_BU MUL_BU_inst ( // 9'h0c6;
MUL_9x9 MUL_BU_inst ( // 9'h0c6;
.clken ( clk_en ),
.clock ( clk ),
.dataa ( du_i ), // signed 9bit (mul 198. you must mult 256 and add)
.datab ( 9'h0c6 ), // add 2011.2.16
.result ( d_Bu2 ) // 18bit
);


endmodule



QsysのComponent Editorで新規登録すると、各信号タイプがてきとうに判断されて、Qsysの
Generateでエラーとなるので、以下のようにGUIで修正して保存すると次のtclになった。


# TCL File Generated by Component Editor 11.0
# Mon Aug 15 09:25:24 JST 2011
# DO NOT MODIFY


# +-----------------------------------
# |
# | custom_inst_yuv2rgb "ci_yuv2rgb" v1.0
# | null 2011.08.15.09:25:24
# |
# |
# | C:/user/work/neek/qsys_tutorial/niosii-ethernet-standard-3c25/rtl/custom_inst_yuv2rgb.v
# |
# | ./custom_inst_yuv2rgb.v syn, sim
# |
# +-----------------------------------

# +-----------------------------------
# | request TCL package from ACDS 11.0
# |
package require -exact sopc 11.0
# |
# +-----------------------------------

# +-----------------------------------
# | module custom_inst_yuv2rgb
# |
set_module_property NAME custom_inst_yuv2rgb
set_module_property VERSION 1.0
set_module_property INTERNAL false
set_module_property OPAQUE_ADDRESS_MAP true
set_module_property GROUP HOGE
set_module_property DISPLAY_NAME ci_yuv2rgb
set_module_property TOP_LEVEL_HDL_FILE custom_inst_yuv2rgb.v
set_module_property TOP_LEVEL_HDL_MODULE custom_inst_yuv2rgb
set_module_property INSTANTIATE_IN_SYSTEM_MODULE true
set_module_property EDITABLE true
set_module_property ANALYZE_HDL TRUE
set_module_property STATIC_TOP_LEVEL_MODULE_NAME ""
set_module_property FIX_110_VIP_PATH false
# |
# +-----------------------------------

# +-----------------------------------
# | files
# |
add_file custom_inst_yuv2rgb.v {SYNTHESIS SIMULATION}
# |
# +-----------------------------------

# +-----------------------------------
# | parameters
# |
# |
# +-----------------------------------

# +-----------------------------------
# | display items
# |
# |
# +-----------------------------------

# +-----------------------------------
# | connection point clock
# |
add_interface clock nios_custom_instruction end
set_interface_property clock clockCycle 0
set_interface_property clock operands 2

set_interface_property clock ENABLED true

add_interface_port clock clk clk Input 1
# |
# +-----------------------------------

# +-----------------------------------
# | connection point reset
# |
add_interface reset nios_custom_instruction end
set_interface_property reset clockCycle 0
set_interface_property reset operands 2

set_interface_property reset ENABLED true

add_interface_port reset reset reset Input 1
# |
# +-----------------------------------

# +-----------------------------------
# | connection point nios_custom_instruction_slave
# |
add_interface nios_custom_instruction_slave nios_custom_instruction end
set_interface_property nios_custom_instruction_slave clockCycle 0
set_interface_property nios_custom_instruction_slave operands 2

set_interface_property nios_custom_instruction_slave ENABLED true

add_interface_port nios_custom_instruction_slave start start Input 1
add_interface_port nios_custom_instruction_slave done done Output 1

add_interface_port nios_custom_instruction_slave dataa a Input 32
add_interface_port nios_custom_instruction_slave datab b Input 32

add_interface_port nios_custom_instruction_slave dataa dataa Input 32
add_interface_port nios_custom_instruction_slave datab datab Input 32

add_interface_port nios_custom_instruction_slave result result Output 32
add_interface_port nios_custom_instruction_slave clk_en clk_en Input 1
# |
# +-----------------------------------



ちなみにQsys画面では、NiosIIのマスター側とカスタム命令マクロの各信号とを接続した。
custom_instruction_master <--> clk, reset, nios_custom_instruction_slave

これでNios SBTでソフトウェアをSSRAMへダウンロードすると、SystemIDミスマッチになる。
SystemIDとTimeStampをチェック無しにしてやっても、FAILEDとなってしまう。
原因解析中。サブモジュールの接続を見ると、カスタム命令のインスタンスが接続されてない。
これがダウンロード失敗と何か関係してると思われる。

custom_inst_yuv2rgb custom_inst_yuv2rgb_0 (
.clk (cpu_custom_instruction_master_multi_slave_translator0_ci_master_clk), // clock.clk
.reset (), // reset.reset
.start (), // nios_custom_instruction_slave.start
.done (), // .done
.dataa (), // .a
.datab (), // .b
.result (cpu_custom_instruction_master_comb_slave_translator0_ci_master_result), // .result
.clk_en () // .clk_en
);



よくよくQsysのComponent Editor画面を見ると以下ワーニングが。

Warning: nios_custom_instruction_slave: Signal dataa[32] of type a must have width [5]
Warning: nios_custom_instruction_slave: Signal datab[32] of type a must have width [5]

a, bではなく、dataa, databに修正して、Generateをやり直ししてみたが、
まだ全て接続されてない。なぜだ?

custom_inst_yuv2rgb custom_inst_yuv2rgb_0 (
.clk (cpu_custom_instruction_master_multi_slave_translator0_ci_master_clk), // clock.clk
.reset (), // reset.reset
.start (), // nios_custom_instruction_slave.start
.done (), // .done
.dataa (cpu_custom_instruction_master_comb_slave_translator0_ci_master_dataa), // .dataa
.datab (cpu_custom_instruction_master_comb_slave_translator0_ci_master_datab), // .datab
.result (cpu_custom_instruction_master_comb_slave_translator0_ci_master_result), // .result
.clk_en () // .clk_en
);



ダウンロードしてみても、プログラムをカスタム命令に切り替えると、失敗する。
以下を変更してみた。しかし失敗。

MegaWizard Plug-In Manager > MUL9x9(LPM_MULT)開く > Generalタブ
  修正前: Automatically calculate the width
修正後: Restrict the width to 18 bits


NiosIIをe/をf/にしてみるが、そうすると、「altera_reserved_tck」のエラー問題が
出てしまう。以下URLで興味深い話をされている。
Web Editionでの解決策が良くわからないので保留。

http://www.ujiya-denshi.com/adiary/adiary.cgi/0125#c125


このブログのコメントで記載されていた
「JTAG系ペリフェラルを使う使う場合はTiming Driven Compilationはdefaultが良い」
について、設定を以下に変更。
  変更前: Timing Driven Synthesis = チェック有
  変更後: Timing Driven Synthesis = チェック無
結果、まだタイミング違反ある。


次は、Advisor > Timing Optimization Advisor > Use Global Clocks
> Open Assignment Editor
を起動し、外部50MHzクロック入力端子をグローバルクロック設定にする。
  clkin_50   Global Signal   Global Clock

結果違反消えず以下。

<Slow 1200mV 85C Model>
Setup Summary:  eth_std_main_system_inst|sdram|eth_std_main_system_sdram_controller_phy_inst|eth_std_main_system_sdram_phy_inst|eth_std_main_system_sdram_phy_alt_mem_phy_inst|clk|pll|altpll_component|auto_generated|pll1|clk[1] -1.207 -4.894
Removal Summary: altera_reserved_tck -2.269 -2.269


・・・何を変更したか忘れた。何か変更してコンパイルしたけど結局違反消えず。
Hold違反も出てきた。

<Slow 1200mV 85C Model>
Setup Summary:  
eth_std_main_system_inst|sdram|eth_std_main_system_sdram_controller_phy_inst|eth_std_main_system_sdram_phy_inst|eth_std_main_system_sdram_phy_alt_mem_phy_inst|clk|pll|altpll_component|auto_generated|pll1|clk[1] -1.053 -24.240
Hold Summary:  clkin_50 -0.629 -9.583
Removal Summary:  altera_reserved_tck -2.066 -2.066


いい加減よく分からないので、NiosIIはf/でなくe/に戻す事に。
すると、タイミング違反は全て消えた。


 QsysのNiosIIプロパティで以下のワーニング出てた。e/でもf/でも同じ。
 これSWのダウンロードエラーと何か関係あるかな。

Warning: cpu: The address range of the slaves connected to the Nios II instruction masters exceeds 28 bits. Attempts to call functions across 28-bit boundaries is not supported by GCC and will result in linker errors.



ワーニングの指摘は28bitなので、表せるのは0x10000000まで。
オーバーしてた以下ペリフェラルのアドレスを変更。
  sgdma_mmc_desc: 0x40000000 → 0x08000000
  sgdma_mmc    : 0x41000000 → 0x08100000
これでワーニングは消えた。
けど、やっぱりダウンロードエラーは消えない。


ダウンロードする時にSystemIDが不一致でRUN出来なかったため、ちょっと前からSystemID
チェックを外してやってた。それを元に戻すとやっぱり、SystemID不一致でRUN押せない。
QsysでSystemIDを再度インスタンス呼び出して、Generateし直して、sof作成まで実行。
それでも、SystemID不一致が出て、SWダウンロードのRUNが押せない。


次は、カスタム命令モジュールのリセット接続されてないのを疑う。
Highでリセットかかるので、reset端子に次の信号を接続した。

custom_inst_yuv2rgb custom_inst_yuv2rgb_0 (
.clk (cpu_custom_instruction_master_multi_slave_translator0_ci_master_clk), // clock.clk
.reset (rst_controller_reset_out_reset), // reset.reset
.start (), // nios_custom_instruction_slave.start
.done (), // .done
.dataa (cpu_custom_instruction_master_comb_slave_translator0_ci_master_dataa), // .dataa
.datab (cpu_custom_instruction_master_comb_slave_translator0_ci_master_datab), // .datab
.result (cpu_custom_instruction_master_comb_slave_translator0_ci_master_result), // .result
.clk_en () // .clk_en
);


結果は同じく失敗。


カスタム命令モジュールのclk_en、startをH固定しないと動かないので、1'b1に接続。

custom_inst_yuv2rgb custom_inst_yuv2rgb_0 (
.clk (cpu_custom_instruction_master_multi_slave_translator0_ci_master_clk), // clock.clk
.reset (rst_controller_reset_out_reset), // reset.reset
.start (1'b1), // nios_custom_instruction_slave.start
.done (), // .done
.dataa (cpu_custom_instruction_master_comb_slave_translator0_ci_master_dataa), // .dataa
.datab (cpu_custom_instruction_master_comb_slave_translator0_ci_master_datab), // .datab
.result (cpu_custom_instruction_master_comb_slave_translator0_ci_master_result), // .result
.clk_en (1'b1) // .clk_en
);


結果は・・・っと思ったけど、よくよく実際の回路見ると、startとclk_enが常にHだと
動きがおかしくなるから、それはボツ。


QsysのComponent Editorでカスタム命令回路の設定いじりながら以下みてたら
少し分かって来た。
http://www.altera.com/literature/ug/ug_nios2_custom_instruction.pdf
YUV2RGBは、4段階のステートマシンで構成されるから、clockCycleは4になると思う。
さらに、カスタム命令のタイプは資料で言うところの「Multicycle」になるはず。
だけど、QsysのComponent Editorの設定では、「Combinational」になってしまっていて、
しかも変更する場所が分からない。
ここを設定出来れば、QsysでGenerateした後に接続されてないclk_en、start、done
(つまりclk、reset、dataa、datab、result以外)が自動的に接続されるはず。

(2011/8/17追記)
clk_en、start、done信号も自動接続されるようになった。
やった事は以下2つ。
  ・Quatus v11.0へSP1をインストール。
  ・clk、reset端子の設定も、nios_custom_instruction_slaveタイプにした。
これでGenerateしたら、全ての端子が自動接続されるようになった。
やった事2個目は、昨日も同じ事をやっていたが、その時はGenerateの際、
  「clk端子はclockに接続しなければならない」
という意味のエラーが出ていた。
エラーが出なくなった理由はSP1インストールだと思うが、もしかしたら、何か他の設定も
変えてしまっている事も要因なのかもしれない。(記憶ではそんな事してないが)
とにかく自動的にyuv2rgbの全端子が接続されたのが以下。
また、その時のtclも記載しておく。

custom_inst_yuv2rgb custom_inst_yuv2rgb_0 (
.done (cpu_custom_instruction_master_multi_slave_translator0_ci_master_done), // nios_custom_instruction_slave.done
.dataa (cpu_custom_instruction_master_multi_slave_translator0_ci_master_dataa), // .dataa
.datab (cpu_custom_instruction_master_multi_slave_translator0_ci_master_datab), // .datab
.result (cpu_custom_instruction_master_multi_slave_translator0_ci_master_result), // .result
.clk_en (cpu_custom_instruction_master_multi_slave_translator0_ci_master_clk_en), // .clk_en
.start (cpu_custom_instruction_master_multi_slave_translator0_ci_master_start), // .start
.reset (cpu_custom_instruction_master_multi_slave_translator0_ci_master_reset), // .reset
.clk (cpu_custom_instruction_master_multi_slave_translator0_ci_master_clk) // .clk
);



# TCL File Generated by Component Editor 11.0sp1
# Wed Aug 17 18:31:45 JST 2011
# DO NOT MODIFY


# +-----------------------------------
# |
# | custom_inst_yuv2rgb "ci_yuv2rgb" v1.0
# | null 2011.08.17.18:31:45
# |
# |
# | C:/user/work/neek/qsys_tutorial/niosii-ethernet-standard-3c25/rtl/custom_inst_yuv2rgb.v
# |
# | ./custom_inst_yuv2rgb.v syn, sim
# |
# +-----------------------------------

# +-----------------------------------
# | request TCL package from ACDS 11.0
# |
package require -exact sopc 11.0
# |
# +-----------------------------------

# +-----------------------------------
# | module custom_inst_yuv2rgb
# |
set_module_property NAME custom_inst_yuv2rgb
set_module_property VERSION 1.0
set_module_property INTERNAL false
set_module_property OPAQUE_ADDRESS_MAP true
set_module_property GROUP HOGE
set_module_property DISPLAY_NAME ci_yuv2rgb
set_module_property TOP_LEVEL_HDL_FILE custom_inst_yuv2rgb.v
set_module_property TOP_LEVEL_HDL_MODULE custom_inst_yuv2rgb
set_module_property INSTANTIATE_IN_SYSTEM_MODULE true
set_module_property EDITABLE false
set_module_property ANALYZE_HDL TRUE
set_module_property STATIC_TOP_LEVEL_MODULE_NAME custom_inst_yuv2rgb
set_module_property FIX_110_VIP_PATH false
# |
# +-----------------------------------

# +-----------------------------------
# | files
# |
add_file custom_inst_yuv2rgb.v {SYNTHESIS SIMULATION}
# |
# +-----------------------------------

# +-----------------------------------
# | parameters
# |
# |
# +-----------------------------------

# +-----------------------------------
# | display items
# |
# |
# +-----------------------------------

# +-----------------------------------
# | connection point nios_custom_instruction_slave
# |
add_interface nios_custom_instruction_slave nios_custom_instruction end
set_interface_property nios_custom_instruction_slave clockCycle 5
set_interface_property nios_custom_instruction_slave operands 2

set_interface_property nios_custom_instruction_slave ENABLED true

add_interface_port nios_custom_instruction_slave done done Output 1
add_interface_port nios_custom_instruction_slave dataa dataa Input 32
add_interface_port nios_custom_instruction_slave datab datab Input 32
add_interface_port nios_custom_instruction_slave result result Output 32
add_interface_port nios_custom_instruction_slave clk_en clk_en Input 1
add_interface_port nios_custom_instruction_slave start start Input 1
add_interface_port nios_custom_instruction_slave reset reset Input 1
add_interface_port nios_custom_instruction_slave clk clk Input 1
# |
# +-----------------------------------



(2011/8/18追記)
NiosIIの設定で、
Advanced Featuresタブ > include cpu resetrequest and resettaken signal
にチェックしたらダウンロード失敗。

.cpu_cpu_resetrequest_conduit_resetrequest (~clk_clk_in_reset_reset_n),:  The system console model is invalid. Cannot launch.
.cpu_cpu_resetrequest_conduit_resetrequest ( clk_clk_in_reset_reset_n),:  The system console model is invalid. Cannot launch.

生成された端子に外部リセットの論理を反転させて両方繋いでみたけど、
同じSWダウンロードエラーMSG。
CPUリセット後にシステムが再起動しない不具合が解決するかと思ったが。

この設定を無しにしても、SystemIDが不一致で、RUNが押せない問題。
Ignore SystemID、Ignore TimeStampにチェックして強引にダウンロードしても
Downloading ELF Process failed
とエラーになる。
SystemIDが不一致になる原因を探らねば。
スポンサーサイト



コメントの投稿

非公開コメント

カレンダー
01 | 2020/02 | 03
- - - - - - 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
累積訪問者
現在の訪問者
現在の閲覧者数:
最新記事
最新トラックバック
最新コメント
月別アーカイブ
カテゴリ
プロフィール

bobgosso

Author:bobgosso
FPGAのブログへようこそ!

検索フォーム
RSSリンクの表示
リンク
ブロとも申請フォーム

この人とブロともになる

QRコード
QRコード