http://blog.naver.com/PostView.nhn?blogId=hj_veronica&logNo=220541570147&parentCategoryNo=&categoryNo=40&viewDate=&isShowPopularPosts=true&from=search


위의 것을 보고 하자.


ERD 그리는 것은 아래의 사이트나 위의 사이트에서 이걸로 그려라! 하는 프로그램이 있으니 보고 할것.

ERD를 그림으로 그리고 create table A(~~~)를 추출해 내는게 마음편하다.


http://aquerytool.com/    => 이것은 인터넷으로 ERD 그리는 것.

1. 시스템 구조 그리기..




//////////////////////////////////검증 관련//////////////


a. ISIM 시뮬레이션 내부 bit 분석을 통해 동작 검증 (왼쪽 위는 시뮬레이션 결과(run.sh), 오른쪽은 ISIM 내부 bit 확인)


b. FPGA상에서 동작 검증 ( 그림 3개를 통해서, 제일 왼쪽 위는 어떤 레지스터로 프로그램을 만들었는지, 오른쪽 위는 impact랑 minicom 스샷, 왼쪽 아래는 minicom에서 나온 결과 스샷)


//////////////////////////////////성능 관련//////////////


Software/Hardware 암호화의 속도 비교를 통한 성능 확인

NON, Sec, Soft

=> 숫자 only / 영문 포함 / 숫자 영문 섞어서 


(현재 나와있는 )

decode에서 type이 나오고, 여기서 type == SIMD_LDST이면 simd_enable_nxt = 1'd1로 되어 버린다.




그러면 이제 type이 어떻게 결정되는지를 살펴보면, 




instruction을 보고 알 수 있다. 여기서, instruction[27:4]를 보고 type을 결정하게 되는데,




순서가 중요하다고 한다. 그래서 여기서 우리가 쓸 수 있는 instruction은




24'b1101??0?????????101????? : type = SIMD_LDST; 이것을 쓸 수 있을 것 같다. 그래서 이 instruction이 오게 된다면, on, off를 바꿔주는 것이다.




그렇다면 instruction은 어디서 오는지를 살펴봐야 된다.




assign instruction      =         instruction_sel == 2'd0 ? o_read_data               :


                                  instruction_sel == 2'd1 ? saved_current_instruction :


                                                            pre_fetch_instruction     ;


이렇게 되어있으니, 1. o_read_data나 2. saved_current_instruction이나 3. pre_fetch_instruction에서 볼 수 있다.




1. 그러면 o_read_data부터 살펴보면 다음과 같이 나온다.




이것은 always @ ( posedge i_clk )


    if (!i_fetch_stall) 


        begin                                                                                                                 


        o_read_data                 <= i_read_data;


o_simd_read_data    <= i_simd_read_data; //@sungbo


이렇게 되어있는 것으로 보아 stall상태가 아닌 경우에 i_read_data가 들어오는 것이다.




그렇다면 i_read_data는 어디서 오는 것인지를 살펴보면 




input으로 들어오는 것이다. 이것은 fetch.v의 o_read_data에서 나오는 것인데., 




assign o_read_data       = sel_cache  ? cache_read_data : 


                           sel_wb     ? wb_dat32        : //@sungbo


                                        32'he3a00000    ;


이렇게 되어있는 것으로 봐서 A. cache_read_data 혹은 B. wb_dat32 로부터 오는 것임을 알 수 있다.




1-A. 그렇다면 cache_read_data는 어디서 오는 것인지 확인해보면 cache.v에서 o_read_data와 연결이 되어 있는 것을 알 수 있다.




그렇다면 cache.v로 가서 보면 




assign o_read_data      = wb_read_buf_hit                              ? wb_read_buf_data   :


                          i_address[WORD_SEL_MSB:WORD_SEL_LSB] == 2'd0 ? hit_rdata [31:0]   :


                          i_address[WORD_SEL_MSB:WORD_SEL_LSB] == 2'd1 ? hit_rdata [63:32]  :


                          i_address[WORD_SEL_MSB:WORD_SEL_LSB] == 2'd2 ? hit_rdata [95:64]  :


                                                                         hit_rdata [127:96] ;




