싱글사이클 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 되어져서 실행되는것을 확인할 수 있습니다.


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


저작자 표시 비영리 변경 금지
신고
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

저작자 표시 비영리 변경 금지
신고
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

저작자 표시 비영리 변경 금지
신고
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

저작자 표시 비영리 변경 금지
신고
by Sone 2009.10.13 23:30
| 1 |