📄 arm10.v
字号:
end end end end end end endtask //Software Interrupts (SWI) task swi; begin //Store next Instruction (PC = PC+4) inst_result[0] = r15; result_dest[0] = 5'h18; result_valid[0] = 1'b1; //Store the CPSR in SPSR_svc psr_result[0] = CPSR; psr_dest[0] = 3'h2; psr_valid[0] = 1'b1; //Set SVC Mode and disable IRQ psr_result[1] = {PSR0[31:8],1'b1,PSR0[6],6'b010011}; psr_dest[1] = 3'h0; psr_valid[1] = 1'b1; //Set the PC to the SWI Vector next_pc = 32'h00000008; //Don't increment PC on next pc_touched = 1'b1; end endtask //Branch Instructions task br; reg [31:0] twosC; //2's Comp of Offset, if (-) reg [31:0] offset; //holds the shifted, s-ext offset begin offset = {{6{ir[23]}},ir[23:0],2'b00}; //Store PC if Link bit set //Actually storing PC + 4 if (ir[24] == 1'b1) begin inst_result[0] = r15+4; result_dest[0] = map(4'hE); result_valid[0] = 1'b1; end //Calculate offset (if negative) and //update the PC if (offset[31] == 1'b1) begin twosC = ~(offset) + 1; next_pc = r15 - twosC + 8; pc_touched = 1'b1; end else begin next_pc = r15 + offset + 8; pc_touched = 1'b1; end end endtask //Store Half-Word Instructions task strh; reg [31:0] data; //data to store reg [31:0] addr; //address to store reg [31:0] base; //address in base register reg [31:0] reg_offset; //offset in register reg [31:0] temp; //necessary for writing only //a half word. begin data = reg_decode(map(Rd)); base = reg_decode(map(Rn)); reg_offset = reg_decode(map(Rm)); //Calculate the Destination Address //Register Offset if (ir[22] == 1'b0) begin if (ir[23] == 1'b1) //add offset addr = base + reg_offset; else //sub offset addr = base - reg_offset; end //Immediate Offset else begin if (ir[23] == 1'b1) //add offset addr = base + {{24{1'b0}},ir[11:8],ir[3:0]}; else //sub offset addr = base - {{24{1'b0}},ir[11:8],ir[3:0]}; end //perform the store if (ir[24] == 1'b1) //pre-index begin addr_bus = addr; data_bus = {2{data[15:0]}}; end else //post-index begin addr_bus = base; data_bus = {2{data[15:0]}}; end //Perform Write-back, if necessary if ((ir[24] == 1'b0)||(ir[21] == 1'b1)) begin inst_result[0] = addr; result_dest[0] = map(Rn); result_valid[0] = 1'b1; end /*Simulate a Smart Memory System Problem with my memory is that its word-addressable This causes problems when trying to write only a half-word, or byte. To write a half word, I have to read the memory location, overwrite the specified half-word, and then write the data.*/ temp = mem[addr_bus[31:2]]; case ({BIGEND,addr_bus[1]}) 2'b00,2'b11: //word boundary temp = {temp[31:16],data_bus[15:0]}; 2'b01,2'b10: //half-word boundary temp = {data_bus[31:16],temp[15:0]}; endcase data_bus = temp; $save_store(); mem[addr_bus[31:2]] = temp; end endtask //Store Single Data Instruction task strw; reg [32:0] shifted_offset; //holds shifted offset reg [31:0] data; //data to store reg [31:0] addr; //address to store reg [31:0] base; //base address reg [31:0] reg_offset; //offset value reg [31:0] temp; //necessary for byte-addressing begin data = reg_decode(map(Rd)); //Read data8 base = reg_decode(map(Rn)); reg_offset = reg_decode(map(Rm)); //Read Offset shifted_offset = shift(reg_offset); //Shift Offset //Calculate the Destination Address //Shifted Register Offset if (ir[25] == 1'b1) begin if (ir[23] == 1'b1) //add offset addr = base + shifted_offset[31:0]; else //sub offset addr = base - shifted_offset[31:0]; end //Immediate Offset else begin if (ir[23] == 1'b1) //add offset addr = base + {{20{1'b0}},ir[11:0]}; else //sub offset addr = base - {{20{1'b0}},ir[11:0]}; end //perform the store case ({ir[24],ir[22]}) //Post Indexing, Store Word 2'b00: begin addr_bus = base; data_bus = data; end //Post Indexing, Store Byte 2'b01: begin addr_bus = base; data_bus = {4{data[7:0]}}; end //Pre Indexing, Store Word 2'b10: begin addr_bus = addr; data_bus = data; end //Pre Indexing, Store Byte 2'b11: begin addr_bus = addr; data_bus = {4{data[7:0]}}; end endcase //Perform Write-back, if necessary if ((ir[24] == 1'b0)||(ir[21] == 1'b1)) begin inst_result[0] = addr; result_dest[0] = map(Rn); result_valid[0] = 1'b1; end /*Simulate the Memory System I defined the memory system to be word addressable, so to write a byte, first the data must be read from memory. The correct byte must be overwritten, then the data written back.*/ temp = mem[addr_bus[31:2]]; if (ir[22] == 1'b0) //store word temp = data_bus; else begin //store byte case ({BIGEND,addr_bus[1:0]}) 3'b000,3'b111: temp = {temp[31:8],data_bus[7:0]}; 3'b001,3'b110: temp = {temp[31:16],data_bus[15:8],temp[7:0]}; 3'b010,3'b101: temp = {temp[31:24],data_bus[23:16],temp[15:0]}; 3'b011,3'b100: temp = {data_bus[31:24],temp[23:0]}; endcase end data_bus = temp; $save_store(); mem[addr_bus[31:2]] = temp; end endtask //Store Multiple Data Words task stm; reg [31:0] low_addr; //lowest address reg [31:0] high_addr; //higest address reg [31:0] addr; //store to address reg [3:0] reg_index; //Register index reg pre_inc_addr; //Pre-Increment integer inc_dec; //holds +/- 4 integer int_Rn; //Integer equiv. of Rn integer i; integer j; begin low_addr = reg_decode(map(Rn)); //set Base Pointer high_addr = low_addr; //initialize High Address reg_index = 4'h0; //reset index int_Rn = Rn; //set int_Rn to Rn //Increment or decrement if (ir[23] == 1'b1) //Up? inc_dec = 4; else //Down? inc_dec = -4; //Calculate High and Low Addresses for (i = 0; i <= 15; i = i+1) begin if ((ir[i] == 1'b1) && (ir[23] == 1'b0)) low_addr = low_addr + inc_dec; if ((ir[i] == 1) && (ir[23] == 1'b1)) high_addr = high_addr + inc_dec; end //Initialize Store Address, Always store //From lowest address to Highest Address addr = low_addr; //If Pre-Inc or Post-Dec - Need to //Increment Low Address before the store if (((ir[24] == 1'b1) && (ir[23] == 1'b1)) ||((ir[24] == 1'b0) && (ir[23] == 1'b0))) addr = addr + 4; // Perform the store for (j = 0; j <= 15; j = j+1) begin //Write-Back performed after First Store //If Incrementing -> high_addr, else -> low_addr if ((j == 1) && (ir[21] == 1)) begin //leaving this write, because it is necessary to //write the base back. Putting in the delay, so that //it will not screw up the checker. Checker should //not see this reg change until the next instruction. //Therefore, if the clock cycle changes length, //the delay must be changed suitably. #75; write_reg(map(Rn),(ir[23] ? high_addr : low_addr)); end if (ir[j] == 1'b1) begin if (ir[22] == 1'b1) //only transfer USR bank registers begin mem[addr[31:2]] = reg_decode({1'b0, reg_index}); addr_bus = addr; data_bus = reg_decode({1'b0, reg_index}); $save_store(); end else //transfer <mode> registers begin mem[addr[31:2]] = reg_decode(map(reg_index)); addr_bus = addr; data_bus = reg_decode(map(reg_index)); $save_store(); end //Increment address unless not supposed to if ((j != 15)||(ir[24] != 1'b1)) addr = addr + 4; end reg_index = reg_index + 1; end end endtask //Load Multiple Data Words task ldm; reg [31:0] low_addr; //lowest load address reg [31:0] high_addr; //highest address reg [31:0] addr; //store address reg [3:0] reg_index; //Register index reg r15_set; //R15 in list? integer inc_dec; //holds +/- 4 integer int_Rn; //integer equiv. of Rn integer i; integer j; begin low_addr = reg_decode(map(Rn)); //set Base Pointer high_addr = low_addr; //initialize high address addr = low_addr; //initialize reg_index = 4'h0; //reset index r15_set = ir[15]; int_Rn = Rn; //Increment or decrement if (ir[23] == 1'b1) //Up? inc_dec = 4; else //Down? inc_dec = -4; //Calculate the Highest & Lowest Addresses high_addr = low_addr; for (i = 0; i <= 15; i = i+1) begin if ((ir[i] == 1'b1) && (ir[23] == 1'b0)) low_addr = low_addr + inc_dec; if ((ir[i] == 1) && (ir[23] == 1'b1)) high_addr = high_addr + inc_dec; end //Initialize Store Address, Always store //From lowest address to Highest Address addr = low_addr; //If Pre-Inc or Post-Dec - Need to //Increment Low Address before the store if (((ir[24] == 1'b1) && (ir[23] == 1'b1)) ||((ir[24] == 1'b0) && (ir[23] == 1'b0))) addr = addr + 4; //Perform the Load Operation for (j = 0; j <= 15; j = j+1) begin //Write-Back performed after First Load //If Incrementing -> high_addr, else -> low_addr if ((j == 1) && (ir[21] == 1)) begin //leaving this write, because it is necessary to //write the base back. Putting in the delay, so that //it will not screw up the checker. Checker should //not see this reg change until the next instruction. //Therefore, if the clock cycle changes length, //the delay must be changed suitably. #75; write_reg(map(Rn),(ir[23] ? high_addr : low_addr)); end if (ir[j] == 1'b1) begin //IF S & R15, SPSR->CPSR if ((j == 15) && (ir[22] == 1)) begin psr_result[0] = psr_decode(mappsr(1'b1)); psr_dest[0] = 3'h0; psr_valid[0] = 1'b1; end //IF S & !R15, Load to User Bank Registers if ((ir[22] == 1'b1)&&(r15_set == 1'b0)) //only transfer USR bank registers begin inst_result[j] = mem[addr[31:2]]; result_dest[j] = {1'b0, reg_index}; result_valid[j] = 1'b1; data_bus = mem[addr[31:2]]; addr_bus = addr; end else //transfer <mode> registers begin inst_result[j] = mem[addr[31:2]]; result_dest[j] = map(reg_index); result_valid[j] = 1'b1; data_bus = mem[addr[31:2]]; addr_bus = addr; end /
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -