先日、アキバの書泉ブックタワーで見かけた復刻版です。中が見えなかったんですが、誘われてる気がしたので衝動買しました。結果的には当たりでしたね。
shop.cqpub.co.jp
本書には、「ビット処理システム」(BPU)言うなれば、1bit CPUとも言うべきシーケンサ、コントローラが載ってます。
曰く「小規模なディジタル・システムを設計するとき,データの流れや演算,メモリといった部分は比較的すんなり行っても,全体のコントロール・タイミングを作るのには苦労します.一様な動きならまだしも、複雑に条件がからむ動作は、特に一筋縄ではいきません。ゲートとFFをあちこちに繋いで何度も更新しても、ちゃんと動いてくれないという経験は筆者だけではないと思います。
ランダム・ゲートとFFで順序回路を組んでいたら大変だということで、PLAが出現しました。しかし、市場に出回っているPLAは入出力が少なく、小さなシステムでも数個使用したり、外部にデコーダ、カウンタ、ラッチなどを必要とし、容量を超えたら、お手上げ、というわけで、2~30bitの入力と出力をbit単位で制御出来る、統一手法はないものかと長年考えていました。その結果がここに紹介するビット処理システムです。」
ということで、最小構成と、何種類かの拡張システムが紹介されいます。
基本システムで8bit x 128wordのプログラムROMにつながる7bitカウンタと
フラグと呼ばれるAND項を持ったアキュムレータ、最大64bit入力セレクタ、最大64bitのセレクトラッチを持つシステムで、
オペコードはたったの3種類、入力/出力/ジャンプだけです。
実際の構成をVerilogHDLで書き起こすとこんなカンジ。
//BPU(Bit Processor Unit)
// form 復刻版 ディジタル回路設計ノウハウ【オンデマンド版】CQ出版
// https://shop.cqpub.co.jp/hanbai/books/52/52181.html
//write VerilogHDL 2023-10-28sa
//
`default_nettype none
module BPU
( input wire CLK_H_i
,input wire INIT_L_i
,input wire [31:0] GPIs_i
,output wire[31:0] GPOs_o
) ;
wire[ 4:0] PAs ;
wire IND_H = GPIs_i[ PAs ] ;
wire[ 7:0] MDs ;
wire[ 6:0] MAs ;
wire OUTD_H ;
wire STB_L ;
BPU_CORE
BPU_CORE
( .CLK_H_i ( CLK_H_i )
,.INIT_L_i ( INIT_L_i )
,.IND_H_i ( IND_H )
,.MDs_i ( MDs )
,.MAs_o ( MAs )
,.PAs_o ( PAs )
,.OUTD_H_o ( OUTD_H )
,.STB_L_o ( STB_L )
)
;
reg[31:0]GPOs ;
always@(posedge CLK_H_i or negedge INIT_L_i)
if( ~ INIT_L_i ) GPOs <= 0 ;
else
if( ~ STB_L ) GPOs[ PAs ] <= OUTD_H ;
assign GPOs_o = GPOs ;
BPU_PGMEM
BPU_PGMEM
( .ADRs_i ( MAs )
,.DATs_o ( MDs )
)
;
endmodule
module BPU_CORE
( input wire CLK_H_i
,input wire INIT_L_i
,input wire IND_H_i
,input wire [ 7:0] MDs_i
,output wire[ 6:0] MAs_o
,output wire[ 4:0] PAs_o
,output wire OUTD_H_o
,output wire STB_L_o
) ;
reg[ 6:0] MAs_a ;
reg[ 6:0] MAs ;
reg FLG_a ;
reg FLG ;
wire PP = MDs_i[5] ;
assign OUTD_H_o = PP;
reg STB_L ;
assign STB_L_o = STB_L ;
always@(MAs,MDs_i,FLG,PP,IND_H_i)
begin
MAs_a = MAs + 1 ;
FLG_a = FLG;
STB_L = 1'b1 ;
casex( MDs_i[7:6] )
2'b00: //out cmd
if( ~ FLG ) STB_L = 1'b0 ;
2'b01: //in cmd
if(PP!=IND_H_i) FLG_a = 1'b1 ;
2'b1x: //jp cmd
begin
FLG_a = 1'b0 ;
if(~ FLG) MAs_a = MDs_i[ 6:0] ;
end
endcase
end
always@(posedge CLK_H_i or negedge INIT_L_i)
if( ~ INIT_L_i)
begin FLG <= 1'b0 ;
MAs <= 0 ;
end else
begin
FLG <= FLG_a ;
MAs <= MAs_a ;
end
assign MAs_o = MAs ;
assign PAs_o = MDs_i[ 4:0];
endmodule
module BPU_PGMEM //8bit x 128 word (1024bit)
( input wire [ 6:0] ADRs_i
,output wire[ 7:0] DATs_o
) ;
reg[ 7:0]DATs ;
always@( ADRs_i )
case( ADRs_i )
7'h00: DATs = 8'b00_10_0000 ;
7'h01: DATs = 8'b00_10_0001 ;
7'h02: DATs = 8'b00_10_0010 ;
7'h03: DATs = 8'b00_10_0011 ;
7'h04: DATs = 8'b00_10_0100 ;
7'h05: DATs = 8'b00_10_0101 ;
7'h06: DATs = 8'b00_10_0110 ;
7'h07: DATs = 8'b00_10_0111 ;
7'h08: DATs = 8'b00_10_1000 ;
7'h09: DATs = 8'b00_10_1001 ;
7'h0A: DATs = 8'b00_10_1010 ;
7'h0B: DATs = 8'b00_10_1011 ;
7'h0C: DATs = 8'b00_10_1100 ;
7'h0D: DATs = 8'b00_10_1101 ;
7'h0E: DATs = 8'b00_10_1110 ;
7'h0F: DATs = 8'b00_10_1111 ;
7'h10: DATs = 8'b00_00_0000 ;
7'h11: DATs = 8'b00_00_0001 ;
7'h12: DATs = 8'b00_00_0010 ;
7'h13: DATs = 8'b00_00_0011 ;
7'h14: DATs = 8'b00_00_0100 ;
7'h15: DATs = 8'b00_00_0101 ;
7'h16: DATs = 8'b00_00_0110 ;
7'h17: DATs = 8'b00_00_0111 ;
7'h18: DATs = 8'b00_00_1000 ;
7'h19: DATs = 8'b00_00_1001 ;
7'h1A: DATs = 8'b00_00_1010 ;
7'h1B: DATs = 8'b00_00_1011 ;
7'h1C: DATs = 8'b00_00_1100 ;
7'h1D: DATs = 8'b00_00_1101 ;
7'h1E: DATs = 8'b00_00_1110 ;
7'h1F: DATs = 8'b00_00_1111 ;
7'h20: DATs = 8'b01_00_0000 ;//GPI[0]!=0->F<=1
7'h21: DATs = 8'b10_10_0000 ;//~F?jump $20
7'h22: DATs = 8'b10_00_0000 ;//jp 0
default: DATs = 8'b10_00_0000 ;
endcase
assign DATs_o = DATs ;
endmodule