📄 thumb_2_nnarm.v
字号:
cti[7],cti[2:0], //op1 and target
8'b00000000, //just extend
cti[6],cti[5:3]}; //op2
//cmp
2'b01 : t2a <= {2'b00, //always 00
1'b0, //op2 is a register
4'b1010, //cmp op
1'b1, //set condition code
cti[7],cti[2:0], //op1
4'h0, //no target
8'h00, //just extend
cti[6],cti[5:3]}; //op2
//mov
2'b10 : t2a <= {2'b00, //always 00
1'b0, //op2 is register
4'b1101, //mov
1'b0, // do not set condition code
4'b0000, //no op1
cti[7],cti[2:0], //target
8'b00000000, //just extend
cti[6],cti[5:3]}; //op2 to move to target
//bx
2'b11 : t2a <= {20'b0001_0010_1111_1111_1111,
4'b0001,cti[6],cti[5:3]};
endcase
//\/\/\/\/\/\/\\
else //ALU Operations
case(cti[9:6])
//lsl
4'b0010 : t2a <= {13'b000_1101_1_0000_0,cti[2:0],1'b0 , //mov lsl
cti[5:3],1'b0,cti[8],cti[6],2'b10,cti[2:0]};
//lsr
4'b0011 : t2a <= {13'b000_1101_1_0000_0,cti[2:0],1'b0 , //mov lsr
cti[5:3],1'b0,cti[8],cti[6],2'b10,cti[2:0]};
//asr
4'b0100 : t2a <= {13'b000_1101_1_0000_0,cti[2:0],1'b0 , //mov asr
cti[5:3],1'b0,cti[8],cti[6],2'b10,cti[2:0]};
//ror
4'b0111 : t2a <= {13'b000_1101_1_0000_0,cti[2:0],1'b 0 , //mov ror
cti[5:3],1'b0,cti[8],cti[6],2'b10,cti[2:0]};
//tst
4'b1000 : t2a <= {9'b000_1000_1_0,cti[2:0],4'b0000 ,
9'b000000000,cti[5:3] };
//neg
4'b1001 : t2a <= {9'b001_0011_1_0,cti[5:3],1'b0 ,
cti[2:0],12'h000 };
//cmp
4'b1010 : t2a <= {9'b000_1010_1_0,cti[2:0],4'b0000 ,
9'b000000000,cti[5:3] };
//cmn
4'b1011 : t2a <= {9'b000_1011_1_0,cti[2:0],4'b0000 ,
9'b000000000,cti[5:3] };
//mul
4'b1101 : t2a <= {9'b000_0000_1_0,cti[2:0],5'b00000 ,
cti[2:0],5'b10010,cti[5:3] };
//mvn
4'b1111 : t2a <= {13'b000_1111_1_0000_0,cti[2:0] ,
9'b00000000_0,cti[5:3] };
//op code same as normal arm instruction
default : t2a <= {3'b000,cti[9:6],2'b10,cti[2:0],1'b0 ,
cti[2:0],9'b000000000,cti[5:3] }; //Mian: AND,EOR,ADC,SBC,ORR,BIC
endcase
end
//+++++++++++++++++++++//
3'b011 : begin // Load/Store with Immediate Offset
if(cti[12]==1'b1) //transfer byte
t2a <= {2'b01, //always 01
1'b0, //offset is immediate
1'b1, //pre index
1'b1, //up , add offset to base
cti[12], //byte or word
1'b0, //no write back
cti[11], //load or store
1'b0,cti[5:3] , //base register
1'b0,cti[2:0], //store source or load target
5'b00000,2'b00,cti[10:6]}; //offset
else //transfer word
t2a <= {5'b01011,cti[12],1'b0,cti[11],1'b0,cti[5:3] ,
1'b0,cti[2:0],5'b00000,cti[10:6],2'b00 };//same as byte access, but must shift offset left 2 bit because word align
end
//+++++++++++++++++++++//
3'b100 : begin
if(cti[12]==1'b0) //SP-relative Load/Store
t2a <= {2'b01, //always 01
1'b0, //offset is immediate
1'b1, //pre index
1'b1, //up add offset
1'b0, //word transfer
1'b0, //no write back
cti[11], //load or store
4'b1101, //base is R13(SP)
1'b0,cti[10:8], //store source or load target
2'b00,cti[7:0],2'b00}; //word offset
else //Load/Store Halfword
t2a <= {3'b000, //always 000
2'b11, //pre index and up add offset
1'b1, //always 1
1'b0, //no write back
cti[11], //load or store
1'b0,cti[5:3], //base register
1'b0,cti[2:0], //store source or load target
2'b00,cti[10:9], //high 4 bit of offset
4'b1011, //unsigned half word
cti[8:6],1'b0 }; //low 4 bit of offset
end
//+++++++++++++++++++++//
3'b101 : begin
if(cti[12]==1'b1)
begin
if(cti[10]==1'b1) //Push/Pop Registers
t2a <= {3'b100, //multiple register transfer
(~cti[11]), //when load(1) post index, store(0) pre index
cti[11], //when load(1) up,when store(0) down
1'b0, //do not load PSR
1'b1, //write back
cti[11], //load or store
4'b1101, //base is SP
(cti[11] & cti[8]), //when load PC is loaded from MEM depending upon PC/LR bit (cti[8])
(~cti[11] & cti[8]),//when Store LR is stored to MEM depending upon PC/LR bit (cti[8])
6'b000000,cti[7:0]};
//changed in ver 0.2
/*
begin
if(cti[11]==1'b1) //ldm
t2a <= {3'b100, //multiple register transfer
(~cti[11]), //when load(1) post index, store(0) pre index
cti[11], //when load(1) up,when store(0) down
1'b0, //do not load PSR
1'b1, //write back
cti[11], //load or store
4'b1101, //base is SP
cti[8],1'b0,6'b000000,cti[7:0]}; //if load top stack to PC?
else //stm
t2a <= {3'b100, //always 100 for multiple register transfer
(~cti[11]),
cti[11],
2'b01,
cti[11],
4'b1101,
1'b0,cti[8], 6'b000000,cti[7:0]}; //store as LR?
end
*/
else //Add Offset to Stack Pointer
t2a <= {2'b00, //always 00 for data processing
1'b1, //offset is immediate
1'b0,(~cti[7]),cti[7],1'b0,//add or sub
1'b0, //do not set condition code
4'b1101, //op1 is SP
4'b1101, //target is SP
4'b1111, //ror 30 bit equal to lsl 2 bit
1'b0,cti[6:0]}; //offset
end
else //Load Address
begin
t2a <= {2'b00, //always 00
1'b1, // immediate
4'b0100, //add op
1'b0, //do not set condition code
2'b11,(~cti[11]),1'b1, //PC or SP
1'b0,cti[10:8], //target register
4'b1111,cti[7:0]}; //ror 30 bit equal to lsl 2 bit
ClearBit1=1'b1; //ssy add 2001 7 19
end
end
//+++++++++++++++++++++//
3'b110 : begin
if(cti[12]==1'b1)
begin
if(& cti[11:8]) //SWI
t2a <= {4'b1111,16'h0000,cti[7:0] } ;
else //Conditional Branch
t2a <= {4'b1010,{16{cti[7]}},cti[7:0]} ;// ? {15{cti[7]}},cti[7:1]
//Mian: This is not true conversion to ARM. Because in
//ARM branches are Word Aligned i.e [1:0] == 00
//But in Thumb branches are Halfword aligned i.e [0] == 0
//So when Branch inst executes in Thumb, use (offset << 1), instead
//(offset << 2) as in ARM state.
end
else
begin
if(cti[11]==1'b1) //Multiple Load
//changed in ver 0.2
t2a <= {6'b100010,wb_check,cti[11],1'b0 ,
cti[10:8],8'h00,cti[7:0] };//only when the base is not in the list, can you write back that register
//wb_check replaced following case changed in ver 0.2
/*
case(cti[10:8])
3'b000 : t2a <= {6'b100010,~cti[0],cti[11],1'b0 ,
cti[10:8],8'h00,cti[7:0] };
3'b001 : t2a <= {6'b100010,~cti[1],cti[11],1'b0 ,
cti[10:8],8'h00,cti[7:0] };
3'b010 : t2a <= {6'b100010,~cti[2],cti[11],1'b0 ,
cti[10:8],8'h00,cti[7:0] };
3'b011 : t2a <= {6'b100010,~cti[3],cti[11],1'b0 ,
cti[10:8],8'h00,cti[7:0] };
3'b100 : t2a <= {6'b100010,~cti[4],cti[11],1'b0 ,
cti[10:8],8'h00,cti[7:0] };
3'b101 : t2a <= {6'b100010,~cti[5],cti[11],1'b0 ,
cti[10:8],8'h00,cti[7:0] };
3'b110 : t2a <= {6'b100010,~cti[6],cti[11],1'b0 ,
cti[10:8],8'h00,cti[7:0] };
3'b111 : t2a <= {6'b100010,~cti[7],cti[11],1'b0 ,
cti[10:8],8'h00,cti[7:0] };
endcase
*/
else //Multiple Store
t2a <= {6'b100010,1'b1,cti[11],1'b0,
cti[10:8],8'h00,cti[7:0]};
end
end
//+++++++++++++++++++++//
3'b111 : begin
if(cti[12]==1'b1) //Long Branch = NO Operation
begin
if(cti[11]==1'b0) //the high 11 bits of offset
begin
t2a <= {28'b000_1101_0_0000_0000_00000_00_0_0000};
//MOV r0,r0 i.e No Operation
Next_LongBranchWithLinkOff=cti[10:0];
Next_AddressOfFirstHalf={in_AddressGoWithInstruction[`AddressBusWidth-1:1],1'b1}; //indicate there is a valid long branch with link
end
else
begin
t2a <= {4'b1011,2'b00,LongBranchWithLinkOff,cti[10:0]};//generate a bl with two 11bits offset, you must shift left 1 bit (not 2 bit as normal bl)to get real offset
Next_LongBranchWithLinkOff=LongBranchWithLinkOff; //preserve the high bits because the later stage may not being able to go
Next_AddressOfFirstHalf=AddressOfFirstHalf;
end
end
else //UnConditional Branch
t2a <= {4'b1010,{13{cti[10]}},cti[10:0]} ;//?
//Mian: This is not true conversion to ARM. Because in
//ARM branches are Word Aligned i.e [1:0] == 00
//But in Thumb branches are Halfword aligned i.e [0] == 0
//So when Branch inst executes in Thumb, use (offset << 1), instead
//(offset << 2) as in ARM state.
end
//+++++++++++++++++++++//
default : t2a <= {28'b000_1101_0_0000_0000_00000_00_0_0000}; //MOV R0,R0
endcase
if(in_ChangePC==1'b1 || in_MEMChangePC==1'b1)
begin
Next_LongBranchWithLinkOff=11'b0000_0000_000;
Next_AddressOfFirstHalf=`AddressBusZero;
end
end
//-----------------------------------------------------------//
// Joining The Condition and Opcode //
//-----------------------------------------------------------//
assign arm_inst = {cond,t2a} ;
//ssy add 2001 7 20
always @(posedge clock or negedge reset)
begin
if(reset==1'b0)
begin
LongBranchWithLinkOff=11'b0000_0000_000;
AddressOfFirstHalf=`AddressBusZero;
end
else
begin
LongBranchWithLinkOff=Next_LongBranchWithLinkOff;
AddressOfFirstHalf=Next_AddressOfFirstHalf;
end
end
endmodule
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -