[Harman 세미콘 아카데미] Day_46(System Verilog)
오늘은 어제에 이어 RAM을 추가하였습니다.
RAM은 ROM과 다르게 Write 동작도 가능합니다. 그리하여 Write를 Enable 하는 WE 신호, RAM 내부에 작성할 Addr주소와 주소에 작성할 wData를 입력할 수 있습니다. 또한 Read 동작도 가능하여 레지스터 내부의 주소 값을 rData로 출력할 수 있습니다.
RAM 까지만들어 어제 생성한 MCU와 연결하면 아래와 같은 Schematic을 구할 수 있습니다.
ROM의 명령을 받아, RV32I_Core로 들어가 동작을 하게되고, 명령어에 따라 RAM에 Data를 작성하거나, Data를 뽑아 올 수 도 있습니다.
또한, 어제는 R-Type에 대해 만들어 놓았다면, 이번에는 S-Type, L-Type, I-Type에 대한 선택을 한 번에 할 수 있도록 하였습니다. 기본 동작은 R-Type과 동일하지만, 각 Type 별 OpCode는 다르게 되어 있습니다. 또한 S-Type과 L-Type의 경우에는 RAM에서 값을 가져오기 떄문에 Imm이라는 Immediate값을 가져오게 됩니다. 그래서 기존의 R-Type이 갖고 있는 32bit의 데이터 형태와는 약간 다른 형태를 띄고 있습니다.
S와 I type은 imm값을 가지고 있고, 이를 활용해 연산을 진행합니다.
그리하여, ALU를 거치기 전, Imm Extend에 대한 값을 갖는 모듈을 만들어주고, MUX를 통해 RD2와 Imm Extend 값을 선택하여 사용할 수 있도록 합니다. 이를, RAM의 Addr 주소가 되고 주소에 wData값을 작성하게 됩니다.
이러한 방식으로 S-Type의 SW(Store Wood) 결과를 만들어 낼 수 있습니다.
그래서 아래의 rom[2]를 보게 되면, register file의 x2번 주소의 값인 12를 Imm = 8, 그리고 rs1 = 0으로 설정하여,
8을 4로 나눈 2 즉, RAM[2]에 12의 값을 저장하게 합니다.
아래의 그림과 같이, RAM의 2번 메모리에 12의 값이 저장됨을 볼 수 있고,
아래의 표를 통해, 제어 신호와 값이 들어가는 것을 자세히 확인할 수 있습니다.
RAM에 값을 저장하는 것을 배웠으면 값을 가져다 쓰는 법도 해야 합니다. RAM의 데이터인 rData를 출력하여 레지스터 파일의 새로운 저장소에 저장하는 것입니다.
교수님께서 만들어 보라고 하셔서 저는 아래의 그림과 같이 만들었습니다.
Imm을 제어하는 MUX_SEL 신호를 활용하여 ALU되어 연산되어 오는 값을 rData와 MUX처리를 하여 레지스터 파일에 넣어 주었습니다. 이때, rData와 ALU 연산값을 MUX할 때, rData에 대한 신호를 MUX의 1로 설정하여, Imm 값을 잘 받을 수 있도록 설정하였습니다.
RAM 메모리 2번에 저장 되어있는 12의 값을 레지스터 파일의 6번에 다시 저장하도록 구성하였습니다.
아래의 결과를 보게 되면, 맨 아래에 있는 Register File의 6번 저장소에, 상단에 있는 Mem[6]의 12 값이 잘 들어가는 것을 확인할 수 있었습니다.
교수님의 방법은 아래와 같습니다.
ALU에서 나오는 값과 rData의 값을 동일하게 MUX처리를 진행하는데, 이때 MUX의 SEL신호를 하나 더 추가하여 만드셨습니다. 그리하여, Control Unit에서는 regWen, ALUMuxSel, RFSrcMuxSel, DataWe의 총 4bit 신호로 제어를 진행합니다.
이를 테스트하기 위해, RAM Memory[2]번의 12 값을 regfile[3]번에 넣도록 Rom 명령어를 만들어 주었습니다.
그 결과, 위의 명령어의 결과와 값이 동일하게 나옴을 확인 할 수 있습니다.
그리고, I-Type에 대해서도 구현하였습니다.
I-Type의 경우 모든 기능들의 구조가 같지 않습니다. 기본적으로 R-Type과 기능 및 구조가 동일하되 뺄셈의 기능만 존재하지 않습니다. 또한, SLLI, SRLI, SRAI의 기능을 제외한 나머지 기능들은 32bit의 데이터 구조가 S-Type과 동일하고 방금 언급한 3가지 기능들은 R-Type과 32bit의 데이터 구조가 동일합니다.
그래서, 위의 정보들을 담아 하나의 I-Type으로 만들기 위해서 제가 고안한 방법은 imm의 값을 0으로 처리해 주었습니다.
3가지 SLLI, SRLI, SRAI들은 imm의 값을 사용하지 않는 R-Type과 동일한 Function을 수행하기 때문에 그대로 두었고, imm의 값을 가지는 나머지 녀석들을 모두 0으로 처리하여 R-Type과 동일하게 동작을 수행하도록 하였습니다.
######## I-Type 표 추가 예정 ###########
그 중에서, 연산들과 3가지 SLLI,SRLI,SRAI에 대해서 구분을 해 줘야 하기 때문에, 이들을 구분할 수 있는 Func3을 통해 imm의 값에 대해 처리하도록 하였습니다.
위의 그림처럼, ROM으로부터 들어오는 32bit의 InstrCode의 Function3부분인 [14:12]에 대해 Imm을 처리하도록 하였습니다. if 처리 되어 나오는 SLLI, SRLI, SRAI는 Imm을 사용하지 않기 때문에 shamt를 하기 위한 값들로 채우고 상위 비트를 0으로 처리합니다. 나머지 연산들은 [31:20]비트가 imm을 사용하기 때문에 남겨두고 상위 비트들을 0으로 처리하여 최종적으로 모두 32bit를 맞춰주게 됩니다.
그리고, ALU_Control의 경우에도, Imm의 초기값을 0으로 둔 덕분에, R-Type의 연산과 동일하게 사용할 수 있어 연산자도 동일하게 사용하였습니다.
ROM에 대해 작성한 스크립트 입니다.
rom[4] : Register File의 16번 주소에 rs1주소 2의 12값과 imm의 8값이 더해져 20의 결과를 나타냄
rom[5] : Register File의 17번 주소에 rs1주소 2의 12값을 왼쪽으로 5번 Shift 하도록 설정
rom[6] : Register File의 7번 주소에 rs1주소 1의 11값과 rs2주소의 2의 값이 감산해져 -1 결과를 나타냄
rom[7] : rom[6]에서 레지스터 파일의 7번 주소에 -1을 사용하여, SRAI 연산을 통해 출력 값을 모두 1로 나타내도록 합니다.
그에 대한 결과는 아래와 같습니다. ADDI, SLLI, SRAI 부분에 대해서 봐주시면 감사하겠습니다.
그리고, 이제 Github에 제 코드를 업로드 하게 되었습니다!! 관심 있으시면 참고하셔도 좋을 것 같습니다.
https://github.com/Heeju99/Code_Verilog_SystemVerilog
GitHub - Heeju99/Code_Verilog_SystemVerilog
Contribute to Heeju99/Code_Verilog_SystemVerilog development by creating an account on GitHub.
github.com
감사합니다!