?? risc16f84_clk2x.v
字號(hào):
sleepflag_reg <= 0;
status_reg[4] <= 1; // /T0 = 1
status_reg[3] <= 1; // /PD = 1
stack_pnt_reg <= 0; // Reset stack pointer
// go to Q2 state if reset signal is de-asserted
if (~reset_i) state_reg <= Q2_PP;
end // End of QRESET_PP state
// 2-3. Q2 cycle
Q2_PP :
begin
ram_we_reg <= 0; // Default to not writing (Can be overridden below)
aux_we_reg <= 0; // Default to not writing (Can be overridden below)
// 2-3-1. Read data-RAM and substitute source values to alu-input regs
if (exec_op_reg && ~intstart_reg && ~sleepflag_reg) // Not stalled
begin
// 2-3-1-1. Set aluinp1 register (source #1)
if ( inst_movf || inst_swapf || inst_addwf || inst_subwf
|| inst_andwf || inst_iorwf || inst_xorwf || inst_decf
|| inst_incf || inst_rlf || inst_rrf || inst_bcf
|| inst_bsf || inst_btfsc || inst_btfss || inst_decfsz
|| inst_incfsz || inst_comf)
aluinp1_reg <= ram_i_node; // RAM/Special registers
else
if ( inst_movlw || inst_addlw || inst_sublw || inst_andlw
|| inst_iorlw || inst_xorlw || inst_retlw)
aluinp1_reg <= inst_reg[7:0]; // Immediate value ("k")
else
if ( inst_clrf || inst_clrw) aluinp1_reg <= 0; // 0
else aluinp1_reg <= w_reg; // W register
// 2-3-1-2. Set aluinp2 register (source #2)
c_in <= 0; // Default to no carry in.
if (inst_decf || inst_decfsz) aluinp2_reg <= -1; // for decr.
else if (inst_incf || inst_incfsz) aluinp2_reg <= 1; // for incr.
// -1 * W register (for subtract)
else if (inst_sublw || inst_subwf)
begin
aluinp2_reg <= ~w_reg + 1;
c_in <= 1; // Set c_in for subtract operations (makes C come out).
end
// operation of BCF: AND with inverted mask ("1..101..1")
// mask for BCF: value of only one position is 0
else if (inst_bcf) aluinp2_reg <= ~mask_node;
// operation of BSF: OR with mask_node ("0..010..0")
// operation of FSC and FSS: AND with mask_node, compare to 0
else if (inst_btfsc || inst_btfss || inst_bsf)
aluinp2_reg <= mask_node;
else aluinp2_reg <= w_reg; // W register
// 2-3-1-3. Set stack pointer register (pop stack)
if (inst_ret || inst_retlw || inst_retfie)
stack_pnt_reg <= stack_pnt_reg - 1; // cycles 3,2,1,0,7,6...
// 2-4-1-3. Set data-SRAM write enable (hazard-free)
if (writeram_node && addr_sram) ram_we_reg <= 1;
if (writeram_node && addr_aux_dat) aux_we_reg <= 1;
end // End of "if not stalled"
// 2-3-4. Goto next cycle
if (reset_i) state_reg <= QRESET_PP;
// if in sleep mode, wait until wake-up trigger comes
else if (sleepflag_reg && ~intstart_reg) // Sleeping, not stalled
begin
if (inte_sync_reg)
begin
// if rb0/inte interrupt comes, then resume execution
sleepflag_reg <= 0;
state_reg <= Q2_PP;
end
end
else state_reg <= Q4_PP;
end // End of Q2 state
// 2-5. Q4 cycle
Q4_PP :
begin
int_node <= 0; // Default state is: no interrupt request
if (exec_op_reg && ~intstart_reg) // if NOT STALLED
begin
// 2-4-1-2. Set C flag and DC flag
if (inst_addlw || inst_addwf || inst_sublw || inst_subwf)
begin
status_reg[1] <= addlow_node[4]; // DC flag
status_reg[0] <= add_node[8]; // C flag
end
else if (inst_rlf) status_reg[0] <= aluinp1_reg[7]; // C flag
else if (inst_rrf) status_reg[0] <= aluinp1_reg[0]; // C flag
end
// 2-4-2. Check external interrupt and set int. flag
if (~intstart_reg && intcon_reg[7]) // GIE
begin
// PORT-B0 INT
if (inte_sync_reg)
begin
intcon_reg[1] <= 1; // set INTF
intclr_reg <= 1; // clear external int-register
// (intrise_reg and intdown_reg)
int_node <= 1; // Flag ensures that PC is held, and that
// GIE bit is set appropriately by logic
// further "downstream" within this state.
end
end
if (~exec_op_reg && ~intstart_reg) // if STALLED (not interrupt)
begin
pc_reg <= inc_pc_node; // increment PC
exec_op_reg <= 1; // end of stall
end
else // if NOT stalled
begin
// (note: if intstart_reg, only stack/pc-operations in this
// else-clause will be performed)
// 2-5-2. Store calculation result into destination,
// set PC and flags, and determine if execute next cycle.
// 2-5-2-1. Set W register, if not in stall cycle
// (~intstart_reg) and destination is W
// writew_node == 0 if intstart_reg...
if (writew_node) w_reg <= aluout; // write W reg
// 2-5-2-2. Set data RAM/special registers,
// if not in stall cycle (~intstart_reg)
if (writeram_node)
begin
if (addr_stat)
begin
status_reg[7:5] <= aluout[7:5]; // write IRP,RP1,RP0
// status(4),status(3)...unwritable, see below (/PD,/T0 part)
status_reg[1:0] <= aluout[1:0]; // write DC,C
end
if (addr_fsr) fsr_reg <= aluout; // write FSR
if (addr_pclath) pclath_reg <= aluout[4:0]; // write PCLATH
if (addr_intcon) intcon_reg[6:0] <= aluout[6:0];
// write INTCON (except GIE)
// intcon(7)...see below (GIE part)
if (addr_option) option_reg <= aluout; // write OPTION
if (addr_aux_adr_lo) aux_adr_lo_reg <= aluout; // write AUX low
if (addr_aux_adr_hi) aux_adr_hi_reg <= aluout; // write AUX high
end
// 2-5-2-3. Set/clear Z flag, if not in stall cycle (~intstart_reg)
if (~intstart_reg)
begin
if (addr_stat) status_reg[2] <= aluout[2]; // (dest. is Z flag)
else if ( inst_addlw || inst_addwf || inst_andlw || inst_andwf
|| inst_clrf || inst_clrw || inst_comf || inst_decf
|| inst_incf || inst_movf || inst_sublw || inst_subwf
|| inst_xorlw || inst_xorwf || inst_iorlw || inst_iorwf )
status_reg[2] <= aluout_zero_node; // Z=1 if result == 0
end
// 2-5-2-4. Set PC and determine whether to execute next cycle or not
// After interrupt-stall cycle ends, jump to interrupt vector
if (intstart_reg)
begin
pc_reg <= 4; // (interrupt vector)
exec_op_reg <= 0; // the next cycle is a stall cycle
end
else if (inst_ret || inst_retlw || inst_retfie) // "return" instr.
begin
pc_reg <= stack_reg[stack_pnt_reg];
exec_op_reg <= 0; // the next cycle is stall cycle
end
else if (inst_goto || inst_call) // "goto/call" instructions
begin
// (see pp.18 of PIC16F84 data sheet)
pc_reg <= {pclath_reg[4:3],inst_reg[10:0]};
exec_op_reg <= 0;
end
else if ( ( (inst_btfsc || inst_decfsz || inst_incfsz)
&& aluout_zero_node)
|| (inst_btfss && ~aluout_zero_node)
) // bit_test instrcutions
begin
pc_reg <= inc_pc_node;
exec_op_reg <= 0;
// the next cycle is stall cycle, if test conditions are met.
end
else if (writeram_node && addr_pcl) // PCL is data-destination
begin
// (see pp.18 of PIC16F84 data sheet)
pc_reg <= pclath_reg[4:0] & aluout;
exec_op_reg <= 0;
end
else
begin
// this check MUST be located AFTER the above if/else sentences
// check if interrupt trigger comes
if (~int_node) pc_reg <= inc_pc_node;
// if not, the next instr. fetch/exec. will be performed normally
else pc_reg <= pc_reg;
// if so, value of PC must be held
//(will be pushed onto stack at the end of next instruction cycle)
exec_op_reg <= 1;
end
// 2-5-2-5. Push current PC value into stack, if necessary
if (inst_call || intstart_reg)
// CALL instr. or End of interrupt-stall cycle
begin
stack_reg[stack_pnt_reg] <= pc_reg; // write PC value
stack_pnt_reg <= stack_pnt_reg + 1; // increment stack pointer
end
// 2-5-2-6. Set GIE bit in intcon register (intcon_reg(7))
if (~intstart_reg)
begin
if (int_node) // interrupt trigger comes
begin
intcon_reg[7] <= 0; // clear GIE
intstart_reg <= 1; // the next cycle is interrupt-stall cycle
end
else if (inst_retfie) // "return from interrupt" instruction
begin
intcon_reg[7] <= 1;
intstart_reg <= 0;
end
else if (writeram_node && addr_intcon) // destination is GIE
begin
intcon_reg[7] <= aluout[7];
intstart_reg <= 0;
end
else intstart_reg <= 0;
end
else intstart_reg <= 0;
// 2-5-2-7. Enter sleep mode if needed. (No need to set /TO and /PD)
if (~intstart_reg && inst_sleep) sleepflag_reg <= 1;
end // (if not stalled)
// 2-5-3. Clear data-SRAM write enable (hazard-free)
ram_we_reg <= 0;
aux_we_reg <= 0;
// 2-5-1. Fetch next program-instruction
inst_reg <= prog_dat_i;
// 2-5-6. Goto next cycle
if (reset_i) state_reg <= QRESET_PP;
else state_reg <= Q2_PP;
end // End of Q4 state
// 2-6. Illegal states (NEVER REACHED in normal execution)
default : state_reg <= QRESET_PP; // goto reset state
endcase;
end // End of global clock enable
end // End of process
// Detect external interrupt requests
// INT0 I/F
always @(posedge int0_i or posedge intclr_reg)
begin
if (intclr_reg) intrise_reg <= 0;
else intrise_reg <= 1; // catch positive edge
end // process
always @(negedge int0_i or posedge intclr_reg)
begin
if (intclr_reg) intdown_reg <= 0;
else intdown_reg <= 1; // catch negative edge
end // process
assign rb0_int = option_reg[6]?intrise_reg:intdown_reg;
// Decode INT triggers
// (do not AND with GIE(intcon_reg(7)), since these signals are
// also used for waking up from SLEEP)
assign inte = intcon_reg[4] && rb0_int; // G0IE and raw-trigger signal
// Circuit's output signals
assign prog_adr_o = pc_reg; // program ROM address
assign ram_adr_o = ram_adr_node; // data RAM address
assign ram_dat_o = aluout; // data RAM write data
assign ram_we_o = ram_we_reg; // data RAM write enable
assign aux_adr_o = {aux_adr_hi_reg,aux_adr_lo_reg};
assign aux_dat_io = (aux_we_reg && clk_en_i)?aluout:{8{1'bZ}};
assign aux_we_o = aux_we_reg;
endmodule
//`undef STATEBIT_SIZE
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -