Dec 142012
 
Pinterest

며칠 전부터 크롬 브라우저를 열고 스크롤만 조금 하려고 하면 블루스크린이 떠서 미추어버리는줄 알았다. 일시적인 현상이겠거니… 했는데 이건 뭐 일을 못할 정도(일의 대부분이 인터넷 검색 없이 되질 않으니). 작정하고 원인이 뭔가 찾아봤더니 멀웨어;;;

카스퍼스키에서 제공한 TDSSKiller로 스캔했더니 위험하다는 멀웨어 하나를 잡았는데, 처리한 후에 리부팅하고 스캔했더니 없어졌다. 이후에는 문제 없음.

아래 cnet에서 다운받아서 업데이트 한 후 스캔했었음.

비슷한 문제로 고생하는 분들 있을까 싶어 기록.
http://download.cnet.com/Kaspersky-TDSSKiller/3000-2239_4-75722087.html

Pinterest

Dec 102012
 
Pinterest

기억력이 붕어라 기록

 

HDL (Hardware Description Language)를 하다보면 어쩔 수 없이 inout 포트를 써야할 경우가 있다.

내 경우에는 외부에 flash memory를 콘트롤 해야하는데 flash memory의 입출력 핀 가운데 address/command 입력핀과 data 입출력핀이 inout port로 되어 있다. 이 말인즉슨, 플래시 메모리에서 값을 읽을 때, 특정 버스에 주소값이나 명령어(자세한 것은 nand flash memory 데이터시트를 참고)를 입력하고 바로 그 버스에서 값을 읽는다는 뜻. 포트가 입력으로도, 출력으로도 쓰인다.

이런 경우를 처음 접하면 입력 포트 따로, 출력 포트 따로 있는 경우보다 쬐끔 더 짜증이 난다.

시뮬레이션에서 기능 검증 등을 하려고 테스트벤치를 작성할 때도 마찬가지.

그래서 정답은 아닐지도 모르지만 간단하게 본인이 하는 방법을 기록.

일단 inout 포트를 쓰는 모듈의 일부를 가져와보면 아래와 같다.

output [7:0] DataOut;
inout wire [7:0] IO;
reg [7:0] Buf; //temp storage for IO

//if IO_SEL is high, IO is used for OUTPUT
//else IO is used for INPUT…in this case, input IO value will be transfered to specified output port or reg assigned temporary variable.
assign IO = (IO_SEL?Buf:8’hzz); //1st assign
assign DataOut = (IO_SEL?8’hzz:IO); //2nd assign

코드 해석을 해보면, IO가 inout으로 선언되어 있다. 이 IO는 IO를 쓰는 모듈에서 IO_SEL 신호에 따라 입력으로도, 출력으로도 쓸 수 있다. reg로 선언된 Buf에 출력할 값을 쓰면 assign 문에 의해 IO_SEL이 high냐 low냐에 따라 IO는 입력한 Buf의 값이 뜰 수도, 하이 임피던스가 될 수도 있다. 현재 로직상 IO_SEL이 high일 경우 IO를 ouput으로 쓰고(즉 flash memory로 값을 IO버스에 올려 보내고) low일 경우 input으로(즉 flash memory에서 보낸 값을 IO에서 읽어오는 용도) 썼다. 이것은 코드 작성자 마음.

1st assign을 보면 IO_SEL이 high면 Buf의 값을 IO에 넣고(결국 이 값은 모듈 밖에서 읽어갈 수 있을 것이다) low면 하이임피던스로 냅두는 것을 확인할 수 있다.

2nd assign을 보면 IO_SEL이 low면 IO의 버스값을 DataOut이라는 output 포트에 연결한다. 여기서는 DataOut에 바로 연결해서 다른 모듈로 전달하고 있지만 이 값을 모듈 내부에서 쓴다면 reg로 선언해서 할당하거나 flip-flop에 값을 쓰면 될 것이다.

위의 코드를 품고있는 모듈은 IO를 출력으로 쓰고 싶으면(위의 예에서는 flash memory로 특정 값을 보내고 싶으면) IO_SEL을 high로, 즉 IO_SEL = 1’b1로 설정한 후 Buf에 값을 넣을 때 IO_SEL이 high인지 확인해서 넣으면 된다. 출력으로 안 쓸 때는 Buf를 하이임피던스로 놓는다. 코드로 나타내면

