ひでみのアイデア帳

くだらないことなんだけど、忘れないために・・・

汎用レジスタ

今日は汎用レジスタを作った。

汎用レジスタって何かって言うと、CPUから触れる外部レジスタで汎用に使えるようにしてみたものです。

GEMACがそこそこのボリュームになってきたので、そのテストベンチを書くとなると、外部CPUぐらいの機能があるものが欲しくなってきた。

毎回、CPUの外部バスに接続しているレジスタをスクラッチしているのも面倒なのでそこそこ、汎用性のあるものが欲しくなった。

と、いうことで作ってみた。

大雑把な仕様

バスから書き込みしたらレジスタにデータを保持するバスから読み出しが来たらレジスタのデータを出力する外部入力からビットをリセットできる外部入力からビットをクリアすることができる入力データをそのまま出力する

あと、条件としては

書き込み中の外部入力からのビットセットはバスからの書き込み時もセットされることバスからの書き込み時に外部入力からのビットクリアはしないこと

これくらいの制約でいいだろう。

そしたら、こんなのができた。

module aq_register

(

parameter BASE_ADDR = 32''h0000_0000 ) ( input RST_N, input CLK, input WE, input [3:0] BE, input [31:0] ADRS, input [31:0] WDATA, output [31:0] RDATA, input [31:0] DATA0_I, input [31:0] DATA1_I, input [31:0] DATA2_I, input [31:0] DATA3_I, output [31:0] DATA0_O, output [31:0] DATA1_O, output [31:0] DATA2_O, output [31:0] DATA3_O, input [31:0] DATA0_S, input [31:0] DATA1_S, input [31:0] DATA2_S, input [31:0] DATA3_S, input [31:0] DATA0_C, input [31:0] DATA1_C, input [31:0] DATA2_C, input [31:0] DATA3_C ), // Register 0 reg [31:0] data0_reg; always @(posedge CLK or negedge RST_N) begin if(!RST_N) begin data0_reg[31:0] <= 32''d0; end else begin if( (ADRS[31:4] == BASE_ADRS[31:4]) && (ADRS[3:2] == 2''d0)) begin if(WE) begin if(BE[0]) data0_reg[ 7: 0] <= WDATA[ 7: 0] | DATA0_S[ 7: 0]; if(BE[1]) data0_reg[15: 0] <= WDATA[15: 8] | DATA0_S[15: 8]; if(BE[2]) data0_reg[23:16] <= WDATA[23:16] | DATA0_S[23:16]; if(BE[3]) data0_reg[31:24] <= WDATA[31:24] | DATA0_S[31:24]; end else begin data0_reg[31:0] <=
((DATA0_S[31:0] | DATA0_C[31:0]) != 32''d0)?( (data0_reg[31:0] & ~DATA0_C[31:0]) | DATA0_S[31:0]): data0_reg[31:0]; end end end end // Register 1 reg [31:0] data1_reg; always @(posedge CLK or negedge RST_N) begin if(!RST_N) begin data1_reg[31:0] <= 32''d0; end else begin if( (ADRS[31:4] == BASE_ADRS[31:4]) && (ADRS[3:2] == 2''d1)) begin if(WE) begin if(BE[0]) data1_reg[ 7: 0] <= WDATA[ 7: 0] | DATA1_S[ 7: 0]; if(BE[1]) data1_reg[15: 0] <= WDATA[15: 8] | DATA1_S[15: 8]; if(BE[2]) data1_reg[23:16] <= WDATA[23:16] | DATA1_S[23:16]; if(BE[3]) data1_reg[31:24] <= WDATA[31:24] | DATA1_S[31:24]; end else begin data1_reg[31:0] <=
((DATA1_S[31:0] | DATA1_C[31:0]) != 32''d0)?( (data1_reg[31:0] & ~DATA1_C[31:0]) | DATA1_S[31:0]): data1_reg[31:0]; end end end end // Register 2 reg [31:0] data2_reg; always @(posedge CLK or negedge RST_N) begin if(!RST_N) begin data2_reg[31:0] <= 32''d0; end else begin if( (ADRS[31:4] == BASE_ADRS[31:4]) && (ADRS[3:2] == 2''d2)) begin if(WE) begin if(BE[0]) data2_reg[ 7: 0] <= WDATA[ 7: 0] | DATA2_S[ 7: 0]; if(BE[1]) data2_reg[15: 0] <= WDATA[15: 8] | DATA2_S[15: 8]; if(BE[2]) data2_reg[23:16] <= WDATA[23:16] | DATA2_S[23:16]; if(BE[3]) data2_reg[31:24] <= WDATA[31:24] | DATA2_S[31:24]; end else begin data2_reg[31:0] <=
((DATA2_S[31:0] | DATA2_C[31:0]) != 32''d0)?( (data2_reg[31:0] & ~DATA2_C[31:0]) | DATA2_S[31:0]): data2_reg[31:0]; end end end end // Register 3 reg [31:0] data3_reg; always @(posedge CLK or negedge RST_N) begin if(!RST_N) begin data3_reg[31:0] <= 32''d0; end else begin if( (ADRS[31:4] == BASE_ADRS[31:4]) && (ADRS[3:2] == 2''d3)) begin if(WE) begin if(BE[0]) data3_reg[ 7: 0] <= WDATA[ 7: 0] | DATA3_S[ 7: 0]; if(BE[1]) data3_reg[15: 0] <= WDATA[15: 8] | DATA3_S[15: 8]; if(BE[2]) data3_reg[23:16] <= WDATA[23:16] | DATA3_S[23:16]; if(BE[3]) data3_reg[31:24] <= WDATA[31:24] | DATA3_S[31:24]; end else begin data3_reg[31:0] <=
((DATA3_S[31:0] | DATA3_C[31:0]) != 32''d0)?( (data3_reg[31:0] & ~DATA3_C[31:0]) | DATA3_S[31:0]): data3_reg[31:0]; end end end end assign RDATA[31:0] = ((ADRS[31:4] == BASE_ADRS[31:4]) && (ADRS[3:2] == 2''d0))?(data0_reg[31:0] | DATA0_I[31:0]):32''d0) | ((ADRS[31:4] == BASE_ADRS[31:4]) && (ADRS[3:2] == 2''d1))?(data1_reg[31:0] | DATA1_I[31:0]):32''d0) | ((ADRS[31:4] == BASE_ADRS[31:4]) && (ADRS[3:2] == 2''d2))?(data2_reg[31:0] | DATA2_I[31:0]):32''d0) | ((ADRS[31:4] == BASE_ADRS[31:4]) && (ADRS[3:2] == 2''d3))?(data3_reg[31:0] | DATA3_I[31:0]):32''d0), assign DATA0_O[31:0] = data0_reg[31:0]; assign DATA1_O[31:0] = data1_reg[31:0]; assign DATA2_O[31:0] = data2_reg[31:0]; assign DATA3_O[31:0] = data3_reg[31:0]; end module;

まだ、シミュレーションしてないので、仕様を満足してるかどうかわからんが・・・