⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 risc_core.v

📁 嵌入式操作系统的基本输入输出程序
💻 V
📖 第 1 页 / 共 2 页
字号:
					// 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 + -