目次
前
次
データセレクタ設計開発
データセレクタを、ROMの2732を利用して実現します。
ピンアサインは、以下。
出力の1ビットは、SEL_A、SEL_Bの組み合わせで
ひとつ選択してROMのデータとします。
配列を用意して、2ビットのデータを格納します。
for ( sel = 0 ; sel < 4 ; sel++ ) {
# upper
for ( y = 0 ; y < 16 ; y++ ) {
# lower
for ( x = 0 ; x < 16 ; x++ ) {
# address
adr = (((sel << 4) | y) << 4) | x ;
# low
low = (x >> sel) & 1 ;
# high
high = (y >> sel) & 1 ;
# result
rom[adr] = (high << 1) | low ;
}
}
}
Tcl/Tkでフルアダーを実現するROMの内容を生成します。
#! /usr/bin/tcl
for {set sel 0} {$sel < 4} {incr sel} {
# upper
for {set y 0} {$y < 16} {incr y} {
# lower
for {set x 0} {$x < 16} {incr x} {
# calculate address
set adr [expr ((($sel << 4) | $y) << 4) | $x]
# low
set low [expr ($x >> $sel) & 1]
# high
set high [expr ($y >> $sel) & 1]
# store
set rom($adr) [expr ($high << 1) | $low]
}
}
}
set tmp ""
for {set i 0} {$i < 1024} {incr i} {
# get
set tmp "$tmp[format "%02X" $rom($i)]"
# show
if { [expr $i % 16] == 15 } {
puts $tmp
set tmp ""
}
}
テキストファイルに保存すると、以下。
00010001000100010001000100010001
02030203020302030203020302030203
00010001000100010001000100010001
02030203020302030203020302030203
00010001000100010001000100010001
02030203020302030203020302030203
00010001000100010001000100010001
02030203020302030203020302030203
00010001000100010001000100010001
02030203020302030203020302030203
00010001000100010001000100010001
02030203020302030203020302030203
00010001000100010001000100010001
02030203020302030203020302030203
00010001000100010001000100010001
02030203020302030203020302030203
00000101000001010000010100000101
00000101000001010000010100000101
02020303020203030202030302020303
02020303020203030202030302020303
00000101000001010000010100000101
00000101000001010000010100000101
02020303020203030202030302020303
02020303020203030202030302020303
00000101000001010000010100000101
00000101000001010000010100000101
02020303020203030202030302020303
02020303020203030202030302020303
00000101000001010000010100000101
00000101000001010000010100000101
02020303020203030202030302020303
02020303020203030202030302020303
00000000010101010000000001010101
00000000010101010000000001010101
00000000010101010000000001010101
00000000010101010000000001010101
02020202030303030202020203030303
02020202030303030202020203030303
02020202030303030202020203030303
02020202030303030202020203030303
00000000010101010000000001010101
00000000010101010000000001010101
00000000010101010000000001010101
00000000010101010000000001010101
02020202030303030202020203030303
02020202030303030202020203030303
02020202030303030202020203030303
02020202030303030202020203030303
00000000000000000101010101010101
00000000000000000101010101010101
00000000000000000101010101010101
00000000000000000101010101010101
00000000000000000101010101010101
00000000000000000101010101010101
00000000000000000101010101010101
00000000000000000101010101010101
02020202020202020303030303030303
02020202020202020303030303030303
02020202020202020303030303030303
02020202020202020303030303030303
02020202020202020303030303030303
02020202020202020303030303030303
02020202020202020303030303030303
02020202020202020303030303030303
ROMライターは、HEXファイル形式かSレコード形式で
なければ、受け付けないので、HEXファイル形式に
します。
HEXファイル形式にするため、ヘッダーとフッターを
各行に付加します。
ヘッダー
ヘッダーには、次の4項目があります。
- Start Code(1byte)
- Byte Count(2byte)
- Start Address(4byte)
- Recode Type(2byte)
Start Codeは、':'で固定。
Byte Countは、ヘッダーに含まれないデータ数を指定。
Start Addressは、行データをどこから格納し始めるか指定。
Recode Typeは、データ行であれば、"00"で固定。
Byte Count、Start Addressは、1行のデータ数が
固定であれば、計算が楽になります。
上のデータであれば、Byte Countは、16進数で10
Start Addressは16の倍数になるので、0000、0010
0020と変化させれば充分です。
フッター
フッターは、チェックサムになります。
チェックサムは、Start Codeを除いたByte Count
からデータの最後まで16進数2けたで加算します。
総計を16進数にして、下2けたを2の補数にして
チェックサムとします。
ヘッダーとフッターを付加するAWKスクリプトを
作成してみました。
#
function s2v(x) {
#default
result = 0
#
if ( x == "1" ) { result = 1 }
if ( x == "2" ) { result = 2 }
if ( x == "3" ) { result = 3 }
if ( x == "4" ) { result = 4 }
if ( x == "5" ) { result = 5 }
if ( x == "6" ) { result = 6 }
if ( x == "7" ) { result = 7 }
if ( x == "8" ) { result = 8 }
if ( x == "9" ) { result = 9 }
if ( x == "A" ) { result = 10 }
if ( x == "B" ) { result = 11 }
if ( x == "C" ) { result = 12 }
if ( x == "D" ) { result = 13 }
if ( x == "E" ) { result = 14 }
if ( x == "F" ) { result = 15 }
return result
}
#
function s2d(x) {
# default
result = 0
# upper
dh = s2v(substr(x,1,1))
# lower
dl = s2v(substr(x,2,1))
# judge
result = dh * 16 + dl
return result
}
# bit inverse
function xinverse(x) {
# default
result = 0
# judge
if ( x == 0 ) { result = 1 }
return result
}
# 1's compliment
function bnot(x) {
# copy
tmpx = x
# separate
x0 = int( tmpx % 2 ) ; tmpx = tmpx / 2 ;
x1 = int( tmpx % 2 ) ; tmpx = tmpx / 2 ;
x2 = int( tmpx % 2 ) ; tmpx = tmpx / 2 ;
x3 = int( tmpx % 2 ) ; tmpx = tmpx / 2 ;
x4 = int( tmpx % 2 ) ; tmpx = tmpx / 2 ;
x5 = int( tmpx % 2 ) ; tmpx = tmpx / 2 ;
x6 = int( tmpx % 2 ) ; tmpx = tmpx / 2 ;
x7 = int( tmpx % 2 ) ;
# inverse
x0 = xinverse(x0) ; x1 = xinverse(x1)
x2 = xinverse(x2) ; x3 = xinverse(x3)
x4 = xinverse(x4) ; x5 = xinverse(x5)
x6 = xinverse(x6) ; x7 = xinverse(x7)
# calculate
result = 0 ;
result = result * 2 + x7 ; result = result * 2 + x6
result = result * 2 + x5 ; result = result * 2 + x4
result = result * 2 + x3 ; result = result * 2 + x2
result = result * 2 + x1 ; result = result * 2 + x0
return result
}
{
# get 16 bytes data
dats = $1
# calculate data
sum = 0
for ( i = 0 ; i < 16 ; i++ ) {
stmp = substr(dats,2*i+1,2)
sum += s2d( stmp )
}
# generate entry address
xadr = 16 * (NR-1)
xadrh = xadr / 256
xadrl = xadr % 256
# data count
sum += 16
# address high
sum += xadrh
# address low
sum += xadrl
# get 8 bits
sum %= 256
# 2's complement
sum = bnot(sum)+1
# get 8 bits
sum %= 256
# show
printf(":10%04x00%s%02X\n",xadr,dats,sum)
}
END {
printf(":00000001FF\n")
}
このスクリプトで、HEXファイルを生成します。
gawk -f mksel.awk dsel.txt > dsel.hex
AWKには、ビット演算がありません。
数値を8ビットに分割し、各ビットを反転します。
その値を加算して数値全体のビット反転にします。
HEXファイルの内容は、以下。
:1000000000010001000100010001000100010001E8
:1000100002030203020302030203020302030203B8
:1000200000010001000100010001000100010001C8
:100030000203020302030203020302030203020398
:1000400000010001000100010001000100010001A8
:100050000203020302030203020302030203020378
:100060000001000100010001000100010001000188
:100070000203020302030203020302030203020358
:100080000001000100010001000100010001000168
:100090000203020302030203020302030203020338
:1000a0000001000100010001000100010001000148
:1000b0000203020302030203020302030203020318
:1000c0000001000100010001000100010001000128
:1000d00002030203020302030203020302030203F8
:1000e0000001000100010001000100010001000108
:1000f00002030203020302030203020302030203D8
:1001000000000101000001010000010100000101E7
:1001100000000101000001010000010100000101D7
:1001200002020303020203030202030302020303A7
:100130000202030302020303020203030202030397
:1001400000000101000001010000010100000101A7
:100150000000010100000101000001010000010197
:100160000202030302020303020203030202030367
:100170000202030302020303020203030202030357
:100180000000010100000101000001010000010167
:100190000000010100000101000001010000010157
:1001a0000202030302020303020203030202030327
:1001b0000202030302020303020203030202030317
:1001c0000000010100000101000001010000010127
:1001d0000000010100000101000001010000010117
:1001e00002020303020203030202030302020303E7
:1001f00002020303020203030202030302020303D7
:1002000000000000010101010000000001010101E6
:1002100000000000010101010000000001010101D6
:1002200000000000010101010000000001010101C6
:1002300000000000010101010000000001010101B6
:100240000202020203030303020202020303030386
:100250000202020203030303020202020303030376
:100260000202020203030303020202020303030366
:100270000202020203030303020202020303030356
:100280000000000001010101000000000101010166
:100290000000000001010101000000000101010156
:1002a0000000000001010101000000000101010146
:1002b0000000000001010101000000000101010136
:1002c0000202020203030303020202020303030306
:1002d00002020202030303030202020203030303F6
:1002e00002020202030303030202020203030303E6
:1002f00002020202030303030202020203030303D6
:1003000000000000000000000101010101010101E5
:1003100000000000000000000101010101010101D5
:1003200000000000000000000101010101010101C5
:1003300000000000000000000101010101010101B5
:1003400000000000000000000101010101010101A5
:100350000000000000000000010101010101010195
:100360000000000000000000010101010101010185
:100370000000000000000000010101010101010175
:100380000202020202020202030303030303030345
:100390000202020202020202030303030303030335
:1003a0000202020202020202030303030303030325
:1003b0000202020202020202030303030303030315
:1003c0000202020202020202030303030303030305
:1003d00002020202020202020303030303030303F5
:1003e00002020202020202020303030303030303E5
:1003f00002020202020202020303030303030303D5
:00000001FF
4入力1出力のセレクタを2回路マイコンの中に
入れることができます。
PIC16F84にて、データセレクタを実現できました。
ポートAをデータ出力とセレクタ入力に使います。
- PORTA_4(input)
- PORTA_3(input) SEL_B
- PORTA_2(input) SEL_A
- PORTA_1(output) upper
- PORTA_0(output) lower
ポートBをデータ入力で使います。
- PORTB_7 (input) D(upper)
- PORTB_6 (input) C(upper)
- PORTB_5 (input) B(upper)
- PORTB_4 (input) A(upper)
- PORTB_3 (input) D(lower)
- PORTB_2 (input) C(lower)
- PORTB_1 (input) B(lower)
- PORTB_0 (input) A(lower)
動作は、ポートA、ポートBの値を入力し
指定シフト数でポートBの値から1ビット
を生成します。
ソースコードにまとめると、以下。
/* redefine data */
typedef unsigned char UBYTE ;
#define OFF 0
#define ON OFF+1
#define MASK0F 0x0f
#define MASKF0 0xf0
volatile UBYTE xsel ;
volatile UBYTE xdat ;
volatile UBYTE ydat ;
volatile UBYTE dl ;
volatile UBYTE dh ;
volatile UBYTE xout ;
volatile UBYTE xpre ;
/* function prototype */
void init_usr(void);
UBYTE get_sel(void);
UBYTE get_dat(UBYTE which);
UBYTE get_bit(UBYTE xd,UBYTE xs);
void main(void)
{
/* user initialize */
init_usr();
/* endless loop */
while ( ON ) {
/* get selector */
xsel = get_sel() ;
/* get data */
xdat = get_dat(OFF) ;
ydat = get_dat(ON) ;
/* generate 1 bit data */
dl = get_bit(xdat,xsel) ;
dh = get_bit(ydat,xsel) ;
/* concanate */
xout = (dh << 1) | dl ;
/* impress */
if ( xout != xpre ) { PORTA = xout ; }
/* update */
xpre = xout ;
}
}
/* define function body */
void init_usr(void)
{
/* I/O initial state */
PORTA = 0x00 ;
PORTB = 0x00 ;
/* I/O direction */
TRISA = 0x0c ;
TRISB = 0xff ;
/* others */
xpre = 0 ;
xout = 0 ;
}
UBYTE get_sel(void)
{
UBYTE tmp ;
/* in */
tmp = PORTA ;
/* shift */
tmp >>= 2 ;
/* mask */
tmp &= 3 ;
return tmp ;
}
UBYTE get_dat(UBYTE which)
{
UBYTE tmp ;
/* in */
tmp = PORTB ;
/* shift */
if ( which == ON ) { tmp >>= 4 ; }
/* mask */
tmp &= MASK0F ;
return tmp ;
}
UBYTE get_bit(UBYTE xd,UBYTE xs)
{
UBYTE tmp ;
/* shift */
tmp = (xd >> xs) ;
/* generate 1 bit */
tmp &= ON ;
return tmp ;
}
プログラムが設計通りに動いているのかを
テストするために、与える10ビットデータ
と期待値をPythonスクリプトで生成しました。
alist = [1,2,4,8,16,32,64,128]
slist = [0,1,2,3]
for e in alist :
# generate input nibble
dh = (e >> 4) & 15
dl = e & 15
for i in slist :
# get target bit with selector
hh = (dh >> i) & 1
ll = (dl >> i) & 1
# show
print 'upper=',dh,'lower=',dl,'(sel)',i,'=>',hh,',',ll
print '------------------------------------'
スクリプトを動かすと、以下のように入力値、セレクタの値で
出力がどうなるかを表示します。
upper= 0 lower= 1 (sel) 0 => 0 , 1
upper= 0 lower= 1 (sel) 1 => 0 , 0
upper= 0 lower= 1 (sel) 2 => 0 , 0
upper= 0 lower= 1 (sel) 3 => 0 , 0
------------------------------------
upper= 0 lower= 2 (sel) 0 => 0 , 0
upper= 0 lower= 2 (sel) 1 => 0 , 1
upper= 0 lower= 2 (sel) 2 => 0 , 0
upper= 0 lower= 2 (sel) 3 => 0 , 0
------------------------------------
upper= 0 lower= 4 (sel) 0 => 0 , 0
upper= 0 lower= 4 (sel) 1 => 0 , 0
upper= 0 lower= 4 (sel) 2 => 0 , 1
upper= 0 lower= 4 (sel) 3 => 0 , 0
------------------------------------
upper= 0 lower= 8 (sel) 0 => 0 , 0
upper= 0 lower= 8 (sel) 1 => 0 , 0
upper= 0 lower= 8 (sel) 2 => 0 , 0
upper= 0 lower= 8 (sel) 3 => 0 , 1
------------------------------------
upper= 1 lower= 0 (sel) 0 => 1 , 0
upper= 1 lower= 0 (sel) 1 => 0 , 0
upper= 1 lower= 0 (sel) 2 => 0 , 0
upper= 1 lower= 0 (sel) 3 => 0 , 0
------------------------------------
upper= 2 lower= 0 (sel) 0 => 0 , 0
upper= 2 lower= 0 (sel) 1 => 1 , 0
upper= 2 lower= 0 (sel) 2 => 0 , 0
upper= 2 lower= 0 (sel) 3 => 0 , 0
------------------------------------
upper= 4 lower= 0 (sel) 0 => 0 , 0
upper= 4 lower= 0 (sel) 1 => 0 , 0
upper= 4 lower= 0 (sel) 2 => 1 , 0
upper= 4 lower= 0 (sel) 3 => 0 , 0
------------------------------------
upper= 8 lower= 0 (sel) 0 => 0 , 0
upper= 8 lower= 0 (sel) 1 => 0 , 0
upper= 8 lower= 0 (sel) 2 => 0 , 0
upper= 8 lower= 0 (sel) 3 => 1 , 0
------------------------------------
入力データを、1、2、4、8と変化させて
セレクタ値で、どのビットが出力されるかを
見ています。
上位では、1、2、4、8を4ビット左にシフトし
16、32、64、128としました。
1、2、4、8の組み合わせがわかれば、4ビットが
すべてゼロにならない限り、扱えるビットの組合せ
を網羅できます。
入力値とセレクタを4ビットx2と2ビット構成で
置換すると、以下。
upper= 0000 lower= 0001 (sel) 00 => 0 , 1
upper= 0000 lower= 0001 (sel) 01 => 0 , 0
upper= 0000 lower= 0001 (sel) 10 => 0 , 0
upper= 0000 lower= 0001 (sel) 11 => 0 , 0
------------------------------------------
upper= 0000 lower= 0010 (sel) 00 => 0 , 0
upper= 0000 lower= 0010 (sel) 01 => 0 , 1
upper= 0000 lower= 0010 (sel) 10 => 0 , 0
upper= 0000 lower= 0010 (sel) 11 => 0 , 0
------------------------------------------
upper= 0000 lower= 0100 (sel) 00 => 0 , 0
upper= 0000 lower= 0100 (sel) 01 => 0 , 0
upper= 0000 lower= 0100 (sel) 10 => 0 , 1
upper= 0000 lower= 0100 (sel) 11 => 0 , 0
------------------------------------------
upper= 0000 lower= 1000 (sel) 00 => 0 , 0
upper= 0000 lower= 1000 (sel) 01 => 0 , 0
upper= 0000 lower= 1000 (sel) 10 => 0 , 0
upper= 0000 lower= 1000 (sel) 11 => 0 , 1
------------------------------------------
upper= 0001 lower= 0000 (sel) 00 => 1 , 0
upper= 0001 lower= 0000 (sel) 01 => 0 , 0
upper= 0001 lower= 0000 (sel) 10 => 0 , 0
upper= 0001 lower= 0000 (sel) 11 => 0 , 0
------------------------------------------
upper= 0010 lower= 0000 (sel) 00 => 0 , 0
upper= 0010 lower= 0000 (sel) 01 => 1 , 0
upper= 0010 lower= 0000 (sel) 10 => 0 , 0
upper= 0010 lower= 0000 (sel) 11 => 0 , 0
------------------------------------------
upper= 0100 lower= 0000 (sel) 00 => 0 , 0
upper= 0100 lower= 0000 (sel) 01 => 0 , 0
upper= 0100 lower= 0000 (sel) 10 => 1 , 0
upper= 0100 lower= 0000 (sel) 11 => 0 , 0
------------------------------------------
upper= 1000 lower= 0000 (sel) 00 => 0 , 0
upper= 1000 lower= 0000 (sel) 01 => 0 , 0
upper= 1000 lower= 0000 (sel) 10 => 0 , 0
upper= 1000 lower= 0000 (sel) 11 => 1 , 0
------------------------------------------
0から255までを扱うようにするには、リストの
要素数を増やすだけで対応できます。
alist = range(0,256)
目次
前
次