?? risc16f84_clk2x.v
字號:
wire addr_aux_adr_hi;
wire addr_aux_dat;
wire addr_sram;
// Other output registers (for removing hazards)
reg ram_we_reg; // data-sram write strobe
reg aux_we_reg; // AUX write strobe
// Synchronizers
reg inte_sync_reg;
// Signals used in "main_efsm" procedure
// (Intermediate nodes used for resource sharing.)
wire [7:0] ram_i_node; // result of reading RAM/Special registers
wire [12:0] inc_pc_node; // value of PC + 1
wire [7:0] mask_node; // bit mask for logical operations
wire [8:0] add_node; // result of 8bit addition
wire [4:0] addlow_node; // result of low-4bit addition
wire temp; // Placeholder wire
wire dtemp; // Placeholder wire
wire aluout_zero_node; // H if ALUOUT = 0
reg [7:0] aluout; // result of calculation
reg writew_node; // H if destination is W register
reg writeram_node; // H if destination is RAM/Special registers
reg int_node; // Used in Q4_PP to indicate interrupt condition
//--------------------------------------------------------------------------
// Instantiations
//--------------------------------------------------------------------------
//--------------------------------------------------------------------------
// Functions & Tasks
//--------------------------------------------------------------------------
//--------------------------------------------------------------------------
// Module code
//--------------------------------------------------------------------------
// CPU synchronizers
always @(posedge clk_i)
begin
if (clk_en_i) // Global clock enable
begin
inte_sync_reg <= inte;
end
end
// Decode OPcode (see pp.54 of PIC16F84 data sheet)
// only 1 signal of the following signals will be '1'
assign inst_call = (inst_reg[13:11] == 3'b100 );
assign inst_goto = (inst_reg[13:11] == 3'b101 );
assign inst_bcf = (inst_reg[13:10] == 4'b0100 );
assign inst_bsf = (inst_reg[13:10] == 4'b0101 );
assign inst_btfsc = (inst_reg[13:10] == 4'b0110 );
assign inst_btfss = (inst_reg[13:10] == 4'b0111 );
assign inst_movlw = (inst_reg[13:10] == 4'b1100 );
assign inst_retlw = (inst_reg[13:10] == 4'b1101 );
assign inst_sublw = (inst_reg[13:9] == 5'b11110 );
assign inst_addlw = (inst_reg[13:9] == 5'b11111 );
assign inst_iorlw = (inst_reg[13:8] == 6'b111000 );
assign inst_andlw = (inst_reg[13:8] == 6'b111001 );
assign inst_xorlw = (inst_reg[13:8] == 6'b111010 );
assign inst_subwf = (inst_reg[13:8] == 6'b000010 );
assign inst_decf = (inst_reg[13:8] == 6'b000011 );
assign inst_iorwf = (inst_reg[13:8] == 6'b000100 );
assign inst_andwf = (inst_reg[13:8] == 6'b000101 );
assign inst_xorwf = (inst_reg[13:8] == 6'b000110 );
assign inst_addwf = (inst_reg[13:8] == 6'b000111 );
assign inst_movf = (inst_reg[13:8] == 6'b001000 );
assign inst_comf = (inst_reg[13:8] == 6'b001001 );
assign inst_incf = (inst_reg[13:8] == 6'b001010 );
assign inst_decfsz = (inst_reg[13:8] == 6'b001011 );
assign inst_rrf = (inst_reg[13:8] == 6'b001100 );
assign inst_rlf = (inst_reg[13:8] == 6'b001101 );
assign inst_swapf = (inst_reg[13:8] == 6'b001110 );
assign inst_incfsz = (inst_reg[13:8] == 6'b001111 );
assign inst_movwf = (inst_reg[13:7] == 7'b0000001 );
assign inst_clrw = (inst_reg[13:7] == 7'b0000010 );
assign inst_clrf = (inst_reg[13:7] == 7'b0000011 );
assign inst_ret = (inst_reg[13:0] == 14'b00000000001000);
assign inst_retfie = (inst_reg[13:0] == 14'b00000000001001);
assign inst_sleep = (inst_reg[13:0] == 14'b00000001100011);
// Calculate RAM access address (see pp.19 of PIC16F84 data sheet)
// if "d"=0, indirect addressing is used, so RAM address is BANK+FSR
// otherwise, RAM address is BANK+"d"
// (see pp.19 of PIC16F84 data sheet)
assign ram_adr_node = (inst_reg[6:0]==0)?{status_reg[7],fsr_reg[7:0]}:
{status_reg[6:5],inst_reg[6:0]};
// check if this is an access to external RAM or not
assign addr_sram = (ram_adr_node[6:0] > 7'b0001011); //0CH-7FH,8CH-FFH
// check if this is an access to special register or not
// only 1 signal of the following signals will be '1'
assign addr_pcl = (ram_adr_node[6:0] == 7'b0000010); // 02H, 82H
assign addr_stat = (ram_adr_node[6:0] == 7'b0000011); // 03H, 83H
assign addr_fsr = (ram_adr_node[6:0] == 7'b0000100); // 04H, 84H
assign addr_aux_dat = (ram_adr_node[7:0] == 8'b00001000); // 08H
assign addr_pclath = (ram_adr_node[6:0] == 7'b0001010); // 0AH, 8AH
assign addr_intcon = (ram_adr_node[6:0] == 7'b0001011); // 0BH, 8BH
assign addr_option = (ram_adr_node[7:0] == 8'b10000001); // 81H
assign addr_aux_adr_lo = (ram_adr_node[7:0] == 8'b00000101); // 05H
assign addr_aux_adr_hi = (ram_adr_node[7:0] == 8'b00000110); // 06H
// construct bit-mask for logical operations and bit tests
assign mask_node = 1 << inst_reg[9:7];
// 1. Intermediate nodes for resource sharing
// 1-2. PC + 1
assign inc_pc_node = pc_reg + 1;
// Tri-state drivers instead of a huge selector... It produces smaller
// results, and runs faster.
assign ram_i_node = (addr_sram) ?ram_dat_i:8'bZ;
assign ram_i_node = (addr_pcl) ?pc_reg[7:0]:8'bZ;
assign ram_i_node = (addr_stat) ?status_reg:8'bZ;
assign ram_i_node = (addr_fsr) ?fsr_reg:8'bZ;
assign ram_i_node = (addr_aux_dat) ?aux_dat_io:8'bZ;
assign ram_i_node = (addr_pclath) ?{3'b0,pclath_reg}:8'bZ;
assign ram_i_node = (addr_intcon) ?intcon_reg:8'bZ;
assign ram_i_node = (addr_option) ?option_reg:8'bZ;
assign ram_i_node = (addr_aux_adr_lo) ?aux_adr_lo_reg:8'bZ;
assign ram_i_node = (addr_aux_adr_hi) ?aux_adr_hi_reg:8'bZ;
// 1-3. Adder (ALU)
// full 8bit-addition, with carry in/out.
assign {add_node,temp} = {1'b0,aluinp1_reg,1'b1}
+ {1'b0,aluinp2_reg,c_in};
// lower 4bit-addition
assign {addlow_node,dtemp} = {1'b0,aluinp1_reg[3:0],1'b1}
+ {1'b0,aluinp2_reg[3:0],c_in};
// 1-4. Test if aluout = 0
assign aluout_zero_node = (aluout == 0)?1:0;
// 1-5. Determine destination
always @(
intstart_reg
or inst_reg
or inst_movwf
or inst_bcf
or inst_bsf
or inst_clrf
or inst_movlw
or inst_addlw
or inst_sublw
or inst_andlw
or inst_iorlw
or inst_xorlw
or inst_retlw
or inst_clrw
or inst_movf
or inst_swapf
or inst_addwf
or inst_subwf
or inst_andwf
or inst_iorwf
or inst_xorwf
or inst_decf
or inst_incf
or inst_rlf
or inst_rrf
or inst_decfsz
or inst_incfsz
or inst_comf
)
begin
if (intstart_reg)
begin
writew_node <= 0;
writeram_node <= 0;
end
else if (inst_movwf || inst_bcf || inst_bsf || inst_clrf)
begin
writew_node <= 0;
writeram_node <= 1;
end
else if ( inst_movlw || inst_addlw || inst_sublw || inst_andlw
|| inst_iorlw || inst_xorlw || inst_retlw || inst_clrw)
begin
writew_node <= 1;
writeram_node <= 0;
end
else if ( inst_movf || inst_swapf || inst_addwf || inst_subwf
|| inst_andwf || inst_iorwf || inst_xorwf || inst_decf
|| inst_incf || inst_rlf || inst_rrf || inst_decfsz
|| inst_incfsz || inst_comf)
begin
writew_node <= ~inst_reg[7]; // ("d" field of fetched instruction)
writeram_node <= inst_reg[7]; // ("d" field of fetched instruction)
end
else
begin
writew_node <= 0;
writeram_node <= 0;
end
end // End of determine destination logic
// 2-4-1. Calculation and store result into alu-output register
always @(
add_node
or aluinp1_reg
or aluinp2_reg
or status_reg
or inst_reg
or inst_movwf
or inst_bcf
or inst_bsf
or inst_btfsc
or inst_btfss
or inst_clrf
or inst_movlw
or inst_addlw
or inst_sublw
or inst_andlw
or inst_iorlw
or inst_xorlw
or inst_retlw
or inst_clrw
or inst_movf
or inst_swapf
or inst_addwf
or inst_subwf
or inst_andwf
or inst_iorwf
or inst_xorwf
or inst_decf
or inst_incf
or inst_rlf
or inst_rrf
or inst_decfsz
or inst_incfsz
or inst_comf
)
begin
// 2-4-1-1. Set aluout register
// Rotate left
if (inst_rlf)
aluout <= {aluinp1_reg[6:0],status_reg[0]};
// Rotate right
else if (inst_rrf)
aluout <= {status_reg[0],aluinp1_reg[7:1]};
// Swap nibbles
else if (inst_swapf)
aluout <= {aluinp1_reg[3:0],aluinp1_reg[7:4]};
// Logical inversion
else if (inst_comf)
aluout <= ~aluinp1_reg;
// Logical AND, bit clear/bit test
else if ( inst_andlw || inst_andwf || inst_bcf || inst_btfsc
|| inst_btfss)
aluout <= (aluinp1_reg & aluinp2_reg);
// Logical OR, bit set
else if (inst_bsf || inst_iorlw || inst_iorwf)
aluout <= (aluinp1_reg | aluinp2_reg);
// Logical XOR
else if (inst_xorlw || inst_xorwf)
aluout <= (aluinp1_reg ^ aluinp2_reg);
// Addition, Subtraction, Increment, Decrement
else if ( inst_addlw || inst_addwf || inst_sublw || inst_subwf
|| inst_decf || inst_decfsz || inst_incf || inst_incfsz)
aluout <= add_node[7:0];
// Pass through
else aluout <= aluinp1_reg;
end
// MAIN EFSM: description of register value changes in each clock cycle
always @(posedge clk_i)
begin
if (clk_en_i)
begin
// 2. EFSM body
case (state_reg)
// 2-1. Reset state (see pp.14 and pp.42 of PIC16F84 data sheet)
QRESET_PP :
begin
pc_reg <= 0; // 0
status_reg[7:5] <= 3'b0;
pclath_reg <= 0; // 0
intcon_reg[7:1] <= 7'b0;
option_reg <= -1; // Set to all ones, like vhdl (others => 1)
aux_adr_lo_reg <= 0;
aux_adr_hi_reg <= 0;
exec_op_reg <= 0;
intclr_reg <= 1; // clear int
intstart_reg <= 0;
ram_we_reg <= 0;
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -