Dies Aliquanti

スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

PICを作ろう ,プログラムカウンタ ~昼休みにまったり進めるプロジェクト~

んじゃ,プログラムカウンタ(PC)行ってみましょう.PC(スタックを含む)に必要な機能は,昨日書いたように,以下の6種類
- 分岐 GOTO命令
- サブルーチンコール CALL命令
- サブルーチンからの復帰 RETURN,RETLW,RETFIE命令
- +1 (インクリメント)その他の命令
- 割り込みハンドルルーチン(0004h番地)へのコール
- ホールド(割り込みサイクル)
このうち,割り込みハンドルルーチン(0004h番地)へのコールとホールドの機能は,命令ではなく,インタラプトコントローラからの信号によって機能します.また,SKIP系の命令はインストラクションレジスタのフラッシュ(リセット)によって実装するので,PCには関係する機能はありません.

//
// Program counter
// (c) 2007 BakaOyaji
// $Id$
//
//

`include "../pic_instructions.h"
`include "../pic_def.h"

module pc(

    clk_i, reset_i, por_i ,
    instruction_i, // instruction from instruction reg.
    data_i , // from FileReg write bus
    pcl_we_i , // write enable for pcl
    program_counter_o, // out put of program counter
    pclath_i, // from PCLATH reg
    force_call4_i, // force call 0004
    hold_i, // hold current address
    pcl_o // pcl
);
input clk_i, reset_i, por_i ;
input [(`Instruction_Len-1):0] instruction_i ;

input [7:0] data_i ; // from FileReg write bus
input pcl_we_i ; // write enable for pcl
output [(`PC_Length-1):0] program_counter_o ;
input [7:0] pclath_i ; // from PCLATH reg
input force_call4_i; // force call 0004
input hold_i; // hold current address
output pcl_o ; // pcl out


reg [(`PC_Length-1):0] ProgramCounter ; // program counter
reg [(`PC_Length-1):0] stack[(`StackDepth-1):0];
reg [(`SP_Length-1):0] StackPointer;

    assign program_counter_o = ProgramCounter;
    assign pcl_o = ProgramCounter[7:0] ;

    always@( posedge clk_i ) begin
        if( por_i== 1'b1 ) begin
            ProgramCounter <= 'b0 ;
            StackPointer <= 'b0 ;
        end // if
        else if( reset_i == 1'b1 ) begin
            ProgramCounter <= 'b0 ;
        end // else if
        else if( pcl_we_i == 1'b1 ) begin
            ProgramCounter <= {pclath_i , data_i } ;
        end // else if
        else if(force_call4_i == 1'b1 ) begin
            ProgramCounter <= 'h0004 ;
            // Push note that PC is always advance
            stack[StackPointer] <= ProgramCounter ;
            StackPointer <= StackPointer + 1 ;
        end // else if
        else begin
            casex ( instruction_i )
                `Inst_GOTO : begin 
                    ProgramCounter <= {pclath_i[7:3] , instruction_i[10:0] } ;
                 end
                `Inst_CALL : begin 
                    ProgramCounter <= {pclath_i[7:3] , instruction_i[10:0] } ;
                    // Push note that PC is always advance
                    stack[StackPointer] <= ProgramCounter ;
                    StackPointer <= StackPointer + 1 ;
                 end
                `Inst_RETURN ,
                `Inst_RETFIE,
                `Inst_RETLW : begin // pop & branch
                    ProgramCounter <= stack[ StackPointer - 1 ] ;
                    StackPointer <= StackPointer - 1 ;
                end // pop
                default : begin
                    if( hold_i == 1'b1 ) begin 
                    end // if
                    else begin
                        ProgramCounter <= ProgramCounter + 1 ;
                    end // else
                end // default
            endcase // Instruction
        end // else
    end // always
endmodule // pc
// EOF pc.v


まあ,こんな感じでしょうか? 信号名は入力は最後に_iを,出力は_oをつけています.
リセットは,por_i(PowerOnReset)とreset_iの2系統にしてあります.論理合成してインプリメントする場合は同じ扱いでよいと思いますが,PICの仕様ではリセット時に不定になるレジスタがあり,シミュレーションでもそのように動作させるべく分けました.
pcl_we_iは,PCLレジスタのWriteEnableです.計算型GOTOに相当する機能ですね.分岐アドレスの計算は,PCLレジスタに書き込みの場合は,8ビット目から上をpclathで補うので,
    ProgramCounter <= {pclath_i , data_i } ;
その他リテラル命令の場合は,11ビット目から上を,pclathの3ビット目から上を補うので,
    ProgramCounter <= {pclath_i[7:3] , instruction_i[10:0] } ;
としています.
ホールドの機能は,
    if( hold_i == 1'b1 ) begin
    end // if

という記述で実現しています.条件が成立したら「何もしない」という感じです.

スタックはスタックポインターを使って実装していますが,書き上げてから気がついたのですが,所詮8レベルしかないので,シフトレジスタで書いたほうがよさそうです.また,alwaysブロックの中のif ~ else if ~ else ifとそれに続くcasexの条件は,相互排他(mutual exclusive)になっているところがあるので,論理合成時にはparallel caseにした方がよいです.
この辺は,全体が出来上がってからなおすことにしましょう.

次回は、インストラクションレジスタの予定です。
---
本日の御託
庭の芝刈りをしました.先週サボったために結構大変だった.雑草は気にせず雑草ごと刈り込みしてしまう.春先に気になっていた,スギナも毎週芝刈りをしていれば,それほど生えてはこない.一方,「野芝」が最近は目立つ.野芝はイネ科のため,芝用の除草剤でも駆除できないので,気長に手で摘み取るしかない.コガネムシの幼虫発見。そのうち、薬を撒こう。その他、カナヘビの子供2匹目撃.



コメント

コメントの投稿


管理者にだけ表示を許可する

トラックバック

トラックバック URL
http://diesaliquanti.blog.fc2.com/tb.php/349-b7c8f160
この記事にトラックバックする(FC2ブログユーザー)

FC2Ad

まとめ

上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。