/* Copyright (c) 2006-2011 by Lattice Semiconductor Corporation Name: lm8_idec.v Description: Instruction decoder Permission: Lattice Semiconductor grants permission to use this code for use in synthesis for any Lattice programmable logic product. Other use of this code, including the selling or duplication of any portion is strictly prohibited. Disclaimer: This VHDL or Verilog source code is intended as a design reference which illustrates how these types of functions can be implemented. It is the user's responsibility to verify their design for consistency and functionality through the use of formal verification methods. Lattice Semiconductor provides no warranty regarding the use or functionality of this code. Lattice Semiconductor Corporation 5555 NE Moore Court Hillsboro, OR 97124 U.S.A TEL: 1-800-Lattice (USA and Canada) 408-826-6000 (other locations) web: http://www.latticesemi.com/ email: techsupport@latticesemi.com */ module lm8_idec #( parameter PROM_AW=10 ) ( input [17:0] instr, output reg imi_instr, output reg sub, output reg subc, output reg add, output reg addc, output reg mov, output reg andr, output reg orr, output reg xorr, output reg cmp, output reg test, output reg ror1, output reg rorc, output reg rol1, output reg rolc, output reg clrc, output reg setc, output reg clrz, output reg setz, output reg clri, output reg seti, output reg bz, output reg bnz, output reg bc, output reg bnc, output reg b, output reg callz, output reg callnz, output reg callc, output reg callnc, output reg call, output reg ret, output reg iret, output reg export_, output reg import_, output reg exporti, output reg importi, output reg ssp, output reg lsp, output reg sspi, output reg lspi, output reg wcsr, output reg rcsr, output reg [4:0] addr_rb, output reg [4:0] addr_rd, output reg [7:0] imi_data, output reg [PROM_AW -1:0] addr_jmp, output reg update_c, output reg update_z ); reg instr_l1_0, instr_l1_1, instr_l1_2, instr_l1_3; reg instr_l2_0, instr_l2_1, instr_l2_2, instr_l2_3; reg instr_l3_0, instr_l3_1; reg instr_l4_0, instr_l4_1; reg instr_l5_0, instr_l5_1, instr_l5_2, instr_l5_3; reg instr_l6_0, instr_l6_1; reg instr_l7_0, instr_l7_1, instr_l7_2, instr_l7_3; reg ro; reg sc; reg br0; reg ca0, ca1; reg re; reg iels; reg iels_ie; reg iels_ls; always @(/*AUTOSENSE*/instr) begin // Level 1 decodes of bits [17:16] instr_l1_0 = (~instr[17] & ~instr[16]); instr_l1_1 = (~instr[17] & instr[16]); instr_l1_2 = (instr[17] & ~instr[16]); instr_l1_3 = (instr[17] & instr[16]); // Level 2 decodes of bits [15:14] instr_l2_0 = (~instr[15] & ~instr[14]); instr_l2_1 = (~instr[15] & instr[14]); instr_l2_2 = (instr[15] & ~instr[14]); instr_l2_3 = (instr[15] & instr[14]); // Level 3 decodes of bits [13] instr_l3_0 = ~instr[13]; instr_l3_1 = instr[13]; // Level 4 decodes of bits [12] instr_l4_0 = ~instr[12]; instr_l4_1 = instr[12]; // Level 5 decodes of bits [11:10] instr_l5_0 = (~instr[11] & ~instr[10]); instr_l5_1 = (~instr[11] & instr[10]); instr_l5_2 = (instr[11] & ~instr[10]); instr_l5_3 = (instr[11] & instr[10]); // Level 6 decodes of bits [2] instr_l6_0 = ~instr[2]; instr_l6_1 = instr[2]; // Level 7 decodes of bits [1:0] instr_l7_0 = (~instr[1] & ~instr[0]); instr_l7_1 = (~instr[1] & instr[0]); instr_l7_2 = (instr[1] & ~instr[0]); instr_l7_3 = (instr[1] & instr[0]); end always @(/*AUTOSENSE*/instr or instr_l1_0 or instr_l1_1 or instr_l1_2 or instr_l1_3 or instr_l2_0 or instr_l2_1 or instr_l2_2 or instr_l2_3 or instr_l3_0 or instr_l3_1 or instr_l4_0 or instr_l4_1 or instr_l6_0 or instr_l6_1 or instr_l7_0 or instr_l7_1 or instr_l7_2 or instr_l7_3) begin // Immidiate operand instruction de imi_instr = instr_l3_1; // Decodes for sub* instructions sub = instr_l1_0 & instr_l2_0; subc = instr_l1_0 & instr_l2_1; // Decodes for add* instructions add = instr_l1_0 & instr_l2_2; addc = instr_l1_0 & instr_l2_3; // Decodes for mov* instructions mov = instr_l1_1 & instr_l2_0; // Decodes for logic* instructions andr = instr_l1_1 & instr_l2_1; orr = instr_l1_1 & instr_l2_2; xorr = instr_l1_1 & instr_l2_3; // Decodes for compare/test instructions cmp = instr_l1_2 & instr_l2_0; test = instr_l1_2 & instr_l2_1; // Decodes for rotate instructions ro = instr_l1_2 & instr_l2_2 & instr_l3_0; ror1 = ro & instr_l7_0; rorc = ro & instr_l7_2; rol1 = ro & instr_l7_1; rolc = ro & instr_l7_3; // Decodes for set/clear instructions sc = instr_l1_2 & instr_l2_3 & instr_l3_0; clrc = sc & instr_l6_0 & instr_l7_0; setc = sc & instr_l6_0 & instr_l7_1; clrz = sc & instr_l6_0 & instr_l7_2; setz = sc & instr_l6_0 & instr_l7_3; clri = sc & instr_l6_1 & instr_l7_0; seti = sc & instr_l6_1 & instr_l7_1; // Decodes for import/export instructions iels = instr_l1_2 & instr_l2_3 & instr_l3_1; iels_ie = iels & instr_l6_0; export_ = iels_ie & instr_l7_0; import_ = iels_ie & instr_l7_1; exporti = iels_ie & instr_l7_2; importi = iels_ie & instr_l7_3; // Decodes for load/store instructions iels_ls = iels & instr_l6_1; ssp = iels_ls & instr_l7_0; lsp = iels_ls & instr_l7_1; sspi = iels_ls & instr_l7_2; lspi = iels_ls & instr_l7_3; // Decodes for branch instructions br0 = instr_l1_3 & instr_l2_0; bz = br0 & instr_l3_0 & instr_l4_0; bnz = br0 & instr_l3_0 & instr_l4_1; bc = br0 & instr_l3_1 & instr_l4_0; bnc = br0 & instr_l3_1 & instr_l4_1; // Decodes for call instructions ca0 = instr_l1_3 & instr_l2_1; callz = ca0 & instr_l3_0 & instr_l4_0; callnz = ca0 & instr_l3_0 & instr_l4_1; callc = ca0 & instr_l3_1 & instr_l4_0; callnc = ca0 & instr_l3_1 & instr_l4_1; // Decodes for unconditional branch/call/return instructions re = instr_l1_3 & instr_l2_2; ca1 = instr_l1_3 & instr_l2_2; call = ca1 & instr_l3_0 & instr_l4_0; ret = re & instr_l3_0 & instr_l4_1; iret = re & instr_l3_1 & instr_l4_0; b = ca1 & instr_l3_1 & instr_l4_1; // Decodes for control & status instructions rcsr = instr_l1_2 & instr_l2_3 & instr_l3_0 & instr_l6_1 & instr_l7_2; wcsr = instr_l1_2 & instr_l2_3 & instr_l3_0 & instr_l6_1 & instr_l7_3; // Rd address addr_rd = instr[12:8]; // Rb address addr_rb = instr[7:3]; // Constant data from immidiate instructions imi_data = instr[7:0]; // Enable Carry/Zero Flag update update_c = (instr_l1_0 | ( instr_l1_2 & ~instr_l2_3 & instr[1]) | (instr_l1_2 & instr_l2_0)); update_z = (instr_l1_0 | // add/sub (instr_l1_1 & ~instr_l2_0) | // and/or/xor ro | // rotate cmp | // compare test); // test // setz and clrz do not activate update_z, but are used directly // by the async_z logic in lm8_flow_ctrl. end // Label from branch/call instructions generate if (PROM_AW <= 12) always @(instr) addr_jmp = instr[PROM_AW-1:0]; else always @(instr) addr_jmp = {{PROM_AW-12{instr[11]}},instr[11:0]}; endgenerate endmodule