다운/퍼 가실 때 댓글 부탁드려요. 그리고 받으신 자료 유료 레포트 사이트에 올리지 말아주세요.
1. 개 요
가. 클럭마다 PC(Program Counter)에서 가리키는 rom_table의 instruction을 받아와서 디코드하여 instruction이 가리키는 레지스터의 주소내의 데이터를 연산하여 그 결과값을 다시 레지스터에 기록하는 싱글 사이클 CPU를 구현한다.
나. PC는 다른 조건없이 매 클럭마다 1씩 증가되며, 연산 명령은 구조를 단순화하기 위하여 adder만을 사용하고, wirte_address와 read_address1의 주소를 같게 하여, 예를 들어 a, b에 대한 연산 결과가 a에 저장되는 형태를 취한다. (a = a+b)
2. 알고리즘
가. Instruction Fetch
|
|
1) 클럭에 동기화 되어 PC값이 증가되면서 해당 rom_table에 있는 instruction을 읽어온다
2) pc는 클럭마다 1씩 증가되고 새로운 instruction을 받아오게 된다.(single_cycle 특성)
3) rom_table의 수는
나. Decoder
|
|
1) 받아온 instruction의 상위 6비트는 실질적인 명령어로 사용되고
2) 하위 10비트 중 각각 5비트씩은 read_address1, read_address2로 사용된다.
3) 또한 클록에 동기화되어 write_address는 [9:5]비트의 데이터를 주소로 사용한다.
다. Register & ALU
|
|
1) 이번 과제에서의 operand는 adder기능만을 수행함으로 6‘b000001를 사용한다.
2) read_address1과 read_address2에 해당하는 주소의 데이터를 register에서 읽어와서 ALU에서 adder 연산을 수행한 후 clk이 posedge일 때마다 해당 write_address에 해당하는 register에 연산 결과인 write_data를 쓴다.
3) read_enable1, read_enable2은 instruction에 write_enable값은 클럭에 동기화되어 1로 할당되고 이는 매 클럭마다 2개의 data를 add 연산하여 레지스터에 쓰는 구조를 갖게됨을 의미한다.
3. 코 드
|
module cpu(clk, pc, rst, write_data, read_address1, read_address2, read_enable1, read_enable2); input clk, rst; output [7:0] write_data; output [5:0] pc; output [4:0] read_address1, read_address2; output read_enable1, read_enable2; reg [4:0] read_address1, read_address2, write_address; reg [5:0] pc; reg [7:0] read_data1, read_data2; reg [15:0] inst_out; reg read_enable1, read_enable2, write_enable; // rom_table 모듈 시행 m_rom_table rom_table(clk, pc, rst, inst_out); // instruction decoder 모듈 시행 m_inst_decoder inst_decoder(clk, inst_out, read_address1, read_address2, write_address, read_enable1, read_enable2, write_enable); // register 모듈 시행 m_register register(clk, rst, read_enable1, read_enable2, write_enable, read_address1, read_address2, write_address, read_data1, read_data2, write_data); // alu 모듈 시행 func_sel과 result_sel 값은 adder기능을 수행하도록 0과 2'b00을 대입 m_alu alu(read_data1, read_data2, 0, 2'b00, write_data); always@(posedge clk) // 클럭마다 pc값을 1 증가 begin pc = pc + 1'b1; end endmodule module m_rom_table(clk, pc, rst, inst_out); input [5:0] pc; input clk, rst; output [15:0] inst_out; reg [15:0] inst_out; reg [15:0] rom_data[0:63]; always@(posedge clk or negedge rst) begin if(rst == 1'b0) // rst가 0이면 rom_data 테이블 초기화 begin rom_data[0] = 16'b0000010000000001; rom_data[1] = 16'b0000010000000001; rom_data[2] = 16'b0000010000000001; rom_data[3] = 16'b0000010000000001; |
|
rom_data[4] = 16'b0000010000000001; rom_data[5] = 16'b0000010000000001; rom_data[6] = 16'b0000010000000001; rom_data[7] = 16'b0000010000000001; rom_data[8] = 16'b0000010000000001; rom_data[9] = 16'b0000010000000001; rom_data[10] = 16'b0000010000000001; rom_data[11] = 16'b0000010000000001; rom_data[12] = 16'b0000010000000001; rom_data[13] = 16'b0000010000000001; rom_data[14] = 16'b0000010000000001; rom_data[15] = 16'b0000010000000001; rom_data[16] = 16'b0000010000000001; rom_data[17] = 16'b0000010000000001; rom_data[18] = 16'b0000010000000001; rom_data[19] = 16'b0000010000000001; rom_data[20] = 16'b0000010000000001; rom_data[21] = 16'b0000010000000001; rom_data[22] = 16'b0000010000000001; rom_data[23] = 16'b0000010000000001; rom_data[24] = 16'b0000010000000001; rom_data[25] = 16'b0000010000000001; rom_data[26] = 16'b0000010000000001; rom_data[27] = 16'b0000010000000001; rom_data[28] = 16'b0000010000000001; rom_data[29] = 16'b0000010000000001; rom_data[30] = 16'b0000010000000001; rom_data[31] = 16'b0000010000000001; rom_data[32] = 16'b0000010000000001; rom_data[33] = 16'b0000010000000001; rom_data[34] = 16'b0000010000000001; rom_data[35] = 16'b0000010000000001; rom_data[36] = 16'b0000010000000001; rom_data[37] = 16'b0000010000000001; rom_data[38] = 16'b0000010000000001; rom_data[39] = 16'b0000010000000001; rom_data[40] = 16'b0000010000000001; rom_data[41] = 16'b0000010000000001; rom_data[42] = 16'b0000010000000001; rom_data[43] = 16'b0000010000000001; rom_data[44] = 16'b0000010000000001; rom_data[45] = 16'b0000010000000001; rom_data[46] = 16'b0000010000000001; rom_data[47] = 16'b0000010000000001; rom_data[48] = 16'b0000010000000001; rom_data[49] = 16'b0000010000000001; rom_data[50] = 16'b0000010000000001; rom_data[51] = 16'b0000010000000001; rom_data[52] = 16'b0000010000000001; rom_data[53] = 16'b0000010000000001; rom_data[54] = 16'b0000010000000001; rom_data[55] = 16'b0000010000000001; rom_data[56] = 16'b0000010000000001; rom_data[57] = 16'b0000010000000001; rom_data[58] = 16'b0000010000000001; rom_data[59] = 16'b0000010000000001; rom_data[60] = 16'b0000010000000001; rom_data[61] = 16'b0000010000000001; rom_data[62] = 16'b0000010000000001; rom_data[63] = 16'b0000010000000001; end end always@(posedge clk) // 클럭마다 pc에 해당하는 rom_data의 값 inst_out에 읽어옴 begin inst_out = rom_data[pc]; end endmodule |
|
module m_inst_decoder(clk, inst_in, read_address1, read_address2, write_address, read_enable1, read_enable2, write_enable); input clk; input [15:0] inst_in; output [4:0] read_address1, read_address2, write_address; output read_enable1, read_enable2, write_enable; reg [4:0] read_address1, read_address2, write_address; reg read_enable1, read_enable2, write_enable; always@(inst_in) // instruction을 받을 때마다 read_address1,2를 저장 begin read_address1 = inst_in[9:5]; read_address2 = inst_in[4:0]; read_enable1 = 1; read_enable2 = 1; end always@(posedge clk) // 매 클럭마다 5~9비트 데이터를 write_address로 사용 begin write_address = inst_in[9:5]; write_enable = 1; end endmodule module m_register(clk, rst, read_enable1, read_enable2, write_enable, read_address1, read_address2, write_address, read_data1, read_data2, write_data); input clk, rst, read_enable1, read_enable2, write_enable; input [4:0] read_address1, read_address2, write_address; input [7:0] write_data; output [7:0] read_data1, read_data2; reg [7:0] read_data1, read_data2; reg [7:0] rom_table[0:31]; always@(posedge clk or negedge rst) begin if(rst == 1'b0) // rst가 0이면 rom_table 초기화 begin rom_table[0] = 8'b00000000; rom_table[1] = 8'b00000001; rom_table[2] = 8'b00000010; rom_table[3] = 8'b00000011; rom_table[4] = 8'b00000100; rom_table[5] = 8'b00000101; rom_table[6] = 8'b00000110; rom_table[7] = 8'b00000111; rom_table[8] = 8'b00001000; rom_table[9] = 8'b00001001; rom_table[10] = 8'b00001010; rom_table[11] = 8'b00001011; rom_table[12] = 8'b00001100; |
|
rom_table[13] = 8'b00001101; rom_table[14] = 8'b00001110; rom_table[15] = 8'b00001111; rom_table[16] = 8'b00010000; rom_table[17] = 8'b00010001; rom_table[18] = 8'b00010010; rom_table[19] = 8'b00010011; rom_table[20] = 8'b00010100; rom_table[21] = 8'b00010101; rom_table[22] = 8'b00010110; rom_table[23] = 8'b00010111; rom_table[24] = 8'b00011000; rom_table[25] = 8'b00011001; rom_table[26] = 8'b00011010; rom_table[27] = 8'b00011011; rom_table[28] = 8'b00011100; rom_table[29] = 8'b00011101; rom_table[30] = 8'b00011110; rom_table[31] = 8'b00011111; end else if(write_enable == 1'b1) // write_enable이 1이면 레지스터에 데이터 쓰기 rom_table[write_address] = write_data; end always@(read_address1) begin if(read_enable1 == 1'b1) // read_enable1이 1이면 레지스터에서 데이터 읽음 read_data1 = rom_table[read_address1]; end always@(read_address2) begin if(read_enable2 == 1'b1) // read_enable2이 1이면 레지스터에서 데이터 읽음 read_data2 = rom_table[read_address2]; end endmodule module m_alu(a, b, func_sel, result_sel, result); // 이 이하부터는 ALU 연산 input [7:0] a, b; input func_sel; input [1:0] result_sel; output [7:0] result; reg [7:0] result; reg [7:0] adder_result; reg [7:0] and_result; reg [7:0] or_result; m_adder adder1(a, b, adder_result, func_sel); m_and and1(a, b, and_result); m_or or1(a, b, or_result); always@(result or adder_result or and_result or or_result or result_sel) case(result_sel) 2'b00 : result = adder_result; 2'b01 : begin if(adder_result >= 0) result = 8'b00000000; else result = 8'b00000001; end |
|
2'b10 : result = and_result; 2'b11 : result = or_result; endcase endmodule module m_adder(a, b, adder_result, func_sel); input [7:0] a, b; input func_sel; output [7:0] adder_result; wire [7:0] c; wire [7:0] b1; m_complement com1(b, b1, func_sel); m_half_adder ha(a[0], b1[0], c[0], adder_result[0]); m_full_adder fa1(a[1], b1[1], c[0], c[1], adder_result[1]); m_full_adder fa2(a[2], b1[2], c[1], c[2], adder_result[2]); m_full_adder fa3(a[3], b1[3], c[2], c[3], adder_result[3]); m_full_adder fa4(a[4], b1[4], c[3], c[4], adder_result[4]); m_full_adder fa5(a[5], b1[5], c[4], c[5], adder_result[5]); m_full_adder fa6(a[6], b1[6], c[5], c[6], adder_result[6]); m_full_adder fa7(a[7], b1[7], c[6], c[7], adder_result[7]); endmodule module m_full_adder(a, b, cin, cout, adder_result); input a, b, cin; output cout, adder_result; wire c1, c2, s1; m_half_adder ha1(b, cin, c1, s1); m_half_adder ha2(a, s1, c2, adder_result); assign cout = c1 | c2; endmodule module m_half_adder(a, b, c, adder_result); input a, b; output c, adder_result; assign adder_result = a ^ b; assign c = a & b; endmodule |
|
module m_complement(b, b1, func_sel); input [7:0] b; input func_sel; output [7:0] b1; reg [7:0] tmp; always@(b or tmp or func_sel) case(func_sel) 1'b0 : tmp = b; 1'b1 : tmp = ~b + 1; endcase assign b1 = tmp; endmodule module m_and(a, b, and_result); input [7:0] a, b; output [7:0] and_result; assign and_result = a & b; endmodule module m_or(a, b, or_result); input [7:0] a, b; output [7:0] or_result; assign or_result = a | b; endmodule |
4. 파형 및 분석
|
|
가. 위 파형에서 rst가 0으로 시작하여 일단 rom_data와 rom_table을 각각 초기화 시켰다.
나. 위 연산은 read_address1의 데이터와 read_address2의 데이터를 더하여 다시 read_address1에 저장하는 것이며, write_data는 read_address1에 저장된 데이터 값을 출력한다.
다. (1)에서 pc값이 1 증가되면서 해당 instruction을 rom_data에서 빼오는데 rom_data 64개 모두 0000010000000001의 값이 저장되어 있다. 즉 00000번과 00001번지의 데이터를 000001(add) 연산하라는 뜻인데, 그 결과 rst에 의해서 초기화되어 있었던 rom_table의 00000번과 00001번의 데이터 0과 1이 더해져서 다시 00000번지 레지스터에 쓰여지고 그 연산결과인 1이 wirte_data로 출력됨을 볼 수 있다.
라. 그 후에는 매번 00001번의 데이터 값인 1이 추가해서 더해짐으로 (2)번과 같이 write_data는 매 pc마다 1씩 증가함을 볼 수 있다.
|
|
가. 이 파형은 00001번지 레지스터의 값을 단순히 2로 바꾸어놓은 것이다. 즉 매 pc마다 00001번지의 2 값이 계속 더해짐으로 write_data는 2만큼 계속 늘어나가는 것을 볼 수 있다.
※ 참고 문헌
가. HDL Chip Design(Doone Publications / Douglas J Smith 저)
'레포트 자료' 카테고리의 다른 글
| 컴퓨터구조 설계 및 실험 - 16bit CPU (Load / Store instruction 추가) (0) | 2009/02/02 |
|---|---|
| 컴퓨터구조 설계 및 실험 - 16bit CPU (I-type 추가) (0) | 2009/02/02 |
| 컴퓨터구조 설계 및 실험 - 16bit CPU (Instruction Fetch & Decode) (1) | 2009/02/02 |
| 컴퓨터구조 설계 및 실험 - register (0) | 2009/02/02 |
| 컴퓨터구조 설계 및 실험 - ALU (1) | 2009/02/02 |
| 컴퓨터구조 설계 및 실험 - 유한상태기계(FSM - Finite State Machine) (2) | 2009/01/30 |


cpu(instruction,decode).zip



