Dies Aliquanti

スポンサーサイト

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

PICを作ろう ,ファイルレジスタ ~昼休みにまったり進めるプロジェクト

ファイルレジスタだが、思いっきり面倒くさい。とりあえず、PIC16F84Aの汎用レジスタと最低限必要な、スペシャルファンクションレジスタのPCLATH、PCL、STATUS,FSRだけ実装する。といっても、PCL,FSRは実体はCPUの中にあるため、インターフェースのみの実装です。
基本的にはデコーダーとデータセレクタのかたまりです、はい。PIC16シリーズでは、ファンクションレジスタのアドレス空間は最大で512バイト(Page0から4)ですが、品種によってはページ数が異なります。また、レジスタによっては異なるページでも同じページ内アドレスでアクセスできるようになっています。たとえば、PIC16F84では、PCLレジスタはページ0でのみアクセスできますが、STATUSレジスタはページ0,1でアクセスできます。品種によるこのような違いをできるだけ少なくするため、アドレスを以下のように定義しています。

`define ADDR_PCL    (9'bx_0000_0010)
`define ADDR_STATUS (9'bx_x000_0011)

そのうえで、アドレスデコードを行うfunction hit()を用意しました。if文ではなく、casex文を使用していることに注意してください。casexを用いることで、比較対照のデータのうちxをDon't careと解釈させています。
一方、普通のRAMに相当するレジスタは、一定のアドレスのレンジを持ちます。こちらはうまい方法が思いつかないので、必要なビットスライスだけをとりだし、範囲の比較をしているだけです(function hit_gpr_addr)。
データセレクタは、回路的にはAND-OR treeになるのですが、あとからレジスタの構成を変える(つまり別のPIC16の品種に対応する)のがいくらかでも簡単になるように、wor(Wired OR)を使用しています。論理合成ツールが対応しているかどうかよく判りませんが、ダメならあとで、普通のネットとORを使うように書き直します。
実体がCPUの中にあるレジスタに関しては、Special functionレジスタの書き込みイネーブルや読み出しパスを一種のバックドアとして実装しました。
----
本日の御託
民主党内でも必ずしも足並みがそろっていないようだが、テロ特別措置法の延長が最大の争点になる感じになってきた。無責任な予測では、ずばり「参院での可決を取引材料に、衆院解散」(笑)。

//
// file registers of YAP16T84
//  (c) 2007 BakaOyaji
// $Id$
//
`include "yap16_instructions.h"
`include "yap16_def.h"
`include "yap16t84_def.h"

module yap16t84_file(
    input clk_i,
    input reset_i,

    input [(`YAP16_FA_WIDTH)-1:0] fr_addr_i ,
    input [7:0] data_i,        // write port
    input we_i,                // write enable
    output [7:0] data_o, // read port
    input re_i,                // read enable

    // backdoors
    // PCL register
    input [7:0] pcl_i,            // data from PCL reg
    output pcl_we_o,
    // back doors from/to CPU
    input [7:0] status_i,   // data from status reg
    output status_we_o,        // write enable
    // PCLATH reg
    output [(`YAP16_PC_WIDTH -1 -8):0] pclath_o ,
    // FSR reg
    output [7:0] fsr_o
) ;

    wor [7:0] data_o ;

    // address decoders
    assign hit_tmr0 =        hit( fr_addr_i , `ADDR_TMR0);
    assign hit_pcl =        hit( fr_addr_i , `ADDR_PCL) ;
    assign hit_status =        hit( fr_addr_i , `ADDR_STATUS) ;
    assign hit_fsr =        hit( fr_addr_i , `ADDR_FSR );
    assign hit_porta=        hit( fr_addr_i , `ADDR_PORTA) ;
    assign hit_portb =        hit( fr_addr_i , `ADDR_PORTB) ;
    assign hit_eedata = hit( fr_addr_i , `ADDR_EEDATA) ;
    assign hit_eeadr =        hit( fr_addr_i , `ADDR_EEADR) ;
    assign hit_pclath = hit( fr_addr_i , `ADDR_PCLATH) ;
    assign hit_gpr =        hit_gpr_addr( fr_addr_i[5:0]) ;

    // feed read data
    // assign data_o = hit_tmr0 ? 8'hxx : 8'h00 ;
    assign data_o = hit_pcl        ? pcl_i : 8'h00 ;
    assign data_o = hit_status ? status_i : 8'h00 ;
    assign data_o = hit_fsr ? fsr_o : 8'h00 ;
    //assign data_o = hit_porta ? 8'hxx : 8'h00 ;
    //assign data_o = hit_portb ? 8'hxx : 8'h00 ;
    //assign data_o = hit_eedata ? 8'hxx : 8'h00 ;
    //assign data_o = hit_eeadr ? 8'hxx : 8'h00 ;
    assign data_o = hit_pclath        ?  { 8'h00, pclath} : 8'h00 ;
    assign data_o = hit_gpr ? gpr[ fr_addr_i[6:0]] : 8'h00 ;


    // generate XXXX_we_o
    assign pcl_we_o = (hit_pcl && (we_i == 1'b1));
    assign status_we_o = (hit_status && (we_i == 1'b1));

    // simple regs
    // FSR
    reg [7:0] fsr ;
    assign fsr_o = fsr ;
    always@( posedge clk_i) begin
        if( reset_i == 1'b1 ) begin
`ifdef FULLRESET
            fsr <= 8'h00 ;
`endif // FULLRESET
        end // if
        else if( hit_fsr && (we_i == 1'b1) ) begin
            fsr <= data_i ;
        end // else if
    end // always

    // PCLATH
    reg [(`YAP16_PC_WIDTH -1 -8):0] pclath ;
    assign pclath_o = pclath ;
    always@( posedge clk_i) begin
        if( reset_i == 1'b1 ) begin
`ifdef FULLRESET
            pclath <= 8'h00 ;
`endif // FULLRESET
        end // if
        else if( hit_pclath &&( we_i == 1'b1) ) begin
            pclath <= data_i ;
        end // else if
    end // always
    // General Purpose regs
    reg [7:0] gpr [`ADDR_GPR_LOW : `ADDR_GPR_HIGH] ;
    always@( posedge clk_i) begin
        if( hit_gpr &&( we_i == 1'b1) ) begin
            gpr[ fr_addr_i[6:0]] <= data_i ;
        end // if
    end // always

    // ---------------
    function hit(
        input [(`YAP16_FA_WIDTH-1):0] a ,
        input [(`YAP16_FA_WIDTH-1):0] b ) ;
    begin
        casex( a )
            b: hit = 1'b1 ; // true
            default : hit = 1'b0 ;  //false
        endcase
    end
    endfunction // hit

    function hit_gpr_addr(
            input [6:0] addr   ); // address is cut off to 6bit) ;
    begin
        hit_gpr_addr = ( ( `ADDR_GPR_LOW <=  addr) &&
                          (  addr <= `ADDR_GPR_HIGH) ) ;
    end
    endfunction // hit_gpr_addr

endmodule // yap16t84_file



コメント

コメントの投稿


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

トラックバック

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

FC2Ad

まとめ

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