이렇게 되어있다. 그러면 a. wb_read_buf_data와 b. hit_rdata로 되어있으니 하나씩 살펴보면




1-A-a. wb_read_buf_data는 다음과 같다.


always @ ( posedge i_clk )

    begin

    if ( c_state == CS_FILL1 || c_state == CS_FILL2 || 

         c_state == CS_FILL3 || c_state == CS_FILL4 )

        begin

        if ( !i_wb_stall )

            begin

            wb_read_buf_valid   <= 1'd1;

            wb_read_buf_address <= i_wb_address;

            wb_read_buf_data    <= i_wb_read_data;

            end

        end

    else    

        wb_read_buf_valid   <= 1'd0;

    end


이렇게 되어있다. 그러므로 fill state일 때, i_wb_read_data가 들어오는 것이다. 그렇다면 이것은


input으로 들어오는 것인데, 이것은 fetch.v에서 i_wb_dat와 연결되고


그것은 core에서 input으로 받아서 들어오는 i_wb_dat이다.

1. vmlinux 패치하기(vmlinux - README 참고)

2. 패치한 vmlinux로 원래 있던 initrd-200k-hello-world가 실행이 되는지 확인.

  실행이 되면, 원래있던 hello-world.flt을 사용해서 새로 제작한 initrd로 실행이 되는지 확인.

3. Credit.c 제작하기.

4. Credit.c와 hello-world 폴더에 있는 Makefile, Start.S, section.lds를 사용하여 elf, flt파일 제작.

5. initrd-credit제작해서 보드에서 실행확인.

현재 상태는, 시뮬레이션이 모두 완료된 상태이다.


이제 fpga에 AES module을 추가한 것을 올려야 되는데,


그 전에 변경한 소스가 아닌 원본을 먼저 올려볼 생각이다.


그래서 다시 원본 파일을 불러와서


./run.sh -5 -s hello-world가 잘 돌아가는 것을 확인하였다.

(-s는 spartan6 library를 쓴다는 것이다.)


그리고 ddr3를 Xilinx core generation을 통해 만들어서 넣어주었다.


해당 ddr3는 license때문에 amber에서 추가해 주지 않는다. 그래서 


amber/trunk/hw/vlog/xs_ddr3에서 README.txt를 보고 Coregen으로 


ddr3를 만든 뒤에 써있는 대로 수정을 해 주었다.(해당 파일은 dropbox에)


CentOS 6를 쓸 때에 해주라는 설정은 일단 넘기고 갔고 그 뒤도 넘겼다.

(In order to use Impact on CentOS 6, you need to install a USB driver.

sudo yum install libusb-devel

Then download and make the usb driver from http://rmdir.de/~michael/xilinx/

Once its successfully compiled run setup_pcusb to add the device IDs to the Xilinx installation.


You also need to install the fxload package

sudo rpm -i fxload-2008_10_13-3.el6.i686.rpm

And reboot after installing it.) 

이 부분.....


그리고 bit file을 만들고 아래에 있는 것을 할 예정이다.

(Then power on the SP605 board and connect its USB-JTAG port to your PC.

Then run impact as follows

export LD_PRELOAD=/your-path/libusb-driver.so

impact

Impact should now be able to auto-detect the FPFA card. Right click on the FPGA and select the bitfile to load into it.)


자 일단 여기까지 했으면, 이제 bitfile을 만들 것이다.


그를 위해서 hw/fpga/bin에 들어가서


make new A25=1


이라고 명령어를 입력하면 자동으로 bit 파일을 만들어 준다.


그러면 hw/fpga/bitfiles 폴더에 bit파일이 생성된다.


