Control
control 신호들이 명령어에 해당하는 값들로 세팅되는 개념이다.
control 방식
- mux(multiplexer)에서 하는 control
- write assert 방식
- memory 혹은 register에서 write을 할 건지 말 건지를 결정하는 control
두 개(memory, register) 빼고는 다 mux control이다.
Single-Cycle Control
- 먼저 opcode를 보고 어떤 명령어 인지를 본다.(lw, sw, addi ....)
- 그 명령어에 필요한 control signal을 쫙 보낸다.
- ALU decoder(sub control)에 들어가서 +,/, & 와 같은 명령은 새끼 control에서 하게끔 하여 두 level로 나누었다.
ALU(Arithmetic Login Unit)
Review: Sequential Elements(f/f)
- Register: 회로에서 데이터를 저장한다.
- 저장된 값을 업데이트 할지를 결정하는 clock signal을 사용한다.
- Edge-triggered: 0에서 1로 CLK(clock)이 바뀔 때 업데이트 되는 방식(엣지에서 트리거!)
- Register with write control
- write control input이 1이면 clock 엣지 부분에서만 업데이트 된다.
- 저장된 값이 나중에 요구될 때 사용된다.
Clocking Methodology
- Combinational logic은 clock cycles동안에 데이터를 이동시킨다.
- 즉, clock edges 사이에서
- state elements로 부터 온 input, state element로 가는 output
- 가장 긴 딜레이를 갖는 Combinational logic이 clock 주기를 결정한다.
- clock edge가 rising edge가 되면 state element(register)에 값이 update됨.
명령어 중에 data memory와 register file에 컨트롤이 동시에 write enable되는 경우는 없음.
Register File
빨간 점선은 같은 부분이다.
왼쪽은 write port(A3, WD3) 오른쪽은 read port(A1, A2, RD1, RD2)를 나타낸다.
module regfile(input logic clk,
input logic we3,
input logic [4:0] ra1, ra2, wa3,
input logic [31:0] wd3,
output logic [31:0] rd1, rd2);
logic [31:0] rf[31:0];
// three ported register file : read two ports combinationally
// write third port on rising edge of clk
// register 0 hardwired to 0
// note: for pipelined processor, write third port on falling edge of clk
always_ff @(posedge clk)
if (we3) rf[wa3] <= wd3; //synch write
assign rd1 = (ra1 != 0) ? rf[ra1] : 0;
assign rd2 = (ra2 != 0) ? rf[ra2] : 0;
endmodule
HDL(Hardware Description Language) description
- imem은 실행 중에 바뀌지 않는 ROM(Read Only Memory)모델이다.(load)
- clock에 의해 실행 되는 것이 아닌 async(비동기)이다.
- 읽을 때는 async read 방식.
- 데이터를 쓸 때는, clk에 동기되어 write되는 sync 방식.
- 실행 중에 data가 계속 바뀜(RAM: Random Access Memory)
The Main Control Unit
- 명령어로부터 발생되는 Control Signal
Control Unit: ALU Decoder
- 00: lw, sw
- 01: beq
- 10: R-Type
Control Unit Main Decoder
RegWrite 0이면 register write port에 무슨 값이 들어와도 어차피 write 할 것이 아니기 때문에 MemtoReg는 don't care이다.
Extended Functionality: j
우리는 명령어의 길이가 32bit라고 알아왔었는데 jump 명령에서는 주어지는 다음 address 값이 26bit이므로 PC 값에 들어가기에 부적절하다. 그래서 다음과 같은 addressing 과정이 더해진다.
addressing
한 명령어의 크기는 4btye이다(32bit). 명령어의 시작 주소가 0이라면 다음 주소는 4, 그 다음 주소는 8이 되는 것이다. 이 때, 잘 보면 명령어의 LSB 0 번째와 1 번째 bit는 항상 0이라는 것을 알 수 있다.
즉 명령어는 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx00 과 같은 구조로 이루어져 있다.
따라서 우리는 저 x의 부분만 안다면 전체 명령어를 PC 값으로 만들어 낼 수 있는 것이다.
26비트의 imme 값이 left shift 하면 x4(메모리 한 주소당 4byte) 를 하여 28비트가 되고 그 값이 중간에 PC 값과 concatanate 되어 해당 값이 BTA(Branch Target Address)가 되어 이 주소로 이동하게 된다.
branch는 offset이라 0~15bit로 * 4 해서 PC에 더해주었지만 j와 jal은 26bit 전체가 절대주소가된다.
따라서 25-0 bit를 따로 빼줘서 32bit로 크기 맞춰주고 그게 PC값이 되어야한다.
그렇다면 26bit 짜리놈을 어떻게 32bit로 만들까?
25bit 짜리를 일단 shift left 2를 한다. 어차피 memory에서는 4byte 단위로 잘라먹으니까 하위 2bit는 무조건 00이다. 따라서 명령어로 교환할때는 2bit를 뗀상태로 교환하고 마지막에 붙치는 형식.
그리고 상위 4bit는 현재 PC값의 상위 4bit에서 가져온다. 그렇게하면 228 = 256MB 범위의 주소를 이동할 수 있다.
Q) 왜 left shift를 하는데 26에서 28이 됨?
A) 4배를 했기 때문에 뒤에 00이 붙기 때문에
Q) Target address 상위 4bit을 0000으로 사용하지 않는 이유?
A) Dynamic library는 프로그램 실행 중에 들어오는 부분으로, address의 시작주소 4bit는 0000이 아니다.
따라서 target address 상위 4bit을 0000으로 제한하게 되면 dynamic library로써는 사용할 수 없다.
따라서 dynamic library를 포함하여 더 넓은 범위에서 사용하기 위해서 상위 4bit을 current PC의 상위 4bit로 사용한다.
A sample HDL Testbench
A sample Test Program