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

📄 risc_core.v

📁 pic cpu source code. it is writed in the verilog source code. it can work on the 40Mhz high speed.
💻 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 w
always @(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;
   endcase

always @(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 sfr
reg	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
   end

assign	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 now
always @(posedge clk)	w_we	<= #1 w_we_;	// working register write 0 enable

always @(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 Composite

always @(posedge clk)
	rf_we1		<= #1 valid & rf_we_;			// register file write enable 1

always @(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 3

always @(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 PC
always @(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
   end

always @(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_;
   end

assign invalidate_0_ = (pc_call_ | pc_goto_ | pc_retlw_ | pc_we_);

always @(posedge clk)
   	invalidate_0	<= #1 invalidate_0_;

// Status bits WE
always @(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 connections
assign	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 Logic

always @(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 + -