plc基本指令的编程实验,侯集实验中学
终极管理员 知识笔记 545阅读
在借鉴了友佬的代码后终于是跑通了测试。
1.
2.

4.
5.
6.
还需要改一个

assign sr64_result {{32{op_sra & alu_src1[31]}}, alu_src1[31:0]} >> alu_src2[4:0]; //rj >> i5
代码 mycpu_top.v module mycpu_top( input wire clk, input wire resetn, // inst sram interface output wire inst_sram_we, output wire [31:0] inst_sram_addr, output wire [31:0] inst_sram_wdata, input wire [31:0] inst_sram_rdata, // data sram interface output wire data_sram_we, output wire [31:0] data_sram_addr, output wire [31:0] data_sram_wdata, input wire [31:0] data_sram_rdata, // trace debug interface output wire [31:0] debug_wb_pc, output wire [ 3:0] debug_wb_rf_we, output wire [ 4:0] debug_wb_rf_wnum, output wire [31:0] debug_wb_rf_wdata);reg reset;always (posedge clk) reset < ~resetn;reg valid;always (posedge clk) begin if (reset) begin valid < 1b0; end else begin valid < 1b1; endendwire [31:0] seq_pc;wire [31:0] nextpc;wire br_taken;wire [31:0] br_target;wire [31:0] inst;reg [31:0] pc;wire [11:0] alu_op;wire load_op;wire src1_is_pc;wire src2_is_imm;wire res_from_mem;wire dst_is_r1;wire gr_we;wire mem_we;wire src_reg_is_rd;wire [4: 0] dest;wire [31:0] rj_value;wire [31:0] rkd_value;wire [31:0] imm;wire [31:0] br_offs;wire [31:0] jirl_offs;wire [ 5:0] op_31_26;wire [ 3:0] op_25_22;wire [ 1:0] op_21_20;wire [ 4:0] op_19_15;wire [ 4:0] rd;wire [ 4:0] rj;wire [ 4:0] rk;wire [11:0] i12;wire [19:0] i20;wire [15:0] i16;wire [25:0] i26;wire [63:0] op_31_26_d;wire [15:0] op_25_22_d;wire [ 3:0] op_21_20_d;wire [31:0] op_19_15_d;wire inst_add_w;wire inst_sub_w;wire inst_slt;wire inst_sltu;wire inst_nor;wire inst_and;wire inst_or;wire inst_xor;wire inst_slli_w;wire inst_srli_w;wire inst_srai_w;wire inst_addi_w;wire inst_ld_w;wire inst_st_w;wire inst_jirl;wire inst_b;wire inst_bl;wire inst_beq;wire inst_bne;wire inst_lu12i_w;wire need_ui5;wire need_si12;wire need_si16;wire need_si20;wire need_si26;wire src2_is_4;wire [ 4:0] rf_raddr1;wire [31:0] rf_rdata1;wire [ 4:0] rf_raddr2;wire [31:0] rf_rdata2;wire rf_we ;wire [ 4:0] rf_waddr;wire [31:0] rf_wdata;wire [31:0] alu_src1 ;wire [31:0] alu_src2 ;wire [31:0] alu_result ;wire [31:0] final_result;wire [31:0] mem_result;assign seq_pc pc 32h4;assign nextpc br_taken ? br_target : seq_pc;always (posedge clk) begin if (reset) begin pc < 32h1bfffffc; //trick: to make nextpc be 0x1c000000 during reset end else begin pc < nextpc; endendassign inst_sram_we 1b0;assign inst_sram_addr pc;assign inst_sram_wdata 32b0;assign inst inst_sram_rdata;assign op_31_26 inst[31:26];assign op_25_22 inst[25:22];assign op_21_20 inst[21:20];assign op_19_15 inst[19:15];assign rd inst[ 4: 0];assign rj inst[ 9: 5];assign rk inst[14:10];assign i12 inst[21:10];assign i20 inst[24: 5];assign i16 inst[25:10];assign i26 {inst[ 9: 0], inst[25:10]};decoder_6_64 u_dec0(.in(op_31_26 ), .out(op_31_26_d ));decoder_4_16 u_dec1(.in(op_25_22 ), .out(op_25_22_d ));decoder_2_4 u_dec2(.in(op_21_20 ), .out(op_21_20_d ));decoder_5_32 u_dec3(.in(op_19_15 ), .out(op_19_15_d ));assign inst_add_w op_31_26_d[6h00] & op_25_22_d[4h0] & op_21_20_d[2h1] & op_19_15_d[5h00];assign inst_sub_w op_31_26_d[6h00] & op_25_22_d[4h0] & op_21_20_d[2h1] & op_19_15_d[5h02];assign inst_slt op_31_26_d[6h00] & op_25_22_d[4h0] & op_21_20_d[2h1] & op_19_15_d[5h04];assign inst_sltu op_31_26_d[6h00] & op_25_22_d[4h0] & op_21_20_d[2h1] & op_19_15_d[5h05];assign inst_nor op_31_26_d[6h00] & op_25_22_d[4h0] & op_21_20_d[2h1] & op_19_15_d[5h08];assign inst_and op_31_26_d[6h00] & op_25_22_d[4h0] & op_21_20_d[2h1] & op_19_15_d[5h09];assign inst_or op_31_26_d[6h00] & op_25_22_d[4h0] & op_21_20_d[2h1] & op_19_15_d[5h0a];assign inst_xor op_31_26_d[6h00] & op_25_22_d[4h0] & op_21_20_d[2h1] & op_19_15_d[5h0b];assign inst_slli_w op_31_26_d[6h00] & op_25_22_d[4h1] & op_21_20_d[2h0] & op_19_15_d[5h01];assign inst_srli_w op_31_26_d[6h00] & op_25_22_d[4h1] & op_21_20_d[2h0] & op_19_15_d[5h09];assign inst_srai_w op_31_26_d[6h00] & op_25_22_d[4h1] & op_21_20_d[2h0] & op_19_15_d[5h11];assign inst_addi_w op_31_26_d[6h00] & op_25_22_d[4ha];assign inst_ld_w op_31_26_d[6h0a] & op_25_22_d[4h2];assign inst_st_w op_31_26_d[6h0a] & op_25_22_d[4h6];assign inst_jirl op_31_26_d[6h13];assign inst_b op_31_26_d[6h14];assign inst_bl op_31_26_d[6h15];assign inst_beq op_31_26_d[6h16];assign inst_bne op_31_26_d[6h17];assign inst_lu12i_w op_31_26_d[6h05] & ~inst[25];assign alu_op[ 0] inst_add_w | inst_addi_w | inst_ld_w | inst_st_w | inst_jirl | inst_bl;// assign alu_op[ 0] inst_add_w | inst_addi_w | inst_ld_w | inst_st_w// | inst_jirl | inst_bl | inst_b | inst_beq | inst_bne;assign alu_op[ 1] inst_sub_w;assign alu_op[ 2] inst_slt;assign alu_op[ 3] inst_sltu;assign alu_op[ 4] inst_and;assign alu_op[ 5] inst_nor;assign alu_op[ 6] inst_or;assign alu_op[ 7] inst_xor;assign alu_op[ 8] inst_slli_w;assign alu_op[ 9] inst_srli_w;assign alu_op[10] inst_srai_w;assign alu_op[11] inst_lu12i_w;assign need_ui5 inst_slli_w | inst_srli_w | inst_srai_w;assign need_si12 inst_addi_w | inst_ld_w | inst_st_w;assign need_si16 inst_jirl | inst_beq | inst_bne;assign need_si20 inst_lu12i_w;assign need_si26 inst_b | inst_bl;assign src2_is_4 inst_jirl | inst_bl;//看看是不是要加4.assign imm src2_is_4 ? 32h4 : need_si20 ? {i20[19:0], 12b0} :/*need_ui5 || need_si12*/{{20{i12[11]}}, i12[11:0]} ;assign br_offs need_si26 ? {{ 4{i26[25]}}, i26[25:0], 2b0} : {{14{i16[15]}}, i16[15:0], 2b0} ;// assign br_offs {32{need_si26}} & {{ 4{i26[25]}}, i26[25:0], 2b0} |// {32{need_si16}} & {{14{i16[15]}}, i16[15:0], 2b0} ;assign jirl_offs {{14{i16[15]}}, i16[15:0], 2b0};assign src_reg_is_rd inst_beq | inst_bne | inst_st_w ;assign load_op inst_ld_w;// 从这两个信号可以看出不同类型的指令数据通路是不一样的assign src1_is_pc inst_jirl | inst_bl;assign src2_is_imm inst_slli_w | inst_srli_w | inst_srai_w | inst_addi_w | inst_ld_w | inst_st_w | inst_lu12i_w| inst_jirl | inst_bl ;assign res_from_mem inst_ld_w;assign dst_is_r1 inst_bl;// 是否需要写入通用寄存器assign gr_we ~inst_st_w & ~inst_beq & ~inst_bne & ~inst_b;assign mem_we inst_st_w;assign dest dst_is_r1 ? 5d1 : rd;assign rf_raddr1 rj;assign rf_raddr2 src_reg_is_rd ? rd :rk;regfile u_regfile( .clk (clk ), .raddr1 (rf_raddr1), .rdata1 (rf_rdata1), .raddr2 (rf_raddr2), .rdata2 (rf_rdata2), .we (rf_we ), .waddr (rf_waddr ), .wdata (rf_wdata ) );assign rj_value rf_rdata1;assign rkd_value rf_rdata2;assign rj_eq_rd (rj_value rkd_value);assign br_taken ( inst_beq && rj_eq_rd || inst_bne && !rj_eq_rd || inst_jirl || inst_bl || inst_b ) && valid;assign br_target (inst_beq || inst_bne || inst_bl || inst_b) ? (pc br_offs) : /*inst_jirl*/ (rj_value jirl_offs);assign alu_src1 src1_is_pc ? pc[31:0] : rj_value;assign alu_src2 src2_is_imm ? imm : rkd_value;alu u_alu( .alu_op (alu_op ), .alu_src1 (alu_src1 ),//alu_src2 .alu_src2 (alu_src2 ), .alu_result (alu_result) );assign data_sram_we mem_we && valid;assign data_sram_addr alu_result;assign data_sram_wdata rkd_value;assign mem_result data_sram_rdata;assign final_result res_from_mem ? mem_result : alu_result;assign rf_we gr_we;assign rf_waddr dest;assign rf_wdata final_result;// debug info generateassign debug_wb_pc pc;assign debug_wb_rf_we {4{rf_we}};assign debug_wb_rf_wnum dest;assign debug_wb_rf_wdata final_result;endmodule
alu.v module alu( input wire [11:0] alu_op, input wire [31:0] alu_src1, input wire [31:0] alu_src2, output wire [31:0] alu_result);wire op_add; //add operationwire op_sub; //sub operationwire op_slt; //signed compared and set less thanwire op_sltu; //unsigned compared and set less thanwire op_and; //bitwise andwire op_nor; //bitwise norwire op_or; //bitwise orwire op_xor; //bitwise xorwire op_sll; //logic left shiftwire op_srl; //logic right shiftwire op_sra; //arithmetic right shiftwire op_lui; //Load Upper Immediate// control code decompositionassign op_add alu_op[ 0];assign op_sub alu_op[ 1];assign op_slt alu_op[ 2];assign op_sltu alu_op[ 3];assign op_and alu_op[ 4];assign op_nor alu_op[ 5];assign op_or alu_op[ 6];assign op_xor alu_op[ 7];assign op_sll alu_op[ 8];assign op_srl alu_op[ 9];assign op_sra alu_op[10];assign op_lui alu_op[11];wire [31:0] add_sub_result;wire [31:0] slt_result;wire [31:0] sltu_result;wire [31:0] and_result;wire [31:0] nor_result;wire [31:0] or_result;wire [31:0] xor_result;wire [31:0] lui_result;wire [31:0] sll_result;wire [63:0] sr64_result;wire [31:0] sr_result;// 32-bit adderwire [31:0] adder_a;wire [31:0] adder_b;wire adder_cin;wire [31:0] adder_result;wire adder_cout;assign adder_a alu_src1;assign adder_b (op_sub | op_slt | op_sltu) ? ~alu_src2 : alu_src2; //src1 - src2 rj-rkassign adder_cin (op_sub | op_slt | op_sltu) ? 1b1 : 1b0;assign {adder_cout, adder_result} adder_a adder_b adder_cin;// ADD, SUB resultassign add_sub_result adder_result;// SLT resultassign slt_result[31:1] 31b0; //rj < rk 1assign slt_result[0] (alu_src1[31] & ~alu_src2[31]) | ((alu_src1[31] ~^ alu_src2[31]) & adder_result[31]);// SLTU resultassign sltu_result[31:1] 31b0;assign sltu_result[0] ~adder_cout;// bitwise operationassign and_result alu_src1 & alu_src2;assign or_result alu_src1 | alu_src2;assign nor_result ~or_result;assign xor_result alu_src1 ^ alu_src2;assign lui_result alu_src2;// SLL resultassign sll_result alu_src1 << alu_src2[4:0]; //rj << i5// assign sll_result alu_src2 << alu_src1[4:0]; // SRL, SRA resultassign sr64_result {{32{op_sra & alu_src1[31]}}, alu_src1[31:0]} >> alu_src2[4:0]; //rj >> i5assign sr_result sr64_result[31:0];// final result muxassign alu_result ({32{op_add|op_sub}} & add_sub_result) | ({32{op_slt }} & slt_result) | ({32{op_sltu }} & sltu_result) | ({32{op_and }} & and_result) | ({32{op_nor }} & nor_result) | ({32{op_or }} & or_result) | ({32{op_xor }} & xor_result) | ({32{op_lui }} & lui_result) | ({32{op_sll }} & sll_result) | ({32{op_srl|op_sra}} & sr_result);endmodule
标签: