📄 risc_core.v
字号:
// Byte Oriented RF Operations I_ADDWF: alu_op <= #1 ALU_ADD; // ADDWF I_ANDWF: alu_op <= #1 ALU_AND; // ANDWF I_CLRF: alu_op <= #1 ALU_CLR; // CLRF I_CLRW: alu_op <= #1 ALU_CLR; // CLRW I_COMF: alu_op <= #1 ALU_NOT; // COMF I_DEC: alu_op <= #1 ALU_DEC; // DEC I_DECFSZ: alu_op <= #1 ALU_DEC; // DECFSZ I_INCF: alu_op <= #1 ALU_INC; // INCF I_INCFSZ: alu_op <= #1 ALU_INC; // INCFSZ I_IORWF: alu_op <= #1 ALU_IOR; // IORWF I_MOV: alu_op <= #1 ALU_MOV; // MOV I_MOVWF: alu_op <= #1 ALU_MOVW; // MOVWF I_RLF: alu_op <= #1 ALU_RLF; // RLF I_RRF: alu_op <= #1 ALU_RRF; // RRF I_SUBWF: alu_op <= #1 ALU_SUB; // SUBWF I_SWAPF: alu_op <= #1 ALU_SWP; // SWAPF I_XORWF: alu_op <= #1 ALU_XOR; // XORWF // Bit Oriented RF Operations I_BCF: alu_op <= #1 ALU_BCF; // BCF I_BSF: alu_op <= #1 ALU_BSF; // BSF // Literal & Controll Operations I_ANDLW: alu_op <= #1 ALU_AND; // ANDLW I_IORLW: alu_op <= #1 ALU_IOR; // IORLW I_MOVLW: alu_op <= #1 ALU_MOV; // MOWLW I_RETLW: alu_op <= #1 ALU_MOV; // RETLW I_XORLW: alu_op <= #1 ALU_XOR; // XORLW endcase// Source Select// This CPU source 1 can be one of: rf (or sfr) or k,// second source (if any) is always walways @(instr_0) casex(instr_0) // synopsys full_case parallel_case I_ANDLW: src1_sel_ = K_SEL; I_CALL: src1_sel_ = K_SEL; I_GOTO: src1_sel_ = K_SEL; I_IORLW: src1_sel_ = K_SEL; I_MOVLW: src1_sel_ = K_SEL; I_RETLW: src1_sel_ = K_SEL; I_XORLW: src1_sel_ = K_SEL; default: src1_sel_ = ( (instr_0[4:3]==2'h0) & (instr_0[2:0] != 3'h0 )) ? SFR_SEL : RF_SEL; endcasealways @(posedge clk) src1_sel <= #1 src1_sel_[0];// Destination Select// Destination can be one of: rf, w, option, tris OR one of sfr registers: // indf, tmr0, pc, status, fsr, porta, portb, portc, option, trisa, trisb, trisc// Stage 1// select w, pc, rf or sfrreg w_we1, w_we1_;always @(instr_0) begin casex(instr_0) // synopsys full_case parallel_case I_ADDWF, I_ANDWF, I_COMF, I_DEC, I_DECFSZ, I_INCF, I_INCFSZ, I_IORWF, I_MOV, I_RLF, I_RRF, I_SUBWF, I_SWAPF, I_XORWF: // w or f w_we1_ = 1; default: w_we1_ = 0; endcase end always @(instr_0) begin w_we_ = 0; rf_we_ = 0; sfr_we_ = 0; tris_we_= 0; casex(instr_0) // synopsys full_case parallel_case I_ADDWF, I_ANDWF, I_COMF, I_DEC, I_DECFSZ, I_INCF, I_INCFSZ, I_IORWF, I_MOV, I_RLF, I_RRF, I_SUBWF, I_SWAPF, I_XORWF: // w or f begin rf_we_ = instr_0[5] & (instr_0[4] | instr_0[3]); sfr_we_ = instr_0[5] & ~instr_0[4] & ~instr_0[3]; end I_MOVWF, I_CLRF, I_BCF, I_BSF: // only f begin rf_we_ = instr_0[4] | instr_0[3]; sfr_we_ = ~instr_0[4] & ~instr_0[3]; end I_CLRW, I_IORLW, I_MOVLW, I_ANDLW, I_RETLW, I_XORLW: w_we_ = 1; // only w I_TRIS: tris_we_ = 1; // trisa or trisb or trisc endcase endassign indf_we_ = sfr_we_ & (instr_0[2:0] == INDF_ADDR);assign pc_we_ = sfr_we_ & (instr_0[2:0] == PCL_ADDR);// Stage 2 destination encoder// write enable outputs are registered nowalways @(posedge clk) w_we <= #1 w_we_; // working register write 0 enablealways @(posedge clk) w_we1 <= #1 w_we1_; // working register write 1 enable// Register File Write Enable is composed of thee conditions: 1) direct register writing (0x10-0x1f);// 2) Direct Global Register writing (0x08-0x0f), and 3) Indirect Register File Writing// The logic has been partitioned and balanced between the decode and execute stage ...assign rf_we = rf_we1 | (rf_we2 & rf_we3); // register file write enable Compositealways @(posedge clk) rf_we1 <= #1 valid & rf_we_; // register file write enable 1always @(posedge clk) rf_we2 <= #1 valid & (fsr_next[4] | fsr_next[3]);// register file write enable 2 always @(posedge clk) rf_we3 <= #1 indf_we_; // register file write enable 3always @(posedge clk) wdt_clr <= #1 instr_0[11:0] == I_CLRWDT;always @(posedge clk) opt_we <= #1 instr_0[11:0] == I_OPTION;always @(posedge clk) trisa_we <= #1 tris_we_ & (instr_0[2:0] == PORTA_ADDR);always @(posedge clk) trisb_we <= #1 tris_we_ & (instr_0[2:0] == PORTB_ADDR);always @(posedge clk) trisc_we <= #1 tris_we_ & (instr_0[2:0] == PORTC_ADDR);always @(posedge clk) begin // SFR registers tmr0_we <= #1 sfr_we_ & (instr_0[2:0] == TMR0_ADDR); pc_we <= #1 valid & pc_we_; stat_we <= #1 valid & sfr_we_ & (instr_0[2:0] == STAT_ADDR); fsr_we <= #1 valid & sfr_we_ & (instr_0[2:0] == FSR_ADDR); porta_we <= #1 sfr_we_ & (instr_0[2:0] == PORTA_ADDR); portb_we <= #1 sfr_we_ & (instr_0[2:0] == PORTB_ADDR); portc_we <= #1 sfr_we_ & (instr_0[2:0] == PORTC_ADDR); end// Instructions that directly modify PCalways @(instr_0) begin pc_skz_ = 0; pc_bset_ = 0; pc_bclr_ = 0; pc_call_ = 0; pc_goto_ = 0; pc_retlw_ = 0; casex(instr_0) // synopsys full_case parallel_case // Byte Oriented RF Operations I_DECFSZ, I_INCFSZ: pc_skz_ = 1; // Bit Oriented RF Operations I_BTFSS: pc_bset_ = 1; I_BTFSC: pc_bclr_ = 1; // Literal & Controll Operations I_CALL: pc_call_ = 1; I_GOTO: pc_goto_ = 1; I_RETLW: pc_retlw_ = 1; endcase endalways @(posedge clk) begin pc_skz <= #1 valid & pc_skz_; pc_bset <= #1 valid & pc_bset_; pc_bclr <= #1 valid & pc_bclr_; pc_call <= #1 valid & pc_call_; pc_goto <= #1 valid & pc_goto_; pc_retlw <= #1 valid & pc_retlw_; endassign invalidate_0_ = (pc_call_ | pc_goto_ | pc_retlw_ | pc_we_);always @(posedge clk) invalidate_0 <= #1 invalidate_0_;// Status bits WEalways @(posedge clk) begin stat_bwe <= #1 0; if(valid) casex(instr_0) // synopsys full_case parallel_case // Byte Oriented RF Operations I_ADDWF: stat_bwe <= #1 STAT_WR_C | STAT_WR_DC | STAT_WR_Z; I_ANDWF: stat_bwe <= #1 STAT_WR_Z; I_CLRF: stat_bwe <= #1 STAT_WR_Z; I_CLRW: stat_bwe <= #1 STAT_WR_Z; I_COMF: stat_bwe <= #1 STAT_WR_Z; I_DEC: stat_bwe <= #1 STAT_WR_Z; I_INCF: stat_bwe <= #1 STAT_WR_Z; I_IORWF: stat_bwe <= #1 STAT_WR_Z; I_MOV: stat_bwe <= #1 STAT_WR_Z; I_RLF: stat_bwe <= #1 STAT_WR_C; I_RRF: stat_bwe <= #1 STAT_WR_C; I_SUBWF: stat_bwe <= #1 STAT_WR_C | STAT_WR_DC | STAT_WR_Z; I_XORWF: stat_bwe <= #1 STAT_WR_Z; // Literal & Controll Operations I_ANDLW: stat_bwe <= #1 STAT_WR_Z; //I_CLRWDT: // Modifies TO & PD *** FIX ME *** I_IORLW: stat_bwe <= #1 STAT_WR_Z; //I_SLEEP: // Modifies TO & PD *** FIX ME *** I_XORLW: stat_bwe <= #1 STAT_WR_Z; endcase end////////////////////////////////////////////////////////////////////////// Wr & Execute Logic (including PC)// Second Pipeline Stage////////////////////////////////////////////////////////////////////////// Source OP Sel//assign src1 = src1_sel ? rf_rd_data : sfr_rd_data;mux2_8 u3( .sel(src1_sel), .in0(sfr_rd_data), .in1(rf_rd_data), .out(src1) );alu u4( .s1( src1 ), .s2( w ), .mask( mask ), .out( dout ), .op( alu_op ), .c_in( status[0] ), .c( c_out ), .dc( dc_out ), .z( z_out ) );// Register file connectionsassign rf_wr_bnk = fsr[6:5];assign rf_wr_addr = (instr_1[4:0]==0) ? fsr[4:0] : instr_1[4:0];assign rf_wr_data = dout;wire [7:0] status_next2;// Deal with all special registers (SFR) writes/*always @(rst or status or stat_we or stat_bwe or dout or c_out or dc_out or z_out) if(rst) status_next = STAT_RST_VALUE; else begin status_next = status; // Default Keep Value if(stat_we) status_next = dout | 8'h18; else begin if(stat_bwe[0]) status_next[0] = c_out; if(stat_bwe[1]) status_next[1] = dc_out; if(stat_bwe[2]) status_next[2] = z_out; end end*/assign status_next2[0] = stat_bwe[0] ? c_out : status[0];assign status_next2[1] = stat_bwe[1] ? dc_out : status[1];assign status_next2[2] = stat_bwe[2] ? z_out : status[2];mux2_8 u21( .sel(stat_we), .in1( {dout | 8'h18} ), .in0( {status[7:3],status_next2[2:0]} ), .out(status_next) );always @(posedge clk) if(rst) status <= #1 STAT_RST_VALUE; else status <= #1 status_next;//assign fsr_next = fsr_we ? dout[6:0] : fsr;mux2_7 u31( .sel(fsr_we), .in1(dout[6:0]), .in0(fsr), .out(fsr_next) );always @(posedge clk) if(rst) fsr <= #1 FSR_RST_VALUE; else fsr <= #1 fsr_next;always @(posedge clk) if(valid_1 & (w_we | (w_we1 & ~instr_1[5])) ) w <= #1 dout;always @(posedge clk) if(rst) trisa <= #1 TRIS_RST_VALUE; else if(trisa_we & valid_1) trisa <= #1 w;always @(posedge clk) if(rst) trisb <= #1 TRIS_RST_VALUE; else if(trisb_we & valid_1) trisb <= #1 w;always @(posedge clk) if(rst) trisc <= #1 TRIS_RST_VALUE; else if(trisc_we & valid_1) trisc <= #1 w;always @(posedge clk) if(rst) option <= #1 OPT_RST_VALUE; else if(opt_we & valid_1) option <= #1 w[5:0];always @(posedge clk) if(porta_we & valid_1) portaout <= #1 dout;always @(posedge clk) if(portb_we & valid_1) portbout <= #1 dout;always @(posedge clk) if(portc_we & valid_1) portcout <= #1 dout;always @(posedge clk) begin porta_r <= #1 portain; portb_r <= #1 portbin; portc_r <= #1 portcin; end///////////////////////////////////////////////////////////////////////// Timer Logic//assign tmr0_next = tmr0_we ? dout : tmr0_cnt_en ? tmr0_plus_1 : tmr0;//assign tmr0_next = tmr0_we ? dout : tmr0_cnt_en ? (tmr0 + 1) : tmr0;mux2_8 u5( .sel(tmr0_we & valid_1), .in0(tmr0_next1), .in1(dout), .out(tmr0_next) );mux2_8 u6( .sel(tmr0_cnt_en), .in0(tmr0), .in1(tmr0_plus_1), .out(tmr0_next1) );inc8 u7( .in(tmr0), .out(tmr0_plus_1) );always @(posedge clk) tmr0 <= #1 tmr0_next;presclr_wdt u8( .clk( clk ), .rst( rst ), .tcki( tcki ), .option( option[5:0] ), .tmr0_we( tmr0_we & valid_1 ), .tmr0_cnt_en( tmr0_cnt_en ), .wdt_en( wdt_en ), .wdt_clr( wdt_clr & valid_1 ), .wdt_to( wdt_to ) );////////////////////////////////////////////////////////////////////////// Programm Counter Logicalways @(posedge clk) pc_r2 <= #1 pc_r;// 'inst_addr' is a duplication of the 'pc'. The only time when it is really needed// is when the program memory is not on the chip and we want to place the registers// directly in the IO pads to reduce Tcq (For example in a Xilinx FPGA implementation).// If the program memory is on the chip or if the implmentation allows feedback from// registers in the IO cells, this is not needed. Synopsys FPGA compiler appears to// make the correct decission either way, and gett rid of unneded logic ...always @(posedge clk) if(rst) inst_addr <= #1 PC_RST_VECTOR; else inst_addr <= #1 pc_next;always @(posedge clk) if(rst) pc <= #1 PC_RST_VECTOR; else pc <= #1 pc_next;/*always @(pc_plus_1 or dout or pc_we or status or stack_out or pc_call or pc_goto or pc_retlw or instr_1) if(pc_we) pc_next = {status[6:5], 1'b0, dout}; else if(!pc_call & !pc_goto & !pc_retlw) pc_next = pc_plus_1; else if(pc_call) pc_next = {status[6:5], 1'b0, instr_1[7:0]}; else if(pc_goto) pc_next = {status[6:5], instr_1[8:0]}; else if(pc_retlw) pc_next = stack_out;*/wire [10:0] pc_tmp1, pc_tmp2, pc_tmp3;wire pc_sel1;assign pc_tmp1 = {status[6:5], 1'b0, dout[7:0]};assign pc_tmp2 = {status[6:5], 1'b0, instr_1[7:0]};assign pc_tmp3 = {status[6:5], instr_1[8:0]};assign pc_sel1 = (!pc_call & !pc_goto & !pc_retlw);mux2_11 u9 ( .sel(pc_we), .in0(pc_next1), .in1(pc_tmp1), .out(pc_next) );mux2_11 u10( .sel(pc_sel1), .in0(pc_next2), .in1(pc_plus_1), .out(pc_next1) );mux2_11 u11( .sel(pc_call), .in0(pc_next3), .in1(pc_tmp2), .out(pc_next2) );mux2_11 u12( .sel(pc_goto), .in0(stack_out), .in1(pc_tmp3), .out(pc_next3) );inc11 u13( .in(pc), .out(pc_plus_1) );reg invalidate_1_r1, invalidate_1_r2;assign invalidate_1 = (pc_skz & z_out) | (pc_bset & bit_sel) | (pc_bclr & !bit_sel) | (invalidate_0 & valid_1) | invalidate_1_r1;always @(posedge clk) begin invalidate_1_r1 <= #1 (invalidate_0 & valid_1) | invalidate_1_r2; invalidate_1_r2 <= #1 (invalidate_0 & valid_1); end//assign bit_sel = src1[ instr_1[7:5] ];mux8_1 u22( .sel(instr_1[7:5]), .in(src1), .out(bit_sel) );sfifo4x11 u14( .clk(clk), .push(pc_call), .din(pc_r2), .pop(pc_retlw), .dout(stack_out) );endmodule
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -