PICを作ろう ,インタラプトハンドラ ~昼休みにまったり進めるプロジェクト
今日は、インタラプトハンドラです。インタラプト時の制御は、2007/07/21、2007/07/22、2007/07/25、で少し詳しく検討してますので、これに沿って実装します。このときの検討では、割り込みの信号は、2クロックサイクル入る事を前提にしています。このことを「保障」するのは、GIEビットを含めた、special function側で行うことにし、CPU側のインタラプトハンドラは、この前提のもとに実装します。(ソースコードは最後) 一応、FSMです。本当はムーアマシンにしたかったのですが、タイミングの制約から、ミーリィマシンになっています。出力の、iack_oは、インタラプトアクノレジサイクルを表します。
テストをするために、CPUの内部に下記のような記述を追加してみました。
reg irq;
wire [1:0]iack;
initial begin
irq = 1'b0 ;
#200 // change this value to change interrupt timing
@(posedge clk_i) // synch to clock
irq = 1'b1 ;
repeat (2)
@(posedge clk_i) ;
irq = 1'b0 ;
end
#200の部分を変えれば、任意のタイミングで割り込みを発生させられます。
実行結果は、こんな感じ。
とりあえず、うまくいっているようですね。分岐やSKIP系の命令の場合もテストする必要がありますが、次回予定。
----
本日の御託
庭の芝の状態がよろしくない。ちょっと、枯れた感じになっている。どうすっかな・・・
//
// Interrupt handler
// FIGURE 14-15: INT PIN INTERRUPT TIMING
// PIC16F627A/628A/648A
//
// $Id$
//
module interrupt_handler(
input clk_i,
input reset_i,
input irq_i , // interrupt request
output [1:0] iack_o // int ack cycle
) ;
reg int_cycle ;
assign iack_o[0] = (~int_cycle) & irq_i ;
assign iack_o[1] = int_cycle & irq_i ;
// FSM
always@( posedge clk_i) begin
if( reset_i == 1'b1 ) begin
int_cycle <=1'b0 ;
end //if
else if ( iack_o[0] == 1'b1 ) begin
int_cycle <= 1'b1 ;
end //else if
else begin
int_cycle <=1'b0 ;
end //else
end // always
endmodule // interrupt handler
// EOF interrupt handler.v