싱글사이클 32비트 small MIPS 프로세서의 일부를 VerilogHDL을 이용하여 나타낸것입니다.
수행 가능한 명령어는  아래 메인디코더 모듈을 보면 쉽게 파악할 수 있습니다.


always @ (*)
case(op)
6'b000000: controls <= 9'b110000010; //Rtyp
6'b100011: controls <= 9'b101001000; //LW
6'b101011: controls <= 9'b001010000; //SW
6'b000100: controls <= 9'b000100001; //BEQ
6'b000101: controls <= 9'b000100001; //BNE         //modified
6'b001000: controls <= 9'b101000000; //ADDI
6'b001101: controls <= 9'b101000011; //ORI         //modified
6'b000010: controls <= 9'b000000100; //J
default: controls <= 9'bxxxxxxxxx; //???
endcase

일단  R-type Opcode는   Function Table을 참조해야하기때문에  ,예외로 두고,
LW(Load Word) , 
SW(Store Word) , 
BEQ(Branch EQual) , 
BNE(Branch Not Equal) , 
ADDI (Add Imm) , 
ORI ( OR Imm) , 
J(Jump)

또한, ALU디코더 모듈을  살펴보면

case (aluop)
2'b00: alucontrol <= 3'b010; // add
2'b01: alucontrol <= 3'b110; // sub
2'b11: alucontrol <= 3'b001; // ori     //modified
default: 
case(funct) // RTYPE
6'b100000: alucontrol <= 3'b010; // ADD
6'b100010: alucontrol <= 3'b110; // SUB
6'b100100: alucontrol <= 3'b000; // AND
6'b100101: alucontrol <= 3'b001; // OR
6'b101010: alucontrol <= 3'b111; // SLT
default: alucontrol <= 3'bxxx; // ???
endcase
endcase

ADD
SUB
AND
OR
ORI
SLT (Set Less Than)


총13개의 명령 수행이 가능한 CPU입니다.

테스트에 사용된 MIPS Assembly Code는 다음과 같습니다.

#MIPS assembly sample code

.text

main : addi $s1, $0, 0                #$s1 = 0
        addi $s0, $0, 1                #$s0 = 1
addi $t0, $0, 101      #$t0 = 101

loop: slt $t1, $s0, $t0            
        bne     $t1  $0, continue          
        beq $t1, $0, done
continue:  
        add $s1, $s1, $s0
add $s0, $s0, $s0
j   loop  
done:   ori     $s2,  $s1,  0x80      #$s2에 255(FF)가 나오면 증명 
done1: j     done1

위 코드는 20+21+22+23+24+25+26 = 127 (0x7F) 를 먼저 구한뒤 , 
0x7F가 결과로 나오게 되면 SLT에서 FALSE State가 되고 , 따라서 beq에서 done으로 점프합니다.
그리고나서 , 0x80과 ori 연산을 수행하게되면 , 최종적으로 결과는 0xFF가 나옵니다.


위 코드를 직접 기계어로 바꾸면 다음과 같습니다.
20110000
20100001
20080065
0208482A
15200002
11200006
02308820
02108020
08000003
36320080
0800000A



마지막 aluout에  0xFF가 출력되는것을 확인할 수 있습니다.
Program Counter의 증가와,  Instruction의 Fetch도 올바르게 되는것을 확인할 수 있습니다.
싱글사이클이기 때문에  Posedge Clock일때 , 인스트럭션이 Fetch 되어져서 실행되는것을 확인할 수 있습니다.


이 자료를 상업적으로 이용하는것을 절대 금지하며, (레포트월드 등)
만약에 상업적으로 이용하는것이 적발된다면 어떠한 일이 일어날지 모릅니다.


저작자 표시 비영리 변경 금지
신고
크리에이티브 커먼즈 라이선스
Creative Commons License
by Sone 2010.05.29 14:56

Altera Quartus 9.0 SP2 를 기반으로 작성된 소스입니다.


module m_main
(clk,sel,reset,
A,B,A_LED,B_LED,sel_LED,
HEX7,HEX6,HEX5,HEX4,HEX1,HEX0,
status_overflow);
input clk;  //Key1(clk)
input sel;  //iSW17(selector)
input reset; //Key0(reset)
input [7:0] A; //iSW15~08(input switch)
input [7:0] B; //iSW07~00(input switch)
output [7:0] A_LED; //show input status in LEDRx
output [7:0] B_LED; //show input status in LEDRx
output sel_LED;  //show select input status in LEDR17
output [6:0] HEX7; //A input 7segment Display
output [6:0] HEX6; //A input 7segment Display
output [6:0] HEX5; //B input 7segment Display
output [6:0] HEX4; //B input 7segment Display
output [6:0] HEX1; //result 7segment Display
output [6:0] HEX0; //result 7segment Display
output status_overflow; //overflow LEDG0

wire [7:0] input_d_regA; //connected with m_input_D`s output
wire [7:0] input_d_regB; //connected with m_input_D`s output
wire [8:0] result_adder_subtractor; //connected with result_operator
wire overflow_flag;   //connected with overflow result

assign A_LED = A; //show input status
assign B_LED = B;  //show input status
assign sel_LED = sel; //show select input status
assign status_overflow = (overflow_flag==1'b0) ? 1'b0 : 1'b1; //show overflow status

//sub module call
m_input_D U1 (clk, reset, A, input_d_regA),
    U2 (clk, reset, B, input_d_regB); //D_Input
m7SEGMENT U3 (A[7:4], HEX7), //input to 7segment
    U4 (A[3:0], HEX6); //input to 7segment
m7SEGMENT U5 (B[7:4], HEX5), //input to 7segment
    U6 (B[3:0], HEX4); //input to 7segment
m7SEGMENT U7 (result_adder_subtractor[7:4], HEX1), //result to 7segment
    U8 (result_adder_subtractor[3:0], HEX0); //result to 7segment
unsigned_adder_subtractor U9 (input_d_regA, input_d_regB, sel, overflow_flag, result_adder_subtractor);
endmodule


//Data input module
module m_input_D(clk,reset,D,Q);
input clk;
input reset;
input [7:0] D;
output reg [7:0] Q;
always @ (posedge clk or negedge reset) begin
 if(!reset)
  Q <= 8'b0;
 else
  Q <= D;
end
endmodule


//7segment-display module
module m7SEGMENT(D,Q);
input [3:0] D; //4-bit input
output reg [6:0] Q;
always @ (D) begin //stimulate with D
 case (D)
  4'd0: Q = 7'b1000000; //0
  4'd1: Q = 7'b1111001; //1
  4'd2: Q = 7'b0100100; //2
  4'd3: Q = 7'b0110000; //3
  4'd4: Q = 7'b0011001; //4
  4'd5: Q = 7'b0010010; //5
  4'd6: Q = 7'b0000010; //6
  4'd7: Q = 7'b1011000; //7
  4'd8: Q = 7'b0000000; //8
  4'd9: Q = 7'b0011000; //9
  4'd10: Q = 7'b0100000; //A
  4'd11: Q = 7'b0000011; //B
  4'd12: Q = 7'b0100111; //C
  4'd13: Q = 7'b0100001; //D
  4'd14: Q = 7'b0000110; //E
  4'd15: Q = 7'b0001110; //F
  default: Q = 7'b1111111; //off
 endcase
end
endmodule

module unsigned_adder_subtractor
(dataA,dataB,
add_sub,overflow_flag,result);
input [7:0] dataA;
input [7:0] dataB;
input add_sub;   // if this is 1, add; else subtract
output overflow_flag;
output reg [8:0] result;

assign overflow_flag = (result[8]==1'b1) ? 1'b1 : 1'b0;
always @ (dataA or dataB or add_sub) begin
 if (add_sub)
  result <= dataA + dataB;
 else
  result <= dataA - dataB;
end
endmodule

저작자 표시 비영리 변경 금지
신고
크리에이티브 커먼즈 라이선스
Creative Commons License
by Sone 2009.10.14 00:01

Altera Quartus 9.0 SP2 컴파일러를 기반으로 서술되었습니다.


module _xor_(x1, x2, X1_LED, X2_LED, f);

input x1, x2;
output X1_LED, X2_LED, f;

assign X1_LED = x1;
assign X2_LED = x2;

xor U1 (f,x1,x2);
endmodule

저작자 표시 비영리 변경 금지
신고
크리에이티브 커먼즈 라이선스
Creative Commons License
by Sone 2009.10.13 23:35

모든 소스는 Altera Quartus 9.0 SP2 컴파일러,  DE2-70 보드를 기반으로 합니다.


베릴로그는 대부분  비트단위 핸들링을 하는것이 , C언어와는 다르게 느낄수 있는 색다른 매력인것 같다.
직접 Hardware Design과 관계되다보니 , 그런듯..

module ShiftRegister
(clk,clock_enable,
load_en,reset,
input_D,input_status_LED,
output_Q, load_en_LED,clock_enable_LED);

input clk;  //use KEY1  clock input;
input clock_enable; //iSW16  is CE input
input load_en;  //iSW17 is load_en input
input reset; //Use KEY0 Asynchronous Reset Operation
input [7:0] input_D; //use iSW7-0 input data , connected with LEDR_X
output [7:0] input_status_LED; //status for input -  LEDR_X
output load_en_LED; //status for load_en
output clock_enable_LED; //status for clock_enable
output reg [7:0] output_Q; //use LEDG display the output data Q

assign input_status_LED = input_D;
assign load_en_LED = load_en;
assign clock_enable_LED = clock_enable;

always @ (negedge reset or posedge clk)begin
 if (!reset) //if reset is 1
  output_Q <= 8'b00000000; //all output set to 0
 else begin //otherwise
  if (clock_enable) //clock_enable and posedge clk -> shift operation
   output_Q <= {1'b0,output_Q[7:1]};  //Logical Shift Right
  else if(load_en) //(load_en signal)? (new data input) : (existing data)
   output_Q <= input_D;
 end
end
endmodule

저작자 표시 비영리 변경 금지
신고
크리에이티브 커먼즈 라이선스
Creative Commons License
by Sone 2009.10.13 23:30
| 1 |

티스토리 툴바