// 어딘가에서 IO_SEL을 high로 설정

if(IO_SEL == 1’b1) begin
  Buf <= 8’b0000_0000;
  // … 이하 하고 싶은 일
end

 

IO를 입력으로 쓰고 싶으면(위의 예에서는 flash memory로부터 값을 읽어들이고 싶으면) 적당한 타이밍에 IO_SEL을 low로 설정하면 된다.

이런 모듈의 코드가 있을 때 테스트벤치에서 IO에 임의의 값을 써서 위의 모듈이 예상한 타이밍에 적절한 동작을 하는지 검증하고 싶다면 어떻게 해야할까? (거듭 말하지만, 이 방법이 정답이 아닐 수 있다-_-;; 어쨌든 필자가 원하는 테스트를 할 수 있는 코드일 뿐)

테스트벤치를 위한 코드에서 아래와 같은 코드를 썼다.

wire [7:0] f_IO;
wire f_IO_SEL;
reg [7:0] rIO;
integer mem_idx;
integer i, x_clk;
parameter DEPTH = 1024;
parameter EVERY_X_CLK = 1000;
reg [7:0] memory [DEPTH-1:0];

initial begin
  mem_idx = DEPTH – 1;
  x_clk = EVERY_X_CLOCK;
  for( i = 0 ; i < DEPTH ; i = i + 1) begin
    memory[i] = i % 256;
  end
end

always @(posedge clk) begin
  if( x_clk == 0) begin
    x_clk <= EVERY_X_CLOCK;
    rIO <= memory[mem_idx];
    if(mem_idx == 0) begin
      mem_idx <= DEPTH – 1;
    end else begin
      mem_idx <= mem_idx – 1’b1;
    end
  end else begin
    x_clk <= x_clk – 1;
  end
end

assign f_IO = (f_IO_SEL?8’hzz:rIO);

//instance
module_name U_MODULE_NAME(
  .i_sys_clk ( clk ),
  .i_por ( rst_b ),
  // 중간의 연결은 생략
  .io_IO ( f_IO ),
  .o_IO_SEL ( f_IO_SEL),
  // 이후의 연결도 생략
);

코드를 설명하자면 별거 아니고

initial begin 쪽에서 memory에 적당한 값[1]을 넣어주고

매 EVERY_X_CLOCK 번째 clk마다

rIO = memory[mem_idx];

를 이용하여 원하는 값(memory)을 reg로 선언한 임시 값(rIO)에 쓰면

아래 assign문을 이용해

assign f_IO = (f_IO_SEL?8’hzz:rIO);

모듈로부터 연결된 f_IO_SEL 값을 보고 이것이 high면 모듈에서 output으로 쓰는 것이므로 테스트벤치 입장에서는 입력[2]이 될 것이고, 모듈 입장에서 input으로 쓰고 싶으면  f_IO_SEL이 low일 것이므로 이 경우에는 모듈입장에서 보면 테스트벤치에서 마치 rIO에 쓴 값을 외부[3]에서 모듈로 던져준 것처럼 보일 것이다.

 

더 좋은 깔끔한 방법이 있는지는 모르겠다. 어쨌든 모듈에서 만들어 IO에 올린 출력값을 테스트벤치에서 확인하고, 테스트벤치에서 만든 임의의 값을 모듈에 입력하여 모듈의 동작을 확인할 수 있는 소기의 목적을 달성하였기 때문에 더이상의 설명은 생략…이 아니라 깜이 안 되니 할 수도 없;;;;

 

 

 

Footnotes    (↵ returns to text)
  1.  뭐, 이것은 적당히 data 파일 만들어서 $readmemb 같은 것으로 읽어서 처리하면 딱 원하는 값을 테스트 할 수 있을 것이다.
  2.  지금 예에서는 모듈에서 address나 command를 날린 것을 테스트벤치에서 확인할 수 있겠지용
  3.  지금 예에서는 플래시 메모리
Pinterest