이제 impact를 켜려면, opt/Xilinx/14.7/ISE_DS/ISE/bin/lin 에 들어가서


./impact를 하면 된다.


그리고 나서 fpga/flash에 있는 readme에 있는 대로 해주었다.

==================readme.txt=======================

Xilinx Flash/PROM - Write bitfile to SPI serial flash

The included file boot-loader-ethmac.mcs is a flash configuration file

for the SPI (serial) flash on the SP605 FPGA development board.

It contains the boot-loader-ethmac design. Here are instructions on how to create an mcs file

and how to load it onto the SP605 board. These instructions are for Xilinx ISE 14.5.



1. Start impact. Select Prepare a PROM file

Step 1. Select Storage Target

SPI Flash -> Configure single FPGA



Step 2. Add Storage Device

64M


Step 3

File Format MCS

Add Non_Configuration Files No


Select the bitfile to write

Would you like to add another device file to Revision:0 ? No


Impact Process->Generate File...

Impact creates an MCS file and says Generate Succeeded.


Then restart impact and select Boundary Scan flow

Right mouse on the FPGA and select Add SPI/BPI Flash

 => 여기서 module windrvr6 is not loaded. please reinstall the cable    라고 뜨면서 driver가 없다고 해서 그것에 대해 찾아보는 중...

http://www.silabs.com/products/interface/Pages/interface-software.aspx#cp210x   여기서 드라이브 설치함

(이것을 위해 자바 깔아야됨

 * default-jdk

 * ecj

 * gcj-4.6-jdk

 * openjdk-6-jdk

 * gcj-4.5-jdk

 * openjdk-7-jdk

)이것들 깔아보자. - sudo apt-get install

==> 그래도 안됨..

일단 sudo apt-get install portmap  을 해줌..

http://ubuntuforums.org/showthread.php?t=1547435&page=3

위의 것을 보고 해당 위치에 깔고 export 해줌.


//위에껀 다 쓸모없고 우클릭해서 일단 bit file을 다시 업로드하면 된다.

Select Attached SPI/BPI dialogue

SPI PROM -> W25Q64FV

Data Width: 1


Then a Flash device appears in the Boundary scan window attached the tje xc6slx45t FPGA.

Right mouse on the Flash and select Program

// 여기서 program 하려면 usb연결이 안된대서 usb 연결을 또 다시 찾고있음.

//http://www.george-smart.co.uk/wiki/Xilinx_JTAG_Linux 일단 이것을 참조하고 initialize chain을 누르면 자동으로 fpga가 뜨게 된다...

This takes a couple of minutes.


To use that image, you need the following switch settings on the SP605 board;

SW1 (the 2-switch block box near the red on/off power switch in the upper right corner of the board)

 M0=on, M1=off

Then press the PROG button just below it to load that bitfile from the SPI flash into the FPGA.


To use the Parallel flash

 M0=off, M1=off



Online tutorial for instructions with pictures -

http://www.digilentinc.com/Data/Documents/Tutorials/MCS%20File%20Creation%20with%20Xilinx%20ISE%20Tutorial.pdf



1. 일단 state = 0일 때, read시에 어떻게 해야 할 것인가?


state == 0일 때, cyc, stb signal이 1로 오면서 read를 요구한다.

이 때, cyc, stb는 같이 1이 되고, ack를 받아서 바로 core쪽으로 주면 안된다.

일단 ack를 받게 되면, core쪽에는 0으로 hold 시켜 놓고, 

ack를 decrypt start signal로 사용하여 decrypt를 진행시킨다.

그리고 decrypt가 끝나면 dec_done signal이 1이 될 것이다.

그러면 이 dec_done signal을 core쪽으로 보내는 ack 신호로 사용하면 된다.

(이거 완료신호 1clk만 1로 주면 되겠지?)


2. state가 1일 때, read를 할 것이다.

이 때도 state = 0일 때와 동일하게 ack를 받으면 core쪽에는 0으로 hold 시켜 놓고

