リスト1 デコーダの例
function check_int;
input [2:0] opecode;
case (opecode) // synopsys parallel_case
2'b00: check_int = 1'b1;
2'b01: check_int = 1'b0;
2'b10: check_int = 1'b0;
2'b11: check_int = 1'b0;
endcase
endfunction
他の命令カテゴリについても同様に記述すれば良いが、
個別に記述していると嵩張って収拾がつかなくなるし、
論理合成ツールが最適化を行うにも不都合である。
そこで、opecode によって一意に定まる条件については
まとめてデコーダを作成する。
残念なことに verilog-HDL の function は多出力ができないので、
リスト2 のように、信号のベクタを作って
function の出力を一つにまとめる。
リスト2 ベクトルを出力するデコーダ
wire [W_DOPC -1: 0] dopc; // decoded opecode
assign dopc = decode_ins(inst_i[W_INST -2: P_RD]);
assign inte = dopc[W_DOPC -1]; // integer
assign logic = dopc[W_DOPC -2]; // logic
assign shift = dopc[W_DOPC -3]; // shift
assign ld = dopc[W_DOPC -4]; // load
assign st = dopc[W_DOPC -5]; // store
assign br = dopc[W_DOPC -6]; // branch
assign imme16 = dopc[W_DOPC -7]; // immediate 16
assign rsv_o = dopc[W_DOPC -8]; // reserv
assign und = dopc[W_DOPC -9]; // undefined
// **************** decode opecode *****************
// dopc = {inte, logic, shift, ls, br, imm16, rsv, und}
// integer, logic, shift, load, store, branch, immediate, reserved, undefined
function [W_DOPC -1: 0] decode_ins;
input [6: 0] opcode;
case (opecode) // synopsys parallel_case
// integer reg - reg
7'b0000_000: decode_ins = 11'b100000_0_1_0;
7'b0000_001: decode_ins = 11'b100000_0_1_0;
7'b0000_010: decode_ins = 11'b100000_0_1_0;
7'b0000_011: decode_ins = 11'b100000_0_1_0;
7'b0000_100: decode_ins = 11'b100000_0_0_0;
7'b0000_101: decode_ins = 11'b100000_0_1_0;
7'b0000_110: decode_ins = 11'b100000_0_1_0;
7'b0000_111: decode_ins = 11'b100000_0_1_0;
(パラメータ定義の例) parameter W_OPR = 32;
同様に W_RD はレジスタ番号を示す値を入れる大きさなので 4、 REG_S はレジスタの数で 16、といった具合に記述したファイルを 別途用意し各々のモジュールの中で読み込ませる。 このようにすれば、プロジェクト全体で定数の定義をまとめて扱うことができる。
リスト3 レジスタセル
module register_cell(clk, rst,
data_i,
data_o,
w_reserve_i,
w_reserve_o,
wb_i
);
input clk, rst;
input [W_OPR -1: 0] data_i; // data for write
output [W_OPR -1: 0] data_o; // data output
input w_reserve_i; // write reserve
output w_reserve_o; // write reserve out
input wb_i; // write back
reg [W_OPR-1: 0] data_cell; // register cell
reg w_res; // write reserve bit
assign data_o = data_cell;
assign w_reserved = w_res;
always @(posedge clk or negedge rst)
begin
if (~rst)
begin
w_res <= 1'b0;
data_cell <= 32'b0;
end
else
begin
if (w_reserve_i) // write reserve
begin
w_res <= 1'b1;
end
else if (wb_i) // write back
begin
w_res <= 1'b0;
end
if (wb_i)
begin
data_cell <= data_i;
end
end // else: !if(~rst)
end // always @ (posedge clk or negedge rst)
endmodule // register_cell
リスト4 汎用レジスタファイルモジュール
module g_register(clk, rst,
w_reserv_i,
r0_i,
r1_i,
r_opr0_o,
r_opr1_o,
reserved_o,
wb_i,
wb_r_i,
result_i);
`include "../include/params.v"
input clk, rst;
input w_reserv_i;
input [W_RD -1: 0] r0_i; // register No. as opr0 & write_reservation
input [W_RD -1: 0] r1_i; // register No. as opr1
output [W_OPR -1: 0] r_opr0_o; // operand0
output [W_OPR -1: 0] r_opr1_o; // operand1
output reserved_o; // destination is reserved
input wb_i; // write back
input [W_RD -1: 0] wb_r_i; // write back register
input [W_OPR -1: 0] result_i; // write back data
wire [REG_S -1: 0] w_reserve;
wire [REG_S -1: 0] w_reserved;
wire [REG_S -1: 0] wb_r;
wire [W_OPR -1: 0] data0;
wire [W_OPR -1: 0] data1;
// :
// :
// :
wire [W_OPR -1: 0] dataf;
`include "select16.v"
assign r_opr0_o =
select16(r0_i, // register descriptor
data0, data1, data2, data3,
data4, data5, data6, data7,
data8, data9, dataa, datab,
datac, datad, datae, dataf
);
assign r_opr1_o =
select16(r1_i, // register descriptor
data0, data1, data2, data3,
data4, data5, data6, data7,
data8, data9, dataa, datab,
datac, datad, datae, dataf
);
wire [REG_S -1: 0] opr_req0; // operand request vector0
wire [REG_S -1: 0] opr_req1; // operand request vector1
`include "decode16.v"
assign opr_req0 = decode16(r0_i);
assign opr_req1 = decode16(r1_i);
assign w_reserve = opr_req0 & {16{w_reserv_i}};
// if requested register is reserved
assign reserved_o = |((opr_req0 | opr_req1)
& w_reserved);
assign wb_r = decode16(wb_r_i) & {16{wb_i}};
g_reg_cell r0(.clk(clk), .rst(rst),
.data_i(result_i),
.data_o(data0),
.w_reserve_i(w_reserve[0]),
.w_reserve_o(w_reserved[0]),
.wb_r(wb_r[0])
);
g_reg_cell r1(.clk(clk), .rst(rst),
.data_i(result_i),
.data_o(data1),
.w_reserve_i(w_reserve[1]),
.w_reserve_o(w_reserved[1]),
.wb_r(wb_r[1])
);
// :
// :
// :