2024.11.11 수업날
< Control_Block instance >
이번에는 저번에 만들었던 Control_Block에 대해서 마저 만들어본다.
아래의 그림의 Control_Block을 만드는 것이다.
12 bit ring counter source code
/////////////////////////////////////////////// 2024.11.11
module ring_counter_clk12(
input clk, reset_p,
output reg [11:0] t);
always @(posedge clk or posedge reset_p) begin
if(reset_p) t = 12'b0000_0000_0000;
else begin
if(t == 0) t = 12'b0000_0000_0001;
else if(t == 12'b1000_0000_0000) t = 12'b0000_0000_0001;
else t = {t[10:0], 1'b0};
end
end
endmodule
ring_counter_clk12 모듈은 12 bit ring counter를 사용하여 Control_Block에 인스턴스 하기 위한 것이다.
ring counter의 0 bit에 따라 1이면 pc_oen에 1을 출력하고, 0이면 pc_oen에 0을 출력한다.
instr_decoder source code
//////////////////////////////////////////////////
module instr_decoder(
input [7:0] ir_data,
output reg nop, outb, outs, add_s, sub_s, and_s, shl, clr_s, psah,
shr, load, jz, jmp, jge, div_s, mul_s,
mov_ah_cr, mov_ah_dr, mov_tmp_ah, mov_tmp_br, mov_tmp_cr,
mov_tmp_dr, mov_tmp_rr, mov_cr_ah, mov_cr_br, mov_dr_ah, mov_dr_tmp,
mov_dr_br, mov_rr_ah, mov_key_ah, mov_inr_tmp, mov_inr_rr);
always @(ir_data) begin
{nop, outb, outs, add_s, sub_s, and_s, shl, clr_s, psah,
shr, load, jz, jmp, jge, div_s, mul_s,
mov_ah_cr, mov_ah_dr, mov_tmp_ah, mov_tmp_br, mov_tmp_cr,
mov_tmp_dr, mov_tmp_rr, mov_cr_ah, mov_cr_br, mov_dr_ah, mov_dr_tmp,
mov_dr_br, mov_rr_ah, mov_key_ah, mov_inr_tmp, mov_inr_rr} = 0;
case(ir_data)
8'h00 : nop = 1;
8'h0B : outb = 1;
8'h07 : outs = 1;
8'h50 : add_s = 1;
8'h52 : sub_s = 1;
8'h54 : and_s = 1;
8'h55 : div_s = 1;
8'h51 : mul_s = 1;
8'h15 : shl = 1;
8'h10 : clr_s = 1;
8'h14 : psah = 1;
8'h16 : shr = 1;
8'hD6 : load = 1;
8'hD0 : jz = 1;
8'hD4 : jmp = 1;
8'hD2 : jge = 1;
8'h83 : mov_ah_cr = 1;
8'h84 : mov_ah_dr = 1;
8'h88 : mov_tmp_ah = 1;
8'h8A : mov_tmp_br = 1;
8'h8B : mov_tmp_cr = 1;
8'h8C : mov_tmp_dr = 1;
8'h8D : mov_tmp_rr = 1;
8'h98 : mov_cr_ah = 1;
8'h9A : mov_cr_br = 1;
8'hA0 : mov_dr_ah = 1;
8'hA1 : mov_dr_tmp = 1;
8'hA2 : mov_dr_br = 1;
8'hA8 : mov_rr_ah = 1;
8'hB0 : mov_key_ah = 1;
8'hB9 : mov_inr_tmp = 1;
8'hBD : mov_inr_rr = 1;
default : nop = 1;
endcase
end
endmodule
instr_decoder 모듈은 아래의 표를 보고 만들었다.
아래의 표에서 Hexa Code는 기계어로 변환하는 것이다.
C언어에서 의도한대로 코드를 작성하고 Build를 하는 것과 같은 방식인데, 이때 Build를 하면 기계어로 변환되는 것이다.
- NOP: IDLE 상태
- SHL: SHIFT LEFT
- PSAH: Perrel shift accumulator high
- SHR : SHIFT RIGHT
- JZ: JUMP ZERO
- JMP: JUMP
- JGE: JUMP GRATE EQUAL
다음으로, 각 output이 어떤 t에 속해있는지를 구분하여 코드를 작성해야한다.
아래의 표들을 보고 참고하여 작성하면 된다.
곱셈, 나눗셈의 경우
control_signal source code
///////////////////////////////////////////////////
module control_signal(
input [11:0] t,
input nop, outb, outs, add_s, sub_s, and_s, shl, clr_s, psah,
shr, load, jz, jmp, jge, div_s, mul_s,
mov_ah_cr, mov_ah_dr, mov_tmp_ah, mov_tmp_br, mov_tmp_cr,
mov_tmp_dr, mov_tmp_rr, mov_cr_ah, mov_cr_br, mov_dr_ah, mov_dr_tmp,
mov_dr_br, mov_rr_ah, mov_key_ah, mov_inr_tmp, mov_inr_rr,
input zero_flag, sign_flag,
output mar_inen, mdr_inen, mdr_oen, ir_inen, pc_inc, load_pc, pc_oen, breg_inen,
output [1:0] acc_high_reset_p, acc_oen, acc_in_select,
output [1:0] acc_high_select_in, acc_low_select,
output op_add, op_sub, op_mul, op_div, op_and,
output tmpreg_inen, tmpreg_oen, creg_inen, creg_oen,
output dreg_inen, dreg_oen, rreg_inen, rreg_oen,
output outreg_inen, keychreg_oen, inreg_oen, keyout_inen, rom_en);
assign pc_oen = t[0] | (t[3] & (load | jz | jmp | jge));
assign mar_inen = t[0] | (t[3] & (load | jz | jmp | jge));
assign pc_inc = t[1] | (t[4] & (load | jz | jmp | jge));
////////////////////
assign rom_en = ~(t[1] | (t[4] & (load | jz | jmp | jge)));
assign mdr_inen = t[1] | (t[4] & (load | jz | jmp | jge));
assign mdr_oen = t[2] | (t[5] & (load | (jz & zero_flag) | jmp | (jge & ~sign_flag)));
assign load_pc = t[5] & ((zero_flag & jz) | (~sign_flag & jge) | jmp);
assign ir_inen = t[2];
assign tmpreg_oen = t[3] & (outb | mov_tmp_ah | mov_tmp_br | mov_tmp_cr | mov_tmp_dr | mov_tmp_rr);
assign keyout_inen = t[3] & outb;
assign acc_oen = t[3] & (outs | mov_ah_cr | mov_ah_dr);
assign outreg_inen = t[3] & outs;
assign op_add = t[3] & add_s;
assign acc_high_select_in[0] = (t[3] & (add_s | sub_s | and_s | mul_s | shr | mov_tmp_ah | mov_cr_ah | mov_rr_ah | mov_key_ah | mov_dr_ah)) | (t[4] & (add_s | div_s | mul_s)) | (mul_s & (t[5] | t[6] | t[7] | t[8] | t[9] | t[10])) | (div_s & (t[6] | t[8] | t[10]));
assign acc_high_select_in[1] = (t[3] & (add_s | sub_s | and_s | div_s | mul_s | shl | mov_tmp_ah | mov_cr_ah | mov_rr_ah | mov_key_ah | mov_dr_ah)) | (mul_s & (t[5] | t[7] | t[9])) | (div_s & (t[4] | t[5] | t[6] | t[7] | t[8] | t[9] | t[10]));
assign op_sub = t[3] & sub_s;
assign op_and = t[3] & and_s;
assign acc_low_select[0] = (t[3] & (psah | shr)) | (t[4] & (add_s|mul_s)) | (t[6] & mul_s) | (t[8] & mul_s) | (t[10] & mul_s);
assign acc_low_select[1] = (t[3] & (shl | psah | div_s)) | (t[5] & div_s) | (t[7] & div_s) | (t[9] & div_s) | (t[11] & div_s);
assign acc_high_reset_p = t[3] & clr_s;
assign op_div = (t[4] & div_s) | (t[6] & div_s) | (t[8] & div_s) | (t[10] & div_s);
assign op_mul = (t[3] & mul_s) | (t[5] & mul_s) | (t[7] & mul_s) | (t[9] & mul_s);
assign creg_inen = t[3] & (mov_ah_cr | mov_tmp_cr);
assign dreg_inen = t[3] & (mov_ah_dr | mov_tmp_dr );
assign acc_in_select = t[3] & (mov_tmp_ah | mov_cr_ah | mov_dr_ah | mov_rr_ah | mov_key_ah);
assign breg_inen = t[3] & (mov_tmp_br | mov_cr_br | mov_dr_br);
assign rreg_inen = t[3] & (mov_tmp_rr | mov_inr_rr);
assign creg_oen = t[3] & (mov_cr_ah | mov_cr_br);
assign dreg_oen = t[3] & (mov_dr_ah | mov_dr_tmp | mov_dr_br);
assign tmpreg_inen = (t[5] & load) | t[3] & (mov_dr_tmp | mov_inr_tmp);
assign rreg_oen = t[3] & mov_rr_ah;
assign keychreg_oen = t[3] & mov_key_ah;
assign inreg_oen = t[3] & (mov_inr_tmp | mov_inr_rr);
endmodule
이제 위에서 만들었던 코드들을 Control_Block에 인스턴스 한다.
Control_Block source code
//////////////////////////////////// 2024.11.11 -> 인스턴스 진행
module Control_Block(
input clk, reset_p,
input [7:0] ir_data,
input zero_flag, sign_flag,
output mar_inen, mdr_inen, mdr_oen, ir_inen, pc_inc, load_pc, pc_oen, breg_inen,
output [1:0] acc_high_reset_p, acc_oen, acc_in_select,
output [1:0] acc_high_select_in, acc_low_select,
output op_add, op_sub, op_mul, op_div, op_and,
output tmpreg_inen, tmpreg_oen, creg_inen, creg_oen,
output dreg_inen, dreg_oen, rreg_inen, rreg_oen,
output outreg_inen, keychreg_oen, inreg_oen, keyout_inen, rom_en);
wire [11:0] t;
ring_counter_clk12 rcount(.clk(clk), .reset_p(reset_p), .t(t));
wire nop, outb, outs, add_s, sub_s, and_s, shl, clr_s, psah,
shr, load, jz, jmp, jge, div_s, mul_s,
mov_ah_cr, mov_ah_dr, mov_tmp_ah, mov_tmp_br, mov_tmp_cr,
mov_tmp_dr, mov_tmp_rr, mov_cr_ah, mov_cr_br, mov_dr_ah, mov_dr_tmp,
mov_dr_br, mov_rr_ah, mov_key_ah, mov_inr_tmp, mov_inr_rr;
instr_decoder i_decoder(
ir_data,
nop, outb, outs, add_s, sub_s, and_s, shl, clr_s, psah,
shr, load, jz, jmp, jge, div_s, mul_s,
mov_ah_cr, mov_ah_dr, mov_tmp_ah, mov_tmp_br, mov_tmp_cr,
mov_tmp_dr, mov_tmp_rr, mov_cr_ah, mov_cr_br, mov_dr_ah, mov_dr_tmp,
mov_dr_br, mov_rr_ah, mov_key_ah, mov_inr_tmp, mov_inr_rr);
control_signal cs(
t,
nop, outb, outs, add_s, sub_s, and_s, shl, clr_s, psah,
shr, load, jz, jmp, jge, div_s, mul_s,
mov_ah_cr, mov_ah_dr, mov_tmp_ah, mov_tmp_br, mov_tmp_cr,
mov_tmp_dr, mov_tmp_rr, mov_cr_ah, mov_cr_br, mov_dr_ah, mov_dr_tmp,
mov_dr_br, mov_rr_ah, mov_key_ah, mov_inr_tmp, mov_inr_rr,
zero_flag, sign_flag,
mar_inen, mdr_inen, mdr_oen, ir_inen, pc_inc, load_pc, pc_oen, breg_inen,
acc_high_reset_p, acc_oen, acc_in_select,
acc_high_select_in, acc_low_select,
op_add, op_sub, op_mul, op_div, op_and,
tmpreg_inen, tmpreg_oen, creg_inen, creg_oen,
dreg_inen, dreg_oen, rreg_inen, rreg_oen,
outreg_inen, keychreg_oen, inreg_oen, keyout_inen, rom_en);
endmodule
cpu의 구조와 동작원리4(Control_Block instance 진행하기) 끝!