ack를 decrypt start signal로 사용하여 i_wb_dat_i 를 decrypt 시킨다.

그리고 decrypt_done signal이 1이 되는 것을

state를 2로 보내는 signal로 사용하면 된다.


3. state == 2일 때, write를 할 것이다.

state가 2를 encrypt start signal로 사용한다.

그래서 바로 encrypt를 시작한다. ( 1 clk만 되도록 해야됨 )

그리고 encrypt_done signal이 들어오면 stb, cyc, we_o를 1로 준다..

여기서 ack가 들어오면 다시 state를 0으로 보내준다.

1. write에 대해 분석한 것을 바탕으로 모듈을 제작 했는데 안됨


2. 안되서, isim에서 파형을 보려고 했음


3. 아예 프로그램이 돌아가지 않으면 파형이 안나옴


4. 다시 원래 파일을 받아서 그것에서 파형을 봤음


5. 거기서 hello-world.dis 어셈블리어의 순서를 보고, store, load, push, pop등을 찾아 waveform을 확인함.


6. 확인한 결과, 시뮬레이션과 실제로 스파르탄을 써서 할 때에, 사용하는 캐쉬(sram)가 다름....


7. 그래서 현재 메모리에서 read를 해와서 그것을 다시 write하는 방법으로 회귀를 함 그리고 보다가 이상한 것을 발견.


8. 11972.5ns에서 이상한 것을 찾음. write하겠다고 하자마자 바로 ack가 뜸...


9. main_mem와 wishbone_arbiter를 확인해보려고 각각 waveform을 보려고 했는데 segmentation fault가 뜸.


10. 하나하나 올려서 확인해봤는데 ack가 assign으로 연결되어 있어서 그렇다고 생각됨. 그럼 이제 이상한 것이 뭐냐면..


11. 


=============================


state가 0인 상태...

이 상태는 그냥 계속 read만 하고 있는 상태이다.

이 상태에서 cyc, stb, we 가 모두 1이 되면 state를 1로 바꿔준다.


state가 1인 상태...

이 상태에서는 다른 것은 모두 그대로 인데, we만 0으로 바꾸어 준다.

이 상태에서, ack가 1이 되면, state 2로 이동한다.


state가 2인 상태..(read를 해왔고 write를 해야 되는 상태)

이 상태에서는 들어오는 sel을 보고, data를 치환해서 밖으로 내보내준다.

이 상태에서는 we는 1로 넘겨주고 ack가 1이면 state를 0으로 바꿔준다.

캐쉬에 쓰이는 sram이 시뮬레이션 때와 fpga에 올릴 때 다르다는 것을 알게 되어 이것으로 했음.

v1_메모리에서 read하고 write하는 것.tar.gz


일단 캐시로 올리는 부분을 찾아야 되는데, a25_dcache.v에서 아래와 같은 부분이 있음.


generate

    for ( i=0; i<WAYS;i=i+1 ) begin : rams


        // Tag RAMs 

        `ifdef XILINX_SPARTAN6_FPGA

        xs6_sram_256x21_line_en

        `endif


        `ifdef XILINX_VIRTEX6_FPGA

        xv6_sram_256x21_line_en

        `endif


        `ifndef XILINX_FPGA

        generic_sram_line_en 

        `endif


            #(

            .DATA_WIDTH                 ( TAG_WIDTH             ),

            .INITIALIZE_TO_ZERO         ( 1                     ),

            .ADDRESS_WIDTH              ( CACHE_ADDR_WIDTH      ))

        u_tag (

            .i_clk                      ( i_clk                 ),

            .i_write_data               ( tag_wdata             ),

            .i_write_enable             ( tag_wenable_way[i]    ),

            .i_address                  ( tag_address           ),


            .o_read_data                ( tag_rdata_way[i]      )

            );

            

        // Data RAMs 

        `ifdef XILINX_SPARTAN6_FPGA

        xs6_sram_256x128_byte_en

        `endif


        `ifdef XILINX_VIRTEX6_FPGA

        xv6_sram_256x128_byte_en

        `endif


        `ifndef XILINX_FPGA

        generic_sram_byte_en

        `endif


            #(

            .DATA_WIDTH    ( CACHE_LINE_WIDTH) ,

            .ADDRESS_WIDTH ( CACHE_ADDR_WIDTH) )

        u_data (

            .i_clk                      ( i_clk                         ),

            .i_write_data               ( data_wdata                    ),

            .i_write_enable             ( data_wenable_way[i]           ),

            .i_address                  ( data_address                  ),

            .i_byte_enable              ( {CACHE_LINE_WIDTH/8{1'd1}}    ),

            .o_read_data                ( data_rdata_way[i]             )

            );                                                     



        // Per tag-ram write-enable

        assign tag_wenable_way[i]  = tag_wenable && ( select_way[i] || source_sel[C_INIT] );


        // Per data-ram write-enable

        assign data_wenable_way[i] = (source_sel[C_FILL] && select_way[i]) || 

                                     (write_hit && data_hit_way[i] && c_state == CS_IDLE) ||

                                     (consecutive_write && data_hit_way_r[i]);

        // Per data-ram idle_hit flag

        assign data_hit_way[i]     = tag_rdata_way[i][TAG_WIDTH-1] &&                                                  

                                     tag_rdata_way[i][TAG_ADDR_WIDTH-1:0] == i_address[31:TAG_ADDR32_LSB] &&  

                                     c_state == CS_IDLE;                                                               

    end                                                         

endgenerate


=========================================================

여기서 아래의 구문이 128 bits짜리 데이터를 캐쉬에 쓰는 구문임.

            .i_write_data               ( data_wdata                    ),

            .i_write_enable             ( data_wenable_way[i]           ),

            .i_address                  ( data_address                  ),

그렇기 때문에 이 부분에 wiring을 외부로 연결해서 aes 모듈에 연결시켜야됨.

그리고 아래의 byte_enable은 16'hffff이기에, 앞서 살펴봤던 것 같이 모든 데이터를 다 쓴다는 의미로

받아들일 수 있음.


그러면 여기서 한가지 고려해야할 사항이, 

문제 1. data를 쓰고 ack 신호가 오기 전에 다른 data를 쓰라고 바뀌면 어떻게 할 것인가?

=> 그래서 이 문제 해결을 위해서는 queue를 만드는 방법이 제일 좋을 것 같음...


문제 2. write miss가 나면 어떻게 될 것인가? 메모리에서 데이터를 받아오고 다시 하나?

=> 상관 없을 것 같음... 무시 가능할듯.


==================================================================

그러면 해야할 stage로는,


1. 일단 aes 모듈에 wiring을 통해 연결하기


2. write시에는 write 하고 싶다는 신호가 오면


 a. 큐에 데이터가 존재한다면 존재하는 데이터를 메모리로 보내기

 b. 큐에 데이터가 없다면 연결된 wire에서 dcache_diff 신호가 1이 될 때까지 기다리기

(여기서 중요한 것이, 연동이 잘 되어서 항상 큐에 1개만 쌓이게 될 수가 있는데 그렇다면 이렇게 큐를 만들어 줄 필요가 없는 것임 => 속도상승)


3. dcache_diff신호가 1이 되면 데이터를 큐에 넣기


3. 큐에 뭔가 존재하면 거기 있는 데이터를 램으로 보내기


4. ack가 오면 코어로 ack 신호를 보내기.


5. read신호에 대해서는 read중에 dcahce_diff signal이 올 수도 있다.....(맞나??) 그 때는 큐에만 넣어주면 될듯... 


6. write 중에는 read 하고자 할 수 없음. 왜냐면 당연히, write가 끝나고 aes 모듈에 read하고 싶다고 올 테니까.......

일단 캐시로 올리는 부분을 찾아야 되는데, a25_dcache.v에서 아래와 같은 부분이 있음.


generate

    for ( i=0; i<WAYS;i=i+1 ) begin : rams


        // Tag RAMs 

        `ifdef XILINX_SPARTAN6_FPGA

        xs6_sram_256x21_line_en

        `endif


        `ifdef XILINX_VIRTEX6_FPGA

        xv6_sram_256x21_line_en

        `endif


        `ifndef XILINX_FPGA

        generic_sram_line_en 

        `endif


            #(

            .DATA_WIDTH                 ( TAG_WIDTH             ),

            .INITIALIZE_TO_ZERO         ( 1                     ),

            .ADDRESS_WIDTH              ( CACHE_ADDR_WIDTH      ))

        u_tag (

            .i_clk                      ( i_clk                 ),

            .i_write_data               ( tag_wdata             ),

            .i_write_enable             ( tag_wenable_way[i]    ),

            .i_address                  ( tag_address           ),


            .o_read_data                ( tag_rdata_way[i]      )

            );

            

        // Data RAMs 

        `ifdef XILINX_SPARTAN6_FPGA

        xs6_sram_256x128_byte_en

        `endif


        `ifdef XILINX_VIRTEX6_FPGA

        xv6_sram_256x128_byte_en

        `endif


        `ifndef XILINX_FPGA

        generic_sram_byte_en

        `endif


            #(

            .DATA_WIDTH    ( CACHE_LINE_WIDTH) ,

            .ADDRESS_WIDTH ( CACHE_ADDR_WIDTH) )

        u_data (

            .i_clk                      ( i_clk                         ),

            .i_write_data               ( data_wdata                    ),

            .i_write_enable             ( data_wenable_way[i]           ),

            .i_address                  ( data_address                  ),

            .i_byte_enable              ( {CACHE_LINE_WIDTH/8{1'd1}}    ),

            .o_read_data                ( data_rdata_way[i]             )

            );                                                     



        // Per tag-ram write-enable

        assign tag_wenable_way[i]  = tag_wenable && ( select_way[i] || source_sel[C_INIT] );


        // Per data-ram write-enable

        assign data_wenable_way[i] = (source_sel[C_FILL] && select_way[i]) || 

                                     (write_hit && data_hit_way[i] && c_state == CS_IDLE) ||

                                     (consecutive_write && data_hit_way_r[i]);

        // Per data-ram idle_hit flag

        assign data_hit_way[i]     = tag_rdata_way[i][TAG_WIDTH-1] &&                                                  

                                     tag_rdata_way[i][TAG_ADDR_WIDTH-1:0] == i_address[31:TAG_ADDR32_LSB] &&  

                                     c_state == CS_IDLE;                                                               

    end                                                         

endgenerate


=========================================================

여기서 아래의 구문이 128 bits짜리 데이터를 캐쉬에 쓰는 구문임.

            .i_write_data               ( data_wdata                    ),

            .i_write_enable             ( data_wenable_way[i]           ),

            .i_address                  ( data_address                  ),

그렇기 때문에 이 부분에 wiring을 외부로 연결해서 aes 모듈에 연결시켜야됨.

그리고 아래의 byte_enable은 16'hffff이기에, 앞서 살펴봤던 것 같이 모든 데이터를 다 쓴다는 의미로

받아들일 수 있음.


그러면 여기서 한가지 고려해야할 사항이, 

문제 1. data를 쓰고 ack 신호가 오기 전에 다른 data를 쓰라고 바뀌면 어떻게 할 것인가?

=> 그래서 이 문제 해결을 위해서는 queue를 만드는 방법이 제일 좋을 것 같음...


문제 2. write miss가 나면 어떻게 될 것인가? 메모리에서 데이터를 받아오고 다시 하나?

=> 상관 없을 것 같음... 무시 가능할듯.


==================================================================

그러면 해야할 stage로는, 일단 aes 모듈에 

+ Recent posts