Facebook
From Little Marten, 3 Months ago, written in Plain Text.
This paste is a reply to Untitled from Edgy Motmot - go back
Embed
Viewing differences between Untitled and Re: Untitled
`include "defines.vh"
module decode_unit #(
                parameter  INSTR_WIDTH  = 16,   // instructions are 16 bits in width
                parameter  R_ADDR_WIDTH = 5

        )(
                input  wire  [INSTR_WIDTH-1:0]   instruction,
                output reg   [`OPCODE_COUNT-1:0] opcode_type,
                output wire  [`GROUP_COUNT-1:0]  opcode_group,
                output reg   [R_ADDR_WIDTH-1:0]  opcode_rd,
                output reg   [R_ADDR_WIDTH-1:0]  opcode_rr,
                output reg               [11:0]  opcode_imd,
                output reg                [2:0]  opcode_bit
        );

/*Fiindca register file-ul procesorului nostru (ATtiny20)
are doar 16 registre, putem ignora bitii Rr si Rd de pe pozitiile 9 si 8
(Atmel garanteaza ca, din motive de compatibilitate, vor fi mereu setati
pe 1, sau, echivalent, vor fi folosite numai registrele R16 ? R31).
Deci opcode = 000111rdxxxxxxxx devifne 00011111xxxxxxxx. (Btw, that's ADD)
*/

        always @* begin
                  casez (instruction)
                        16'b0000_11??_????_????: begin
                                opcode_type = `TYPE_ADD;
                                opcode_rd   = instruction[8:4];
                                opcode_rr   = {instruction[9], instruction[3:0]};
                        end
                        16'b0001_11??_????_????: begin
                                opcode_type = `TYPE_ADC;
                                opcode_rd   = instruction[8:4];
                                opcode_rr   = {instruction[9], instruction[3:0]};
                        end
                        16'b0010_00??_????_????: begin
                                opcode_type = `TYPE_AND;
                                opcode_rd   = instruction[8:4];
                                opcode_rr   = {instruction[9], instruction[3:0]};
                        end
                                16'b0010_01??_????_????: begin
                                opcode_type = `TYPE_EOR;
                                opcode_rd   = instruction[8:4];
                                opcode_rr   = {instruction[9], instruction[3:0]};
                        end
                        /* TODO 5: LD_Y */
                        16'b1000_000?_????_1000: begin
                                opcode_type = `TYPE_LD_Y;
                                opcode_rd   = instruction[8:4];
                                opcode_rr   = {R_ADDR_WIDTH{1'bx}};
                                opcode_imd  = 12'bx;
                        end
                        /* TODO 3: LDI */
                        16'b1110_????_????_????: begin
                                opcode_type = `TYPE_LDI;
                                opcode_rd   = {1'b1, instruction[7:4]};
                                opcode_rr   = {R_ADDR_WIDTH{1'bx}};
                                opcode_imd  = {4'b0, instruction[11:8], instruction[3:0]};
                        end
                        /* TODO 6,7: instructions */
                        16'b1010_0???_????_????: begin
                                opcode_type = `TYPE_LDS;
                                opcode_rd   = {1'b1, instruction[7:4]};
                                opcode_rr   = {R_ADDR_WIDTH{1'bx}};
                                opcode_imd  = {~instruction[8], instruction[8], instruction[10:9], instruction[3:0]};
                        end
                        16'b0010_11??_????_????: begin
                                opcode_type = `TYPE_MOV;
                                opcode_rd   = instruction[8:4];
                                opcode_rr   = {instruction[9], instruction[3:0]};
                                opcode_imd  = 12'bx;
                        end
                        16'b1001_010?_????_0001: begin
                                opcode_type = `TYPE_NEG;
                                opcode_rd   = instruction[8:4];
                                opcode_rr   = {R_ADDR_WIDTH{1'bx}};
                        end
                        16'b0000_0000_0000_0000: begin
                                opcode_type = `TYPE_NOP;
                                opcode_rd   = {R_ADDR_WIDTH{1'bx}};
                                opcode_rr   = {R_ADDR_WIDTH{1'bx}};
                        end
                        16'b0010_10??_????_????: begin
                                opcode_type = `TYPE_OR;
                                opcode_rd   = instruction[8:4];
                                opcode_rr   = {instruction[9], instruction[3:0]};
                        end
                        16'b0001_10??_????_????: begin
                                opcode_type = `TYPE_SUB;
                                opcode_rd   = instruction[8:4];
                                opcode_rr   = {instruction[9], instruction[3:0]};
                        end
                        /*TODO 4: STS */
                        16'b1010_1???_????_????: begin
                                opcode_type = `TYPE_STS;
                                opcode_rd   = {R_ADDR_WIDTH{1'bx}};
                                opcode_rr   = {1'b1, instruction[7:4]};
                                opcode_imd  = {~instruction[8], instruction[8], instruction[10:9], instruction[3:0]};
                        end
                                /* TODO : De codificat instructiunile din laborator. */

                                default: begin
                                        opcode_type = `TYPE_UNKNOWN;
                                        opcode_rd   = {R_ADDR_WIDTH{1'bx}};
                                        opcode_rr   = {R_ADDR_WIDTH{1'bx}};
                                end
                /*TODO : completati cu opcodes ale voastre.
                  Where can I find such opcodes? Make them up or read the lab and see
                  they're at http://www.atmel.com/images/Atmel-0856-AVR-Instruction-Set-Manual.pdf  */
                  /* Cand gasiti o instructiune de UAL, setati opcode_type la valoarea corecta */
                  /*  instruction seamana cu un ADD? -> opcode_type = `TYPE_ADD; */
                  endcase
        end

        assign opcode_group[`GROUP_ALU_ONE_OP] =
                (opcode_type == `TYPE_NEG);
        assign opcode_group[`GROUP_ALU_TWO_OP] =
                (opcode_type == `TYPE_ADD) ||
                (opcode_type == `TYPE_ADC) ||
                (opcode_type == `TYPE_SUB) ||
                (opcode_type == `TYPE_AND) ||
                (opcode_type == `TYPE_EOR) ||
                (opcode_type == `TYPE_OR);
        assign opcode_group[`GROUP_ALU] =
                opcode_group[`GROUP_ALU_ONE_OP] ||
                opcode_group[`GROUP_ALU_TWO_OP];

        assign opcode_group[`GROUP_LOAD_DIRECT] =
                (opcode_type == `TYPE_LDS);
        assign opcode_group[`GROUP_LOAD_INDIRECT] =
                (opcode_type == `TYPE_LD_Y);

        assign opcode_group[`GROUP_STORE_DIRECT] =
                (opcode_type == `TYPE_STS);
        assign opcode_group[`GROUP_STORE_INDIRECT] =
                0;

        assign opcode_group[`GROUP_REGISTER] =
                /* TODO 3: LDI */
                (opcode_type == `TYPE_LDI) ||
                (opcode_type == `TYPE_MOV);

        assign opcode_group[`GROUP_LOAD] =
                opcode_group[`GROUP_LOAD_DIRECT] ||
                opcode_group[`GROUP_LOAD_INDIRECT];
        assign opcode_group[`GROUP_STORE] =
                opcode_group[`GROUP_STORE_DIRECT] ||
                opcode_group[`GROUP_STORE_INDIRECT];
        assign opcode_group[`GROUP_MEMORY] =
                (opcode_group[`GROUP_LOAD] ||
                 opcode_group[`GROUP_STORE]);
endmodule