OpenCores
URL https://opencores.org/ocsvn/oks8/oks8/trunk

Subversion Repositories oks8

[/] [oks8/] [trunk/] [rtl/] [verilog/] [oks8_decoder.v] - Rev 10

Compare with Previous | Blame | View Log

//                              -*- Mode: Verilog -*-
// Filename        : oks8_decoder.v
// Description     : OKS8 Decoder & Controller with Microcode
// Author          : Jian Li
// Created On      : Sat Jan 07 09:09:49 2006
// Last Modified By: .
// Last Modified On: .
// Update Count    : 0
// Status          : Unknown, Use with caution!
 
/*
 * Copyright (C) 2006 to Jian Li
 * Contact: kongzilee@yahoo.com.cn
 * 
 * This source file may be used and distributed without restriction
 * provided that this copyright statement is not removed from the file
 * and that any derivative works contain the original copyright notice
 * and the associated disclaimer.
 * 
 * THIS SOFTWARE IS PROVIDE "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT
 * SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */
 
`include "oks8_defines.v"
 
//////////////////////////////////////////////////////
 
module oks8_decoder (/*AUTOARG*/
  // Inputs
  clk_i, rst_i, op_i, en_i,
  // Outputs
  dp_o,
  fin_o,
  dx_den,
  dx_alu,
  dx_sts,
  dx_r1, dx_r1_t,
  dx_r2, dx_r2_t,
  dx_r3
  );
 
// Inputs
input clk_i, rst_i, en_i;
input [7:0] op_i;
 
// Outputs
output [1:0] dp_o;
output fin_o;
output dx_den;
output [3:0] dx_alu;
output [1:0] dx_sts;
output [7:0] dx_r1;
output [2:0] dx_r1_t;
output [7:0] dx_r2;
output [2:0] dx_r2_t;
output [15:0] dx_r3;
 
// =====================================================================
// REGISTER/WIRE DECLARATIONS
// =====================================================================
wire [1:0] next;
reg [1:0] nextf;
reg state;
wire fin_o;
 
reg [7:0] op, r1, r2;
reg [15:0] r3;
 
wire [3:0] r1_p, r2_p, x_p;
wire [7:0] r2_im;
 
// OPCODE FLAGS
wire f_idle,	// 1 byte
	f_stop,
	f_di,
	f_ei,
	f_ret,
	f_iret,
	f_rcf,
	f_scf,
	f_ccf,
	f_nop,
	f_inc_rE,
 
	f_dec,		// 2 bytes
	f_rlc,
	f_inc,
	f_jp_2,
	f_pop,
	f_com,
	f_push,
	f_rl,
	f_clr,
	f_rrc,
	f_sra,
	f_rr,
 
	f_add_2,
	f_adc_2,
	f_sub_2,
	f_sbc_2,
	f_or_2,
	f_and_2,
	f_tcm_2,
	f_tm_2,
	f_cp_2,
	f_xor_2,
 
	f_ldc_C3,
	f_ldc_D3,
	f_ld_C7,
	f_ld_D7,
	f_ldcx,
	f_call_F4,
	f_ld_r8,
	f_ld_r9,
	f_ld_rC,
	f_jr_ccB,
 
	f_add_3,	// 3 bytes
	f_adc_3,
	f_sub_3,
	f_sbc_3,
	f_or_3,
	f_and_3,
	f_tcm_3,
	f_tm_3,
	f_cp_3,
	f_xor_3,
 
	f_ld_87,
	f_ld_97,
	f_ld_D6,
	f_ld_E4,
	f_ld_E5,
	f_ld_E6,
	f_ldc_E7,
	f_ld_F5,
	f_call_F6,
	f_ldc_F7,
	f_jp_ccD,
 
	f_ldc_A7,	// 4 bytes
	f_ldc_B7,
 
	f_op_0,		// OPCODE = X0/X1
	f_op_1,		// OPCODE = X2/X3
	f_op_2;		// OPCODE = X4/X5/X6
 
assign f_op_0	= (op[3:1] == 3'b000);
assign f_op_1	= (op[3:1] == 3'b001);
assign f_op_2	= (op[3:2] == 2'b01 && op[1:0] != 2'b11);
 
// =====================================================================
// CONTROL FLAGS
// Flags depending on OPCODE. Only 1 Flag will be active.
// =====================================================================
assign f_idle	= (op == 8'h6F);
assign f_stop	= (op == 8'h7F);
assign f_di		= (op == 8'h8F);
assign f_ei		= (op == 8'h9F);
assign f_ret	= (op == 8'hAF);
assign f_iret	= (op == 8'hBF);
assign f_rcf	= (op == 8'hCF);
assign f_scf	= (op == 8'hDF);
assign f_ccf	= (op == 8'hEF);
assign f_nop	= (op == 8'hFF);
assign f_inc_rE	= (op[3:0] == 4'hE);
 
assign f_dec	= (op[7:4] == 4'h0 && f_op_0);
assign f_rlc	= (op[7:4] == 4'h1 && f_op_0);
assign f_inc	= (op[7:4] == 4'h2 && f_op_0);
assign f_jp_2	= (op == 8'h30);
assign f_pop	= (op[7:4] == 4'h5 && f_op_0);
assign f_com	= (op[7:4] == 4'h6 && f_op_0);
assign f_push	= (op[7:4] == 4'h7 && f_op_0);
assign f_rl		= (op[7:4] == 4'h9 && f_op_0);
assign f_clr	= (op[7:4] == 4'hB && f_op_0);
assign f_rrc	= (op[7:4] == 4'hC && f_op_0);
assign f_sra	= (op[7:4] == 4'hD && f_op_0);
assign f_rr 	= (op[7:4] == 4'hE && f_op_0);
 
assign f_add_2	= (op[7:4] == 4'h0 && f_op_1);
assign f_adc_2	= (op[7:4] == 4'h1 && f_op_1);
assign f_sub_2	= (op[7:4] == 4'h2 && f_op_1);
assign f_sbc_2	= (op[7:4] == 4'h3 && f_op_1);
assign f_or_2	= (op[7:4] == 4'h4 && f_op_1);
assign f_and_2	= (op[7:4] == 4'h5 && f_op_1);
assign f_tcm_2	= (op[7:4] == 4'h6 && f_op_1);
assign f_tm_2	= (op[7:4] == 4'h7 && f_op_1);
assign f_cp_2	= (op[7:4] == 4'hA && f_op_1);
assign f_xor_2	= (op[7:4] == 4'hB && f_op_1);
 
assign f_ldc_C3	= (op == 8'hC3);
assign f_ldc_D3	= (op == 8'hD3);
assign f_ld_C7	= (op == 8'hC7);
assign f_ld_D7	= (op == 8'hD7);
assign f_ldcx	= (op[7:4] == 4'hE && f_op_1);
assign f_call_F4	= (op == 8'hF4);
assign f_ld_r8	= (op[3:0] == 4'h8);
assign f_ld_r9	= (op[3:0] == 4'h9);
assign f_ld_rC	= (op[3:0] == 4'hC);
assign f_jr_ccB	= (op[3:0] == 4'hB);
 
assign f_add_3	= (op[7:4] == 4'h0 && f_op_2);
assign f_adc_3	= (op[7:4] == 4'h1 && f_op_2);
assign f_sub_3	= (op[7:4] == 4'h2 && f_op_2);
assign f_sbc_3	= (op[7:4] == 4'h3 && f_op_2);
assign f_or_3	= (op[7:4] == 4'h4 && f_op_2);
assign f_and_3	= (op[7:4] == 4'h5 && f_op_2);
assign f_tcm_3	= (op[7:4] == 4'h6 && f_op_2);
assign f_tm_3	= (op[7:4] == 4'h7 && f_op_2);
assign f_cp_3	= (op[7:4] == 4'hA && f_op_2);
assign f_xor_3	= (op[7:4] == 4'hB && f_op_2);
 
assign f_ld_87	= (op == 8'h87);
assign f_ld_97	= (op == 8'h97);
assign f_ld_D6	= (op == 8'hD6);
assign f_ld_E4	= (op == 8'hE4);
assign f_ld_E5	= (op == 8'hE5);
assign f_ld_E6	= (op == 8'hE6);
assign f_ldc_E7	= (op == 8'hE7);
assign f_ld_F5	= (op == 8'hF5);
assign f_call_F6	= (op == 8'hF6);
assign f_ldc_F7	= (op == 8'hF7);
assign f_jp_ccD	= (op[3:0] == 4'hD);
 
assign f_ldc_A7	= (op == 8'hA7);
assign f_ldc_B7	= (op == 8'hB7);
 
assign next = (f_ldc_A7 | f_ldc_B7) ? 4 : (
	f_add_3 | f_adc_3 | f_sub_3 | f_sbc_3 | f_or_3 | f_and_3 |
	f_tcm_3 | f_tm_3 | f_cp_3 | f_xor_3 | f_ld_87 | f_ld_97 |
	f_ld_D6 | f_ld_E4 | f_ld_E5 | f_ld_E6 | f_ldc_E7 | f_ld_F5 |
	f_call_F6 | f_ldc_F7 | f_jp_ccD) ? 3 : (
	f_dec | f_rlc | f_inc | f_jp_2 | f_pop | f_com | f_push | f_rl | f_clr |
	f_rrc | f_sra | f_rr | f_add_2 | f_adc_2 | f_sub_2 | f_sbc_2 | f_or_2 |
	f_and_2 | f_tcm_2 | f_tm_2 | f_cp_2 | f_xor_2 | f_ldc_C3 | f_ldc_D3 |
	f_ld_C7 | f_ld_D7 | f_ldcx | f_call_F4 | f_ld_r8 | f_ld_r9 | f_ld_rC |
	f_jr_ccB) ? 2 : 1;
 
// =====================================================================
// SYSTEM INTERFACE
// Indicate here is finish.
// =====================================================================
assign fin_o = (en_i) && (next == nextf);
 
// =====================================================================
// POWER INTERFACE
// CONTROL SIGNALS FOR POWER INTERFACE
// =====================================================================
assign dp_o[1] = f_stop;
assign dp_o[0] = f_idle | f_stop;
 
// =====================================================================
// EXECUTE INTERFACE
// CONTROL SIGNALS FOR THE EXECUTE INTERFACE
// =====================================================================
 
//
// OPERAND CONTROL -> EXEC
// Determines where the SRC and DST operands come from
// Determines where to store the DST operand.
//
assign dx_r1_t = (f_jp_ccD) ? `DST_DA :
(	f_dec | f_rlc | f_inc | f_pop | f_com |
	f_rl | f_clr | f_rrc | f_sra | f_rr) ? ((op[0] == 0) ? `DST_R : `DST_IR) :
(	f_add_2 | f_adc_2 | f_sub_2 | f_sbc_2 | f_or_2 | f_and_2 |
	f_xor_2 | f_add_3 | f_adc_3 | f_sub_3 | f_sbc_3 | f_or_3 | f_and_3 |
	f_xor_3 | f_inc_rE | f_ld_rC | f_ld_r8 | f_ld_C7 | f_ld_87 |
	f_ldc_A7 | f_ldc_C3 | f_ldc_E7 | f_ldcx | f_ld_r9 | f_ld_E4 | f_ld_E5 | f_ld_E6) ? `DST_R :
(	f_cp_2 | f_tcm_2 | f_tm_2 | f_cp_3 | f_tcm_3 | f_tm_3 | f_rcf | f_scf | f_ccf | f_ei | f_di) ? `DST_R2 :
(	f_ld_F5 | f_ld_D7 | f_ld_D6 | f_ld_97) ? `DST_IR :
(	f_ldc_D3 | f_ldc_F7 | f_jp_2) ? `DST_IRR :
(	f_ldc_B7) ? ((dx_r1[3:1] == 3'b000) ? `DST_DA : `DST_IRR) :
(	f_push) ? `DST_PUSH : (f_call_F4 | f_call_F6) ? `DST_CALL : `DST_NON;
 
assign dx_r2_t = 
(	f_add_2 | f_adc_2 | f_sub_2 | f_sbc_2 | f_or_2 | f_and_2 | f_tcm_2 | f_tm_2 |
	f_cp_2 | f_xor_2 | f_push) ? ((op[0]) ? `SRC_IR : `SRC_R) :
(	f_add_3 | f_adc_3 | f_sub_3 | f_sbc_3 | f_or_3 | f_and_3 |
	f_tcm_3 | f_tm_3 | f_cp_3 | f_xor_3) ? 
	((op[2] & op[1]) ? `SRC_IM : ((op[0]) ? `SRC_IR : `SRC_R)) :
(	f_ld_E5 | f_ld_87 | f_ld_C7 | f_nop) ? `SRC_IR :
(	f_ld_97 | f_ld_D7  | f_ld_r9 | f_ldc_D3 |
	f_ldc_F7 | f_ldc_B7 | f_ld_E4 | f_ld_F5 | f_ld_r8) ? `SRC_R :
(	f_ldc_C3 | f_ldc_E7 | f_ldcx) ? `SRC_IRR :
(	f_ldc_A7) ? ((dx_r2[3:1] == 3'b000) ? `SRC_IRR : `SRC_DA) :
(	f_call_F4) ? `SRC_IRR :  (f_call_F6) ? `SRC_DA :
(	f_ret) ? `SRC_RET : (f_pop) ? `SRC_POP : (f_iret) ? `SRC_IRET : `SRC_IM;
 
//
// Determines the content of SRC, DST, x, XS, XL etc.
//
assign dx_r1 = (r1_p[1:0] == 2'b00) ? ((f_rcf | f_scf | f_ccf) ? `V_FLAGS :
	(f_di | f_ei) ? `V_SYM :
	((r1_p[2] == 0) ? {4'hC, op[3:0]} : {4'hC, op[7:4]})) : r1;
 
assign r2_im = (f_rcf) ? 8'h7F : (f_scf | f_ccf) ? 8'h80 :
	(f_dec | f_inc | f_com) ? 8'hFF : (f_jp_2) ? 8'h08 :
	(f_ei) ? 8'h04 : (f_di) ? 8'hFB : 8'h00;
 
assign dx_r2 = (r2_p[1:0] == 2'b00) ?
	(r2_p[3] ? {4'hC, op[7:4]} : r2_im) : r2;
 
assign dx_r3 = (f_ldcx) ? ((op[0]) ? 16'h0001 : 16'hFFFF) : r3;
 
//
// Determines access external data memory
//
assign dx_den = (f_ldc_C3 | f_ldc_E7 | f_ldcx | f_ldc_A7) ? dx_r2[0] :
	(f_ldc_D3 | f_ldc_F7 | f_ldc_B7) ? dx_r1[0] : 1'b0;
 
//
// STATUS AFFECTED -> EXEC
// Tell EXEC to affect changes to the STATUS flags or not.
//
assign dx_sts = (dx_alu[3] || (dx_alu == `ALU_SRA)) ?
	((f_dec | f_inc | f_inc_rE) ? `STS_ZSV : `STS_ALL) :
	(dx_alu[2] && !(op[3:0] == 4'hF)) ? `STS_ZS0 : `STS_NON;
 
// 
// ALU OP -> EXEC
// Determines the exact Operation to perform
//
assign dx_alu = (f_adc_2 | f_adc_3) ? `ALU_ADC :
	(f_add_2 | f_add_3 | f_dec) ? `ALU_ADD :
	(f_and_2 | f_and_3 | f_clr | f_di | f_rcf | f_tm_2 | f_tm_3) ? `ALU_AND :
	(f_jp_2 | f_jp_ccD | f_jr_ccB) ? `ALU_JP :
	(f_ldcx) ? `ALU_LDCX :
	(f_or_2 | f_or_3 | f_ei | f_scf) ? `ALU_IOR :
	(f_rl) ? `ALU_RL : (f_rlc) ? `ALU_RLC :
	(f_rr) ? `ALU_RR : (f_rrc) ? `ALU_RRC :
	(f_sbc_2 | f_sbc_3) ? `ALU_SBC : (f_sra) ? `ALU_SRA :
	(f_sub_2 | f_sub_3 | f_inc | f_inc_rE | f_cp_2 | f_cp_3) ? `ALU_SUB :
	(f_tcm_2 | f_tcm_3) ? `ALU_TCM :
	(f_xor_2 | f_xor_3 | f_ccf | f_com) ? `ALU_XOR : `ALU_NON;
 
 
// =====================================================================
// INTERNAL FLAGS
// Determines the position of SRC and DST operands
// =====================================================================
assign r1_p = (f_dec | f_rlc | f_inc | f_jp_2 | f_pop | f_com | f_rl |
	f_clr | f_rrc | f_sra | f_rr | f_ld_r9 | f_ld_E6 | f_ld_D6 | f_jr_ccB) ? 4'b0001 :	// 8, 1
(	f_add_3 | f_adc_3 | f_sub_3 | f_sbc_3 | f_or_3 | f_and_3 |
	f_tcm_3 | f_tm_3 | f_cp_3 | f_xor_3) ? ((op[1]) ? 4'b0001 : 4'b0010) :	// 8, 1 or 2
(	f_add_2 | f_adc_2 | f_sub_2 | f_sbc_2 | f_or_2 | f_and_2 |
	f_tcm_2 | f_tm_2 | f_cp_2 | f_xor_2 | f_ld_C7 | f_ld_D7 | f_ld_87 |
	f_ldc_C3 | f_ldc_E7 | f_ldc_A7 | f_ldcx) ? 4'b1101 :	// 4h, 1
(	f_ld_E4 | f_ld_E5 | f_ld_F5) ? 4'b0010 :		// 8, 2
(	f_ld_97 | f_ldc_D3 | f_ldc_F7 | f_ldc_B7) ? 4'b1001 :	// 4l, 1
	4'b1100;
 
assign r2_p = (f_push | f_ld_rC | f_ld_r8 | f_ld_E4 | f_ld_E5 |
	f_ld_F5 | f_call_F4) ? 4'b0001 :	// 8, 1
(	f_add_3 | f_adc_3 | f_sub_3 | f_sbc_3 | f_or_3 | f_and_3 |
	f_tcm_3 | f_tm_3 | f_cp_3 | f_xor_3) ? ((op[1]) ? 4'b0010 : 4'b0001) :	// 8, 1 or 2
(	f_add_2 | f_adc_2 | f_sub_2 | f_sbc_2 | f_or_2 | f_and_2 |
	f_tcm_2 | f_tm_2 | f_cp_2 | f_xor_2 | f_ld_C7 | f_ld_D7 | f_ld_87 |
	f_ldc_C3 | f_ldc_E7 | f_ldc_A7 | f_ldcx) ? 4'b1001 :		// 4l, 1
(	f_ld_97) ? 4'b1101:		// 4h, 1
(	f_ld_r9 | f_jp_ccD | f_jr_ccB) ? 4'b1100 :		// 4h, 0
(	f_ld_E6 | f_ld_D6) ? 4'b0010 :		// 8, 2
	4'b0000;
 
//
// Determines the position of x, XS, XL etc.
//
assign x_p = (f_call_F6 | f_jp_ccD) ? 4'b0110 : 4'bZZZZ;	// such as: 6D 01 53
assign x_p = (f_ld_87 | f_ld_97 | f_ldc_E7 | f_ldc_F7) ? 4'b0010 : 4'bZZZZ;
assign x_p = (f_ldc_A7 | f_ldc_B7) ? 4'b1110 : 4'bZZZZ;		// such as: A7 00 04 11
assign x_p = (f_ldc_C3 | f_ldc_D3) ? 4'b0000 : 4'bZZZZ;
 
///////////////////////////////////////////////////////
 
always @(posedge en_i)
begin
  r1 <= 8'h00;
  r2 <= 8'h00;
  r3 <= 16'h0000;
end
 
always @(posedge clk_i)
begin
  if (rst_i || (!en_i)) begin
	nextf <= 2'b01;
	state <= 0;
  end else
  if (!state)
  begin
	op <= op_i;
	nextf <= 2'b01;
	state <= 1;
  end
  else
  begin
	if (r1_p[1:0] == nextf) begin
	  if (r1_p[3] == 0)
		r1 <= op_i;
	  else begin
		if (r1_p[2] == 0)
		  r1 <= {4'hC, op_i[3:0]};
		else
		  r1 <= {4'hC, op_i[7:4]};
	  end
	end
 
	if (r2_p[1:0] == nextf) begin
	  if (r2_p[3] == 0)
		r2 <= op_i;
	  else begin
		if (r2_p[2] == 0)
		  r2 <= {4'hC, op_i[3:0]};
		else
		  r2 <= {4'hC, op_i[7:4]};
	  end
	end
 
	if (x_p[1:0] == nextf) begin
	  r3[7:0] <= op_i;
	end
	if (x_p[3:2] == nextf) begin
	  r3[15:8] <= op_i;
	end
 
	nextf <= nextf + 1'b1;
 
  end
 
end	 // always @(posedge clk_i)
 
endmodule	// oks8_decoder
 
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.