目次

データセレクタ設計開発

 データセレクタを、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は、':'で固定。
  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をデータ出力とセレクタ入力に使います。

 ポートBをデータ入力で使います。

 動作は、ポート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)


目次

inserted by FC2 system