URL
https://opencores.org/ocsvn/attiny_atmega_xmega_core/attiny_atmega_xmega_core/trunk
Subversion Repositories attiny_atmega_xmega_core
[/] [attiny_atmega_xmega_core/] [trunk/] [rtl/] [mega_core_opt.v] - Rev 15
Compare with Previous | Blame | View Log
/*----------------------------------------------------------------------------/ / This IP is the Atmel ATTINY-ATMEGA-ATXMEGA CPU implementation. / /-----------------------------------------------------------------------------/ / / Copyright (C) 2017 Iulian Gheorghiu (morgoth.creator@gmail.com), all right reserved. / / This IP file is an open source software. Redistribution and use of this IP in / source and binary forms, with or without modification, are permitted provided / that the following condition is met: / 1. Redistributions of source code must retain the above copyright notice, / this condition and the following disclaimer. / / This software is provided by the copyright holder and contributors "AS IS" / and any warranties related to this software are DISCLAIMED. / The copyright owner or contributors be NOT LIABLE for any damages caused / by use of this software. /----------------------------------------------------------------------------*/ `timescale 1ns / 1ps /* * Define modes. */ `define USE_RAM_READ_DELAY 1// For now let it undefined because is not fully implemented( uncommenting this line will result in unnexpected behavior ). //`define USE_EXTENDED_RAMP_REGS// For future usage. //`define USE_CCP_REG// For future usage. `define USE_LPM /* * Core configurations: * "REDUCED" // (not working) * "MINIMAL" * "CLASSIC_8K" * "CLASSIC_128K" * "ENHANCED_8K" * "ENHANCED_128K" * "ENHANCED_4M" //Not implemented * "XMEGA" */ /* * Watchdog. */ module watchdog # ( parameter CNT_WIDTH = 0 )( input rst, input clk, input wdt_clk, input wdt_rst_in, output reg wdt_rst_out); reg [CNT_WIDTH:0]wdt_cnt; reg reset; reg reset_n; reg wdt_reset; reg wdt_reset_n; always @ (posedge rst or posedge wdt_rst_in) begin if(rst) reset <= 1'b0; else reset <= ~reset_n; end always @ (posedge rst or posedge wdt_clk) begin if(rst) begin reset_n <= 1'b0; wdt_reset <=1'b0; wdt_cnt <= 'h0000; end else if(reset != reset_n) begin reset_n <= reset; wdt_cnt <= 'h0000; end else if(wdt_clk) begin if(wdt_cnt[CNT_WIDTH]) begin wdt_reset <= ~wdt_reset_n; wdt_cnt <= 'h0000; end else begin wdt_cnt <= wdt_cnt + 1; end end end always @ (posedge rst or posedge clk) begin wdt_rst_out <= 1'b0; if(rst) wdt_reset_n <= 1'b1; else if(wdt_reset != wdt_reset_n) begin wdt_reset_n <= wdt_reset; wdt_rst_out <= 1'b1; end end endmodule /* * !Watchdog. */ /* * !Define modes. */ /* * Instruction set. */ `define INSTRUCTION_NOP 16'b0000000000000000 `define INSTRUCTION_MOVW 16'b00000001xxxxxxxx//00000001DDDDRRRR `define INSTRUCTION_MULS 16'b00000010xxxxxxxx//00000010ddddrrrr `define INSTRUCTION_MULSU 16'b000000110xxx0xxx//000000110ddd0rrr `define INSTRUCTION_FMUL 16'b000000110xxx1xxx//000000110ddd1rrr `define INSTRUCTION_FMULS 16'b000000111xxx0xxx//000000111dddurrr `define INSTRUCTION_FMULSU 16'b000000111xxx1xxx//000000111dddurrr `define INSTRUCTION_CPC 16'b000001xxxxxxxxxx//000001rdddddrrrr `define INSTRUCTION_CP 16'b000101xxxxxxxxxx//000101rdddddrrrr `define INSTRUCTION_SBC 16'b000010xxxxxxxxxx//000010rdddddrrrr `define INSTRUCTION_SUB 16'b000110xxxxxxxxxx//000110rdddddrrrr `define INSTRUCTION_ADD 16'b000011xxxxxxxxxx//000011rdddddrrrr `define INSTRUCTION_ADC 16'b000111xxxxxxxxxx//000111rdddddrrrr `define INSTRUCTION_CPSE 16'b000100xxxxxxxxxx//000100rdddddrrrr `define INSTRUCTION_AND 16'b001000xxxxxxxxxx//001000rdddddrrrr `define INSTRUCTION_EOR 16'b001001xxxxxxxxxx//001001rdddddrrrr `define INSTRUCTION_OR 16'b001010xxxxxxxxxx//001010rdddddrrrr `define INSTRUCTION_MOV 16'b001011xxxxxxxxxx//001011rdddddrrrr `define INSTRUCTION_CPI 16'b0011xxxxxxxxxxxx//0011kkkkddddkkkk `define INSTRUCTION_SUBI 16'b0101xxxxxxxxxxxx//0101kkkkddddkkkk `define INSTRUCTION_SBCI 16'b0100xxxxxxxxxxxx//0100kkkkddddkkkk `define INSTRUCTION_ORI_SBR 16'b0110xxxxxxxxxxxx//0110kkkkddddkkkk `define INSTRUCTION_ANDI_CBR 16'b0111xxxxxxxxxxxx//0111kkkkddddkkkk `define INSTRUCTION_LDD_STD 16'b10x0xxxxxxxxxxxx//10k0kksdddddykkk `define INSTRUCTION_LDS_STS 16'b100100xxxxxx0000//100100sddddd0000 `define INSTRUCTION_LD_ST_YZP 16'b100100xxxxxxx001//100100sdddddy001 `define INSTRUCTION_LD_ST_YZN 16'b100100xxxxxxx010//100100sdddddy010 `define INSTRUCTION_LPM_R 16'b1001000xxxxx0100//1001000ddddd01q0 `define INSTRUCTION_LPM_R_P 16'b1001000xxxxx0101//1001000ddddd01q1 `define INSTRUCTION_XCH 16'b1001001xxxxx0100//1001001ddddd0100 `define INSTRUCTION_LAS 16'b1001001xxxxx0101//1001001ddddd0101 `define INSTRUCTION_LAC 16'b1001001xxxxx0110//1001001ddddd0110 `define INSTRUCTION_LAT 16'b1001001xxxxx0111//1001001ddddd0111 `define INSTRUCTION_LD_ST_X 16'b100100xxxxxx1100//100100sddddd1100 `define INSTRUCTION_LD_ST_XP 16'b100100xxxxxx1101//100100sddddd1101 `define INSTRUCTION_LD_ST_XN 16'b100100xxxxxx1110//100100sddddd1110 `define INSTRUCTION_POP_PUSH 16'b100100xxxxxx1111//100100sddddd1111 `define INSTRUCTION_COM 16'b1001010xxxxx0000//1001010ddddd0000 `define INSTRUCTION_NEG 16'b1001010xxxxx0001//1001010ddddd0001 `define INSTRUCTION_SWAP 16'b1001010xxxxx0010//1001010ddddd0010 `define INSTRUCTION_INC 16'b1001010xxxxx0011//1001010ddddd0011 `define INSTRUCTION_ASR 16'b1001010xxxxx0101//1001010ddddd0101 `define INSTRUCTION_LSR 16'b1001010xxxxx0110//1001010ddddd0110 `define INSTRUCTION_ROR 16'b1001010xxxxx0111//1001010ddddd0111 `define INSTRUCTION_SEx_CLx 16'b10010100xxxx1000//10010100Bbbb1000 `define INSTRUCTION_RET_RETI 16'b10010101000x1000//10010101000x1000 `define INSTRUCTION_RET 16'b1001010100001000//1001010100001000 `define INSTRUCTION_RETI 16'b1001010100011000//1001010100001000 `define INSTRUCTION_SLEEP 16'b1001010110000000//1001010100001000 `define INSTRUCTION_BREAK 16'b1001010110011000//1001010100011000 `define INSTRUCTION_WDR 16'b1001010110101000//1001010100101000 `define INSTRUCTION_LPM_ELPM 16'b10010101110x1000//10010101110q1000 `define INSTRUCTION_SPM 16'b1001010111101000//1001010111101000 `define INSTRUCTION_SPM_Z_P 16'b1001010111111000//1001010111111000 `define INSTRUCTION_IJMP 16'b1001010000001001//1001010c000e1001 `define INSTRUCTION_ICALL 16'b1001010100001001//1001010c000e1001 `define INSTRUCTION_DEC 16'b1001010xxxxx1010//1001010ddddd1010 `define INSTRUCTION_DES 16'b10010100xxxx1011//10010100kkkk1011 `define INSTRUCTION_JMP 16'b1001010xxxxx110x//1001010kkkkk110k `define INSTRUCTION_CALL 16'b1001010xxxxx111x//1001010kkkkk111k `define INSTRUCTION_ADIW 16'b10010110xxxxxxxx//10010110kkppkkkk `define INSTRUCTION_SBIW 16'b10010111xxxxxxxx//10010111kkppkkkk `define INSTRUCTION_CBI_SBI 16'b100110x0xxxxxxxx//100110B0aaaaabbb `define INSTRUCTION_SBIC_SBIS 16'b100110x1xxxxxxxx//100110B1aaaaabbb `define INSTRUCTION_MUL 16'b100111xxxxxxxxxx//100111rdddddrrrr `define INSTRUCTION_IN_OUT 16'b1011xxxxxxxxxxxx//1011saadddddaaaa `define INSTRUCTION_RJMP 16'b1100xxxxxxxxxxxx//1100xxxxxxxxxxxx `define INSTRUCTION_RCALL 16'b1101xxxxxxxxxxxx//1101xxxxxxxxxxxx `define INSTRUCTION_LDI 16'b1110xxxxxxxxxxxx//1110KKKKddddKKKK `define INSTRUCTION_COND_BRANCH 16'b11110xxxxxxxxxxx//11110Bxxxxxxxbbb `define INSTRUCTION_BLD_BST 16'b111110xxxxxx0xxx//111110sddddd0bbb `define INSTRUCTION_SBRC_SBRS 16'b111111xxxxxx0xxx//111111Bddddd0bbb /* * !Instruction set. */ /* * Instruction decoder. */ module inst_dec( input [15:0]inst, input INTERRUPT_IN_EXECUTION, output reg SEL_INSTRUCTION_MOVW, output reg SEL_INSTRUCTION_MULS, output reg SEL_INSTRUCTION_MULSU, output reg SEL_INSTRUCTION_FMUL, output reg SEL_INSTRUCTION_FMULS, output reg SEL_INSTRUCTION_FMULSU, output reg SEL_INSTRUCTION_CPC, output reg SEL_INSTRUCTION_CP, output reg SEL_INSTRUCTION_SBC, output reg SEL_INSTRUCTION_SUB, output reg SEL_INSTRUCTION_ADD, output reg SEL_INSTRUCTION_ADC, output reg SEL_INSTRUCTION_CPSE, output reg SEL_INSTRUCTION_AND, output reg SEL_INSTRUCTION_EOR, output reg SEL_INSTRUCTION_OR, output reg SEL_INSTRUCTION_MOV, output reg SEL_INSTRUCTION_CPI, output reg SEL_INSTRUCTION_SUBI, output reg SEL_INSTRUCTION_SBCI, output reg SEL_INSTRUCTION_ORI_SBR, output reg SEL_INSTRUCTION_ANDI_CBR, output reg SEL_INSTRUCTION_LDD_STD, output reg SEL_INSTRUCTION_LDS_STS, output reg SEL_INSTRUCTION_LD_ST_YZP, output reg SEL_INSTRUCTION_LD_ST_YZN, output reg SEL_INSTRUCTION_LPM_R, output reg SEL_INSTRUCTION_LPM_R_P, output reg SEL_INSTRUCTION_XCH, output reg SEL_INSTRUCTION_LAS, output reg SEL_INSTRUCTION_LAC, output reg SEL_INSTRUCTION_LAT, output reg SEL_INSTRUCTION_LD_ST_X, output reg SEL_INSTRUCTION_LD_ST_XP, output reg SEL_INSTRUCTION_LD_ST_XN, output reg SEL_INSTRUCTION_POP_PUSH, output reg SEL_INSTRUCTION_COM, output reg SEL_INSTRUCTION_NEG, output reg SEL_INSTRUCTION_SWAP, output reg SEL_INSTRUCTION_INC, output reg SEL_INSTRUCTION_ASR, output reg SEL_INSTRUCTION_LSR, output reg SEL_INSTRUCTION_ROR, output reg SEL_INSTRUCTION_SEx_CLx, output reg SEL_INSTRUCTION_RET, output reg SEL_INSTRUCTION_RETI, output reg SEL_INSTRUCTION_SLEEP, output reg SEL_INSTRUCTION_BREAK, output reg SEL_INSTRUCTION_WDR, output reg SEL_INSTRUCTION_LPM_ELPM, output reg SEL_INSTRUCTION_SPM, output reg SEL_INSTRUCTION_SPM_Z_P, output reg SEL_INSTRUCTION_IJMP, output reg SEL_INSTRUCTION_ICALL, output reg SEL_INSTRUCTION_DEC, output reg SEL_INSTRUCTION_DES, output reg SEL_INSTRUCTION_JMP, output reg SEL_INSTRUCTION_CALL, output reg SEL_INSTRUCTION_ADIW, output reg SEL_INSTRUCTION_SBIW, output reg SEL_INSTRUCTION_CBI_SBI, output reg SEL_INSTRUCTION_SBIC_SBIS, output reg SEL_INSTRUCTION_MUL, output reg SEL_INSTRUCTION_IN_OUT, output reg SEL_INSTRUCTION_RJMP, output reg SEL_INSTRUCTION_RCALL, output reg SEL_INSTRUCTION_LDI, output reg SEL_INSTRUCTION_COND_BRANCH, output reg SEL_INSTRUCTION_BLD_BST, output reg SEL_INSTRUCTION_SBRC_SBRS ); always @ (*) begin SEL_INSTRUCTION_MOVW <= 1'b0; SEL_INSTRUCTION_MULS <= 1'b0; SEL_INSTRUCTION_MULSU <= 1'b0; SEL_INSTRUCTION_FMUL <= 1'b0; SEL_INSTRUCTION_FMULS <= 1'b0; SEL_INSTRUCTION_FMULSU <= 1'b0; SEL_INSTRUCTION_CPC <= 1'b0; SEL_INSTRUCTION_CP <= 1'b0; SEL_INSTRUCTION_SBC <= 1'b0; SEL_INSTRUCTION_SUB <= 1'b0; SEL_INSTRUCTION_ADD <= 1'b0; SEL_INSTRUCTION_ADC <= 1'b0; SEL_INSTRUCTION_CPSE <= 1'b0; SEL_INSTRUCTION_AND <= 1'b0; SEL_INSTRUCTION_EOR <= 1'b0; SEL_INSTRUCTION_OR <= 1'b0; SEL_INSTRUCTION_MOV <= 1'b0; SEL_INSTRUCTION_CPI <= 1'b0; SEL_INSTRUCTION_SUBI <= 1'b0; SEL_INSTRUCTION_SBCI <= 1'b0; SEL_INSTRUCTION_ORI_SBR <= 1'b0; SEL_INSTRUCTION_ANDI_CBR <= 1'b0; SEL_INSTRUCTION_LDD_STD <= 1'b0; SEL_INSTRUCTION_LDS_STS <= 1'b0; SEL_INSTRUCTION_LD_ST_YZP <= 1'b0; SEL_INSTRUCTION_LD_ST_YZN <= 1'b0; SEL_INSTRUCTION_LPM_R <= 1'b0; SEL_INSTRUCTION_LPM_R_P <= 1'b0; SEL_INSTRUCTION_XCH <= 1'b0; SEL_INSTRUCTION_LAS <= 1'b0; SEL_INSTRUCTION_LAC <= 1'b0; SEL_INSTRUCTION_LAT <= 1'b0; SEL_INSTRUCTION_LD_ST_X <= 1'b0; SEL_INSTRUCTION_LD_ST_XP <= 1'b0; SEL_INSTRUCTION_LD_ST_XN <= 1'b0; SEL_INSTRUCTION_POP_PUSH <= 1'b0; SEL_INSTRUCTION_COM <= 1'b0; SEL_INSTRUCTION_NEG <= 1'b0; SEL_INSTRUCTION_SWAP <= 1'b0; SEL_INSTRUCTION_INC <= 1'b0; SEL_INSTRUCTION_ASR <= 1'b0; SEL_INSTRUCTION_LSR <= 1'b0; SEL_INSTRUCTION_ROR <= 1'b0; SEL_INSTRUCTION_SEx_CLx <= 1'b0; SEL_INSTRUCTION_RET <= 1'b0; SEL_INSTRUCTION_RETI <= 1'b0; SEL_INSTRUCTION_SLEEP <= 1'b0; SEL_INSTRUCTION_BREAK <= 1'b0; SEL_INSTRUCTION_WDR <= 1'b0; SEL_INSTRUCTION_LPM_ELPM <= 1'b0; SEL_INSTRUCTION_SPM <= 1'b0; SEL_INSTRUCTION_SPM_Z_P <= 1'b0; SEL_INSTRUCTION_IJMP <= 1'b0; SEL_INSTRUCTION_ICALL <= 1'b0; SEL_INSTRUCTION_DEC <= 1'b0; SEL_INSTRUCTION_DES <= 1'b0; SEL_INSTRUCTION_JMP <= 1'b0; SEL_INSTRUCTION_CALL <= 1'b0; SEL_INSTRUCTION_ADIW <= 1'b0; SEL_INSTRUCTION_SBIW <= 1'b0; SEL_INSTRUCTION_CBI_SBI <= 1'b0; SEL_INSTRUCTION_SBIC_SBIS <= 1'b0; SEL_INSTRUCTION_MUL <= 1'b0; SEL_INSTRUCTION_IN_OUT <= 1'b0; SEL_INSTRUCTION_RJMP <= 1'b0; SEL_INSTRUCTION_RCALL <= 1'b0; SEL_INSTRUCTION_LDI <= 1'b0; SEL_INSTRUCTION_COND_BRANCH <= 1'b0; SEL_INSTRUCTION_BLD_BST <= 1'b0; SEL_INSTRUCTION_SBRC_SBRS <= 1'b0; casex({INTERRUPT_IN_EXECUTION, inst}) {1'b0, `INSTRUCTION_MOVW}: SEL_INSTRUCTION_MOVW <= 1'b1; {1'b0, `INSTRUCTION_MULS}: SEL_INSTRUCTION_MULS <= 1'b1; {1'b0, `INSTRUCTION_MULSU}: SEL_INSTRUCTION_MULSU <= 1'b1; {1'b0, `INSTRUCTION_FMUL}: SEL_INSTRUCTION_FMUL <= 1'b1; {1'b0, `INSTRUCTION_FMULS}: SEL_INSTRUCTION_FMULS <= 1'b1; {1'b0, `INSTRUCTION_FMULSU}: SEL_INSTRUCTION_FMULSU <= 1'b1; {1'b0, `INSTRUCTION_CPC}: SEL_INSTRUCTION_CPC <= 1'b1; {1'b0, `INSTRUCTION_CP}: SEL_INSTRUCTION_CP <= 1'b1; {1'b0, `INSTRUCTION_SBC}: SEL_INSTRUCTION_SBC <= 1'b1; {1'b0, `INSTRUCTION_SUB}: SEL_INSTRUCTION_SUB <= 1'b1; {1'b0, `INSTRUCTION_ADD}: SEL_INSTRUCTION_ADD <= 1'b1; {1'b0, `INSTRUCTION_ADC}: SEL_INSTRUCTION_ADC <= 1'b1; {1'b0, `INSTRUCTION_CPSE}: SEL_INSTRUCTION_CPSE <= 1'b1; {1'b0, `INSTRUCTION_AND}: SEL_INSTRUCTION_AND <= 1'b1; {1'b0, `INSTRUCTION_EOR}: SEL_INSTRUCTION_EOR <= 1'b1; {1'b0, `INSTRUCTION_OR}: SEL_INSTRUCTION_OR <= 1'b1; {1'b0, `INSTRUCTION_MOV}: SEL_INSTRUCTION_MOV <= 1'b1; {1'b0, `INSTRUCTION_CPI}: SEL_INSTRUCTION_CPI <= 1'b1; {1'b0, `INSTRUCTION_SUBI}: SEL_INSTRUCTION_SUBI <= 1'b1; {1'b0, `INSTRUCTION_SBCI}: SEL_INSTRUCTION_SBCI <= 1'b1; {1'b0, `INSTRUCTION_ORI_SBR}: SEL_INSTRUCTION_ORI_SBR <= 1'b1; {1'b0, `INSTRUCTION_ANDI_CBR}: SEL_INSTRUCTION_ANDI_CBR <= 1'b1; {1'b0, `INSTRUCTION_LDD_STD}: SEL_INSTRUCTION_LDD_STD <= 1'b1; {1'b0, `INSTRUCTION_LDS_STS}: SEL_INSTRUCTION_LDS_STS <= 1'b1; {1'b0, `INSTRUCTION_LD_ST_YZP}: SEL_INSTRUCTION_LD_ST_YZP <= 1'b1; {1'b0, `INSTRUCTION_LD_ST_YZN}: SEL_INSTRUCTION_LD_ST_YZN <= 1'b1; {1'b0, `INSTRUCTION_LPM_R}: SEL_INSTRUCTION_LPM_R <= 1'b1; {1'b0, `INSTRUCTION_LPM_R_P}: SEL_INSTRUCTION_LPM_R_P <= 1'b1; {1'b0, `INSTRUCTION_XCH}: SEL_INSTRUCTION_XCH <= 1'b1; {1'b0, `INSTRUCTION_LAS}: SEL_INSTRUCTION_LAS <= 1'b1; {1'b0, `INSTRUCTION_LAC}: SEL_INSTRUCTION_LAC <= 1'b1; {1'b0, `INSTRUCTION_LAT}: SEL_INSTRUCTION_LAT <= 1'b1; {1'b0, `INSTRUCTION_LD_ST_X}: SEL_INSTRUCTION_LD_ST_X <= 1'b1; {1'b0, `INSTRUCTION_LD_ST_XP}: SEL_INSTRUCTION_LD_ST_XP <= 1'b1; {1'b0, `INSTRUCTION_LD_ST_XN}: SEL_INSTRUCTION_LD_ST_XN <= 1'b1; {1'b0, `INSTRUCTION_POP_PUSH}: SEL_INSTRUCTION_POP_PUSH <= 1'b1; {1'b0, `INSTRUCTION_COM}: SEL_INSTRUCTION_COM <= 1'b1; {1'b0, `INSTRUCTION_NEG}: SEL_INSTRUCTION_NEG <= 1'b1; {1'b0, `INSTRUCTION_SWAP}: SEL_INSTRUCTION_SWAP <= 1'b1; {1'b0, `INSTRUCTION_INC}: SEL_INSTRUCTION_INC <= 1'b1; {1'b0, `INSTRUCTION_ASR}: SEL_INSTRUCTION_ASR <= 1'b1; {1'b0, `INSTRUCTION_LSR}: SEL_INSTRUCTION_LSR <= 1'b1; {1'b0, `INSTRUCTION_ROR}: SEL_INSTRUCTION_ROR <= 1'b1; {1'b0, `INSTRUCTION_SEx_CLx}: SEL_INSTRUCTION_SEx_CLx <= 1'b1; {1'b0, `INSTRUCTION_RET}: SEL_INSTRUCTION_RET <= 1'b1; {1'b0, `INSTRUCTION_RETI}: SEL_INSTRUCTION_RETI <= 1'b1; {1'b0, `INSTRUCTION_SLEEP}: SEL_INSTRUCTION_SLEEP <= 1'b1; {1'b0, `INSTRUCTION_BREAK}: SEL_INSTRUCTION_BREAK <= 1'b1; {1'b0, `INSTRUCTION_WDR}: SEL_INSTRUCTION_WDR <= 1'b1; {1'b0, `INSTRUCTION_LPM_ELPM}: SEL_INSTRUCTION_LPM_ELPM <= 1'b1; {1'b0, `INSTRUCTION_SPM}: SEL_INSTRUCTION_SPM <= 1'b1; {1'b0, `INSTRUCTION_SPM_Z_P}: SEL_INSTRUCTION_SPM_Z_P <= 1'b1; {1'b0, `INSTRUCTION_IJMP}: SEL_INSTRUCTION_IJMP <= 1'b1; {1'b0, `INSTRUCTION_ICALL}: SEL_INSTRUCTION_ICALL <= 1'b1; {1'b0, `INSTRUCTION_DEC}: SEL_INSTRUCTION_DEC <= 1'b1; {1'b0, `INSTRUCTION_DES}: SEL_INSTRUCTION_DES <= 1'b1; {1'b0, `INSTRUCTION_JMP}: SEL_INSTRUCTION_JMP <= 1'b1; {1'b0, `INSTRUCTION_CALL}: SEL_INSTRUCTION_CALL <= 1'b1; {1'b0, `INSTRUCTION_ADIW}: SEL_INSTRUCTION_ADIW <= 1'b1; {1'b0, `INSTRUCTION_SBIW}: SEL_INSTRUCTION_SBIW <= 1'b1; {1'b0, `INSTRUCTION_CBI_SBI}: SEL_INSTRUCTION_CBI_SBI <= 1'b1; {1'b0, `INSTRUCTION_SBIC_SBIS}: SEL_INSTRUCTION_SBIC_SBIS <= 1'b1; {1'b0, `INSTRUCTION_MUL}: SEL_INSTRUCTION_MUL <= 1'b1; {1'b0, `INSTRUCTION_IN_OUT}: SEL_INSTRUCTION_IN_OUT <= 1'b1; {1'b0, `INSTRUCTION_RJMP}: SEL_INSTRUCTION_RJMP <= 1'b1; {1'b0, `INSTRUCTION_RCALL}: SEL_INSTRUCTION_RCALL <= 1'b1; {1'b0, `INSTRUCTION_LDI}: SEL_INSTRUCTION_LDI <= 1'b1; {1'b0, `INSTRUCTION_COND_BRANCH}: SEL_INSTRUCTION_COND_BRANCH <= 1'b1; {1'b0, `INSTRUCTION_BLD_BST}: SEL_INSTRUCTION_BLD_BST <= 1'b1; {1'b0, `INSTRUCTION_SBRC_SBRS}: SEL_INSTRUCTION_SBRC_SBRS <= 1'b1; endcase end endmodule /* * !Instruction decoder. */ /* * Registers memory. */ `define ALU_FLAG_C 0 `define ALU_FLAG_Z 1 `define ALU_FLAG_N 2 `define ALU_FLAG_V 3 `define ALU_FLAG_S 4 `define ALU_FLAG_H 5 `define ALU_FLAG_T 6 `define ALU_FLAG_I 7 module mega_regs # ( parameter PLATFORM = "XILINX" )( input rst, input clk, input [4:0]rw_addr, input [15:0]rw_data, input rw_16bit, input write, input [4:0]rd_addr_d, output [15:0]rd_data_d, input rd_16bit_d, input read_d, input [4:0]rd_addr_r, output [15:0]rd_data_r, input rd_16bit_r, input read_r ); generate if(PLATFORM == "XILINX") begin reg [7:0]REGL[0:15]; reg [7:0]REGH[0:15]; /*integer k; initial begin for (k = 0; k < 16; k = k + 1) begin REGL[k] = 0; REGH[k] = 0; end end*/ always @ (posedge clk) begin if(write) begin if(!rw_16bit & !rw_addr[0]) REGL[rw_addr[4:1]] <= rw_data[7:0]; else if(!rw_16bit & rw_addr[0]) REGH[rw_addr[4:1]] <= rw_data[7:0]; else begin REGL[rw_addr[4:1]] <= rw_data[7:0]; REGH[rw_addr[4:1]] <= rw_data[15:8]; end end end assign rd_data_d = (read_d) ? (rd_16bit_d) ? {REGH[rd_addr_d[4:1]], REGL[rd_addr_d[4:1]]} : (rd_addr_d[0]) ? {8'h00, REGH[rd_addr_d[4:1]]} : {8'h00, REGL[rd_addr_d[4:1]]} : 16'bx; assign rd_data_r = (read_r) ? (rd_16bit_r) ? {REGH[rd_addr_r[4:1]], REGL[rd_addr_r[4:1]]} : (rd_addr_r[0]) ? {8'h00, REGH[rd_addr_r[4:1]]} : {8'h00, REGL[rd_addr_r[4:1]]} : 16'bx; end /* PLATFORM != "XILINX" */ else if(PLATFORM == "LATTICE_ECP5" || PLATFORM == "LATTICE_ECP3" || PLATFORM == "LATTICE_LIFMD" || PLATFORM == "LATTICE_MARCHXO2" || PLATFORM == "LATTICE_MARCHXO3L") begin/* Lattice Diamond does not know how to implement distributed RAM with true three ports, so I implement him from individual distributed RAM cells. */ wire [7:0]REGLD_out; wire [7:0]REGHD_out; wire [7:0]REGLR_out; wire [7:0]REGHR_out; wire write_to_L = write & ((!rw_16bit & !rw_addr[0]) || rw_16bit); wire write_to_H = write &((!rw_16bit & rw_addr[0]) || rw_16bit); wire write_to_HL = write &rw_16bit; DPR16X4C REG_L_D_4_7( .DI3(rw_data[7]), .DI2(rw_data[6]), .DI1(rw_data[5]), .DI0(rw_data[4]), .WAD3(rw_addr[4]), .WAD2(rw_addr[3]), .WAD1(rw_addr[2]), .WAD0(rw_addr[1]), .WCK(clk), .WRE(write_to_L | write_to_HL), .RAD3(rd_addr_d[4]), .RAD2(rd_addr_d[3]), .RAD1(rd_addr_d[2]), .RAD0(rd_addr_d[1]), .DO3(REGLD_out[7]), .DO2(REGLD_out[6]), .DO1(REGLD_out[5]), .DO0(REGLD_out[4]) ); DPR16X4C REG_L_D_0_3( .DI3(rw_data[3]), .DI2(rw_data[2]), .DI1(rw_data[1]), .DI0(rw_data[0]), .WAD3(rw_addr[4]), .WAD2(rw_addr[3]), .WAD1(rw_addr[2]), .WAD0(rw_addr[1]), .WCK(clk), .WRE(write_to_L | write_to_HL), .RAD3(rd_addr_d[4]), .RAD2(rd_addr_d[3]), .RAD1(rd_addr_d[2]), .RAD0(rd_addr_d[1]), .DO3(REGLD_out[3]), .DO2(REGLD_out[2]), .DO1(REGLD_out[1]), .DO0(REGLD_out[0]) ); DPR16X4C REG_H_D_4_7( .DI3(write_to_HL ? rw_data[15] : rw_data[7]), .DI2(write_to_HL ? rw_data[14] : rw_data[6]), .DI1(write_to_HL ? rw_data[13] : rw_data[5]), .DI0(write_to_HL ? rw_data[12] : rw_data[4]), .WAD3(rw_addr[4]), .WAD2(rw_addr[3]), .WAD1(rw_addr[2]), .WAD0(rw_addr[1]), .WCK(clk), .WRE(write_to_H | write_to_HL), .RAD3(rd_addr_d[4]), .RAD2(rd_addr_d[3]), .RAD1(rd_addr_d[2]), .RAD0(rd_addr_d[1]), .DO3(REGHD_out[7]), .DO2(REGHD_out[6]), .DO1(REGHD_out[5]), .DO0(REGHD_out[4]) ); DPR16X4C REG_H_D_0_3( .DI3(write_to_HL ? rw_data[11] : rw_data[3]), .DI2(write_to_HL ? rw_data[10] : rw_data[2]), .DI1(write_to_HL ? rw_data[9] : rw_data[1]), .DI0(write_to_HL ? rw_data[8] : rw_data[0]), .WAD3(rw_addr[4]), .WAD2(rw_addr[3]), .WAD1(rw_addr[2]), .WAD0(rw_addr[1]), .WCK(clk), .WRE(write_to_H | write_to_HL), .RAD3(rd_addr_d[4]), .RAD2(rd_addr_d[3]), .RAD1(rd_addr_d[2]), .RAD0(rd_addr_d[1]), .DO3(REGHD_out[3]), .DO2(REGHD_out[2]), .DO1(REGHD_out[1]), .DO0(REGHD_out[0]) ); DPR16X4C REG_L_R_4_7( .DI3(rw_data[7]), .DI2(rw_data[6]), .DI1(rw_data[5]), .DI0(rw_data[4]), .WAD3(rw_addr[4]), .WAD2(rw_addr[3]), .WAD1(rw_addr[2]), .WAD0(rw_addr[1]), .WCK(clk), .WRE(write_to_L | write_to_HL), .RAD3(rd_addr_r[4]), .RAD2(rd_addr_r[3]), .RAD1(rd_addr_r[2]), .RAD0(rd_addr_r[1]), .DO3(REGLR_out[7]), .DO2(REGLR_out[6]), .DO1(REGLR_out[5]), .DO0(REGLR_out[4]) ); DPR16X4C REG_L_R_0_3( .DI3(rw_data[3]), .DI2(rw_data[2]), .DI1(rw_data[1]), .DI0(rw_data[0]), .WAD3(rw_addr[4]), .WAD2(rw_addr[3]), .WAD1(rw_addr[2]), .WAD0(rw_addr[1]), .WCK(clk), .WRE(write_to_L | write_to_HL), .RAD3(rd_addr_r[4]), .RAD2(rd_addr_r[3]), .RAD1(rd_addr_r[2]), .RAD0(rd_addr_r[1]), .DO3(REGLR_out[3]), .DO2(REGLR_out[2]), .DO1(REGLR_out[1]), .DO0(REGLR_out[0]) ); DPR16X4C REG_H_R_4_7( .DI3(write_to_HL ? rw_data[15] : rw_data[7]), .DI2(write_to_HL ? rw_data[14] : rw_data[6]), .DI1(write_to_HL ? rw_data[13] : rw_data[5]), .DI0(write_to_HL ? rw_data[12] : rw_data[4]), .WAD3(rw_addr[4]), .WAD2(rw_addr[3]), .WAD1(rw_addr[2]), .WAD0(rw_addr[1]), .WCK(clk), .WRE(write_to_H | write_to_HL), .RAD3(rd_addr_r[4]), .RAD2(rd_addr_r[3]), .RAD1(rd_addr_r[2]), .RAD0(rd_addr_r[1]), .DO3(REGHR_out[7]), .DO2(REGHR_out[6]), .DO1(REGHR_out[5]), .DO0(REGHR_out[4]) ); DPR16X4C REG_H_R_0_3( .DI3(write_to_HL ? rw_data[11] : rw_data[3]), .DI2(write_to_HL ? rw_data[10] : rw_data[2]), .DI1(write_to_HL ? rw_data[9] : rw_data[1]), .DI0(write_to_HL ? rw_data[8] : rw_data[0]), .WAD3(rw_addr[4]), .WAD2(rw_addr[3]), .WAD1(rw_addr[2]), .WAD0(rw_addr[1]), .WCK(clk), .WRE(write_to_H | write_to_HL), .RAD3(rd_addr_r[4]), .RAD2(rd_addr_r[3]), .RAD1(rd_addr_r[2]), .RAD0(rd_addr_r[1]), .DO3(REGHR_out[3]), .DO2(REGHR_out[2]), .DO1(REGHR_out[1]), .DO0(REGHR_out[0]) ); assign rd_data_d = (read_d) ? (rd_16bit_d) ? {REGHD_out, REGLD_out} : (rd_addr_d[0]) ? {8'h00, REGHD_out} : {8'h00, REGLD_out} : 16'bx; assign rd_data_r = (read_r) ? (rd_16bit_r) ? {REGHR_out, REGLR_out} : (rd_addr_r[0]) ? {8'h00, REGHR_out} : {8'h00, REGLR_out} : 16'bx; end/* PLATFORM != "LATTICE_ECP5" || PLATFORM != "LATTICE_ECP3" || PLATFORM != "LATTICE_LIFMD" || PLATFORM != "LATTICE_MARCHXO2" || PLATFORM != "LATTICE_MARCHXO3L" */ endgenerate endmodule /* * !Registers memory. */ /* * Asynchronous ALU. */ module mega_alu # ( parameter CORE_CONFIG = "XMEGA" )( input [3:0]inst, input [4:0]in_addr_1, input [4:0]in_addr_2, input [15:0]in_1, input [15:0]in_2, output reg [15:0]out, //output c_out, input ALU_FLAG_C_IN, //Zero Flag input ALU_FLAG_Z_IN, //Zero Flag input ALU_FLAG_N_IN, //Negative Flag input ALU_FLAG_V_IN, //Two's complement overflow indicator input ALU_FLAG_S_IN, //N?V for signed tests input ALU_FLAG_H_IN, //Half Carry Flag input ALU_FLAG_T_IN, //Transfer bit used by BLD and BST instructions input ALU_FLAG_I_IN, //Global Interrupt Enable/Disable Flag output reg ALU_FLAG_C_OUT, //Carry Flag output reg ALU_FLAG_Z_OUT, //Zero Flag output reg ALU_FLAG_N_OUT, //Negative Flag output reg ALU_FLAG_V_OUT, //Two's complement overflow indicator output reg ALU_FLAG_S_OUT, //N?V for signed tests output reg ALU_FLAG_H_OUT, //Half Carry Flag output reg ALU_FLAG_T_OUT, //Transfer bit used by BLD and BST instructions output reg ALU_FLAG_I_OUT, //Global Interrupt Enable/Disable Flag input SEL_INSTRUCTION_MOVW, input SEL_INSTRUCTION_MULS, input SEL_INSTRUCTION_MULSU, input SEL_INSTRUCTION_FMUL, input SEL_INSTRUCTION_FMULS, input SEL_INSTRUCTION_FMULSU, input SEL_INSTRUCTION_CPC, input SEL_INSTRUCTION_CP, input SEL_INSTRUCTION_SBC, input SEL_INSTRUCTION_SUB, input SEL_INSTRUCTION_ADD, input SEL_INSTRUCTION_ADC, input SEL_INSTRUCTION_AND, input SEL_INSTRUCTION_ANDI_CBR, input SEL_INSTRUCTION_EOR, input SEL_INSTRUCTION_OR, input SEL_INSTRUCTION_ORI_SBR, input SEL_INSTRUCTION_MOV, input SEL_INSTRUCTION_CPI, input SEL_INSTRUCTION_SUBI, input SEL_INSTRUCTION_SBCI, input SEL_INSTRUCTION_LPM_R_P, input SEL_INSTRUCTION_COM, input SEL_INSTRUCTION_NEG, input SEL_INSTRUCTION_SWAP, input SEL_INSTRUCTION_INC, input SEL_INSTRUCTION_ASR, input SEL_INSTRUCTION_LSR, input SEL_INSTRUCTION_ROR, input SEL_INSTRUCTION_SEx_CLx, input SEL_INSTRUCTION_DEC, input SEL_INSTRUCTION_ADIW, input SEL_INSTRUCTION_SBIW, input SEL_INSTRUCTION_MUL ); reg in_addr_1_and_2_equal; always @ (in_addr_1 or in_addr_2) begin in_addr_1_and_2_equal = in_addr_1 == in_addr_2; end reg [15:0]in_2_int; reg cin_int; always @ (*) begin in_2_int <= in_1; cin_int <= ALU_FLAG_C_IN; if(SEL_INSTRUCTION_ADD | SEL_INSTRUCTION_ADC) begin if(!in_addr_1_and_2_equal) in_2_int <= in_2; end if( (SEL_INSTRUCTION_ADIW && CORE_CONFIG != "REDUCED") | (SEL_INSTRUCTION_SBIW && CORE_CONFIG != "REDUCED") | SEL_INSTRUCTION_SUB | SEL_INSTRUCTION_SBC | SEL_INSTRUCTION_SUBI | SEL_INSTRUCTION_SBCI | SEL_INSTRUCTION_INC | SEL_INSTRUCTION_DEC | SEL_INSTRUCTION_LPM_R_P | SEL_INSTRUCTION_CP | SEL_INSTRUCTION_CPI | SEL_INSTRUCTION_CPC) in_2_int <= in_2; if(SEL_INSTRUCTION_ADD | (SEL_INSTRUCTION_ADIW && CORE_CONFIG != "REDUCED") | (SEL_INSTRUCTION_SBIW && CORE_CONFIG != "REDUCED") | SEL_INSTRUCTION_LSR | SEL_INSTRUCTION_NEG | SEL_INSTRUCTION_SUB | SEL_INSTRUCTION_SUBI | SEL_INSTRUCTION_INC | SEL_INSTRUCTION_DEC | SEL_INSTRUCTION_LPM_R_P | SEL_INSTRUCTION_CP | SEL_INSTRUCTION_CPI) cin_int <= 1'b0; end wire [17:0] add_result_int_w_c_tmp = {in_1, 1'b1} + {in_2_int, cin_int}; wire [16:0] add_result_int_w_c = add_result_int_w_c_tmp[17:1]; wire [17:0] sub_result_int_w_c_tmp = {in_1, 1'b0} - {in_2_int, cin_int}; wire [16:0] sub_result_int_w_c = sub_result_int_w_c_tmp[17:1]; /* * Multiply Unit. */ reg [7:0]in_1_mul; reg [7:0]in_2_mul; wire [15:0]mul_result_int = in_1_mul * in_2_mul; wire mul_sign_int = in_1[7] ^ in_2[7]; always @ (*) begin if(CORE_CONFIG != "REDUCED" && CORE_CONFIG != "MINIMAL" && CORE_CONFIG != "CLASSIC_8K" && CORE_CONFIG != "CLASSIC_128K") begin in_1_mul <= 0; in_2_mul <= 0; if(SEL_INSTRUCTION_MUL | SEL_INSTRUCTION_FMUL) begin in_1_mul <= in_1[7:0]; in_2_mul <= in_2[7:0]; end if(SEL_INSTRUCTION_MULS | SEL_INSTRUCTION_FMULS) begin in_1_mul <= {1'b0, in_1[6:0]}; in_2_mul <= {1'b0, in_2[6:0]}; end if(SEL_INSTRUCTION_MULSU | SEL_INSTRUCTION_FMULSU) begin in_1_mul <= {1'b0, in_1[6:0]}; in_2_mul <= in_2[7:0]; end end end always @ (*) begin {ALU_FLAG_C_OUT, out} <= {ALU_FLAG_C_IN, in_1}; if(SEL_INSTRUCTION_ADD) begin if(in_addr_1_and_2_equal) {ALU_FLAG_C_OUT, out} <= {in_1[7], 8'h00, in_1[6:0], cin_int};//LSL else {ALU_FLAG_C_OUT, out} <= {add_result_int_w_c[8], 8'h00, add_result_int_w_c[7:0]}; end if(SEL_INSTRUCTION_ADC) begin if(in_addr_1_and_2_equal) {ALU_FLAG_C_OUT, out} <= {in_1[7], 8'h00, in_1[6:0], cin_int};//ROL else {ALU_FLAG_C_OUT, out} <= {add_result_int_w_c[8], 8'h00, add_result_int_w_c[7:0]}; end if(SEL_INSTRUCTION_INC | SEL_INSTRUCTION_DEC) {ALU_FLAG_C_OUT, out} <= {add_result_int_w_c[8], 8'h00, add_result_int_w_c[7:0]}; if(SEL_INSTRUCTION_SUB | SEL_INSTRUCTION_SBC | SEL_INSTRUCTION_SUBI | SEL_INSTRUCTION_SBCI) {ALU_FLAG_C_OUT, out} <= {sub_result_int_w_c[8], 8'h00, sub_result_int_w_c[7:0]}; if(SEL_INSTRUCTION_LSR | SEL_INSTRUCTION_ROR) {ALU_FLAG_C_OUT, out} <= {in_1[0], 8'h00, cin_int, in_1[7:1]}; if(SEL_INSTRUCTION_AND | SEL_INSTRUCTION_ANDI_CBR) {ALU_FLAG_C_OUT, out} <= {ALU_FLAG_C_IN, 8'h00, (in_1[7:0] & in_2[7:0])}; if(SEL_INSTRUCTION_OR | SEL_INSTRUCTION_ORI_SBR) {ALU_FLAG_C_OUT, out} <= {ALU_FLAG_C_IN, 8'h00, (in_1[7:0] | in_2[7:0])}; if(SEL_INSTRUCTION_EOR) {ALU_FLAG_C_OUT, out} <= {ALU_FLAG_C_IN, 8'h00, (in_1[7:0] ^ in_2[7:0])}; if(SEL_INSTRUCTION_MOV) {ALU_FLAG_C_OUT, out} <= {ALU_FLAG_C_IN, 8'h00, in_2[7:0]}; if(SEL_INSTRUCTION_MOVW) {ALU_FLAG_C_OUT, out} <= {ALU_FLAG_C_IN, in_2}; if(SEL_INSTRUCTION_COM) {ALU_FLAG_C_OUT, out} <= {1'b1, 8'h00, (8'hFF - in_1[7:0])}; if(SEL_INSTRUCTION_NEG) {ALU_FLAG_C_OUT, out} <= {|in_1[7:0], 8'h00, (8'h00 - in_1[7:0])}; if(SEL_INSTRUCTION_ADIW && CORE_CONFIG != "REDUCED") {ALU_FLAG_C_OUT, out} <= add_result_int_w_c; if(SEL_INSTRUCTION_SBIW && CORE_CONFIG != "REDUCED") {ALU_FLAG_C_OUT, out} <= sub_result_int_w_c; if((SEL_INSTRUCTION_MUL) && CORE_CONFIG != "REDUCED" && CORE_CONFIG != "MINIMAL" && CORE_CONFIG != "CLASSIC_8K" && CORE_CONFIG != "CLASSIC_128K") {ALU_FLAG_C_OUT, out} <= {mul_result_int[15], mul_result_int}; if((SEL_INSTRUCTION_MULS) && CORE_CONFIG != "REDUCED" && CORE_CONFIG != "MINIMAL" && CORE_CONFIG != "CLASSIC_8K" && CORE_CONFIG != "CLASSIC_128K") {ALU_FLAG_C_OUT, out} <= {mul_sign_int, mul_sign_int, mul_result_int[14:0]}; if((SEL_INSTRUCTION_MULSU) && CORE_CONFIG != "REDUCED" && CORE_CONFIG != "MINIMAL" && CORE_CONFIG != "CLASSIC_8K" && CORE_CONFIG != "CLASSIC_128K") {ALU_FLAG_C_OUT, out} <= {in_1[7], in_1[7], mul_result_int}; if((SEL_INSTRUCTION_FMUL) && CORE_CONFIG != "REDUCED" && CORE_CONFIG != "MINIMAL" && CORE_CONFIG != "CLASSIC_8K" && CORE_CONFIG != "CLASSIC_128K") {ALU_FLAG_C_OUT, out} <= {mul_result_int[15], mul_result_int[14:0], 1'b0}; if((SEL_INSTRUCTION_FMULS) && CORE_CONFIG != "REDUCED" && CORE_CONFIG != "MINIMAL" && CORE_CONFIG != "CLASSIC_8K" && CORE_CONFIG != "CLASSIC_128K") {ALU_FLAG_C_OUT, out} <= {mul_sign_int, mul_result_int[14:0], 1'b0}; if((SEL_INSTRUCTION_FMULSU) && CORE_CONFIG != "REDUCED" && CORE_CONFIG != "MINIMAL" && CORE_CONFIG != "CLASSIC_8K" && CORE_CONFIG != "CLASSIC_128K") {ALU_FLAG_C_OUT, out} <= {in_1[7], mul_result_int[14:0], 1'b0}; if(SEL_INSTRUCTION_ASR) {ALU_FLAG_C_OUT, out} <= {in_1[0], 8'h00, in_1[7], in_1[7:1]}; if(SEL_INSTRUCTION_CP | SEL_INSTRUCTION_CPI | SEL_INSTRUCTION_CPC) {ALU_FLAG_C_OUT, out} <= {sub_result_int_w_c[8], 8'h00, sub_result_int_w_c[7:0]}; if(SEL_INSTRUCTION_SWAP) {ALU_FLAG_C_OUT, out} <= {ALU_FLAG_C_IN, 8'b0, in_1[3:0], in_1[7:4]}; if(SEL_INSTRUCTION_SEx_CLx) {ALU_FLAG_C_OUT, out} <= inst[2:0] ? {ALU_FLAG_C_IN, {16{1'b0}}} : {~inst[3], {16{1'b0}}}; if(SEL_INSTRUCTION_LPM_R_P && CORE_CONFIG != "REDUCED") {ALU_FLAG_C_OUT, out} <= add_result_int_w_c; end wire flag_h_adc_sub_cp = (~in_1[3] & in_2[3])|(in_2[3] & out[3])|(out[3] & ~in_1[3]); wire flag_v_add_adc = (in_1[7] & in_2[7] & ~out[7])|(~in_1[7] & ~in_2[7] & out[7]); wire flag_v_sub_sbc = (in_1[7] & ~in_2[7] & ~out[7])|(~in_1[7] & in_2[7] & out[7]); /* * ALU FLAG effect for each instruction. */ always @ (inst or out or in_1 or in_2 or ALU_FLAG_Z_IN or ALU_FLAG_N_IN or ALU_FLAG_V_IN or ALU_FLAG_S_IN or ALU_FLAG_H_IN or ALU_FLAG_T_IN or ALU_FLAG_I_IN or ALU_FLAG_C_OUT or in_addr_1_and_2_equal or flag_v_add_adc or flag_h_adc_sub_cp or flag_v_sub_sbc or SEL_INSTRUCTION_ADD or SEL_INSTRUCTION_ADC or SEL_INSTRUCTION_SUB or SEL_INSTRUCTION_SUBI or SEL_INSTRUCTION_CP or SEL_INSTRUCTION_CPI or SEL_INSTRUCTION_INC or SEL_INSTRUCTION_DEC or SEL_INSTRUCTION_SBC or SEL_INSTRUCTION_SBCI or SEL_INSTRUCTION_CPC or SEL_INSTRUCTION_ADIW or SEL_INSTRUCTION_SBIW or SEL_INSTRUCTION_AND or SEL_INSTRUCTION_OR or SEL_INSTRUCTION_COM or SEL_INSTRUCTION_EOR or SEL_INSTRUCTION_NEG or SEL_INSTRUCTION_ASR or SEL_INSTRUCTION_LSR or SEL_INSTRUCTION_ROR or SEL_INSTRUCTION_SEx_CLx or SEL_INSTRUCTION_MUL or SEL_INSTRUCTION_FMUL or SEL_INSTRUCTION_MULS or SEL_INSTRUCTION_MULSU or SEL_INSTRUCTION_FMULS or SEL_INSTRUCTION_FMULSU) begin ALU_FLAG_Z_OUT <= ALU_FLAG_Z_IN; ALU_FLAG_N_OUT <= ALU_FLAG_N_IN; ALU_FLAG_V_OUT <= ALU_FLAG_V_IN; ALU_FLAG_S_OUT <= ALU_FLAG_S_IN; ALU_FLAG_H_OUT <= ALU_FLAG_H_IN; ALU_FLAG_T_OUT <= ALU_FLAG_T_IN; ALU_FLAG_I_OUT <= ALU_FLAG_I_IN; if(SEL_INSTRUCTION_ADD) begin ALU_FLAG_N_OUT <= out[7]; if(in_addr_1_and_2_equal) begin//LSL ALU_FLAG_H_OUT <= in_1[3]; ALU_FLAG_V_OUT <= ALU_FLAG_N_OUT ^ ALU_FLAG_C_OUT; ALU_FLAG_S_OUT <= out[7] != ALU_FLAG_V_OUT; end else begin ALU_FLAG_H_OUT <= (in_1[3] & in_2[3])|(in_2[3] & ~out[3])|(~out[3] & in_1[3]); ALU_FLAG_V_OUT <= flag_v_add_adc; ALU_FLAG_S_OUT <= out[7] ^ ALU_FLAG_V_OUT; end ALU_FLAG_Z_OUT <= &(~out[7:0]); end if(SEL_INSTRUCTION_ADC) begin//ROL ALU_FLAG_N_OUT <= out[7]; if(in_addr_1_and_2_equal) begin ALU_FLAG_H_OUT <= in_1[3]; ALU_FLAG_V_OUT <= ALU_FLAG_N_OUT ^ ALU_FLAG_C_OUT; ALU_FLAG_S_OUT <= out[7] ^ ALU_FLAG_N_OUT ^ ALU_FLAG_C_OUT; end else begin ALU_FLAG_H_OUT <= (in_1[3] & in_2[3])|(in_2[3] & out[3])|(~out[3] & ~in_1[3]); ALU_FLAG_V_OUT <= flag_v_add_adc; ALU_FLAG_S_OUT <= out[7] ^ ALU_FLAG_V_OUT; end ALU_FLAG_Z_OUT <= &(~out[7:0]); end if(SEL_INSTRUCTION_SUB | SEL_INSTRUCTION_SUBI | SEL_INSTRUCTION_CP | SEL_INSTRUCTION_CPI) begin ALU_FLAG_H_OUT <= flag_h_adc_sub_cp; ALU_FLAG_V_OUT <= flag_v_sub_sbc; ALU_FLAG_N_OUT <= out[7]; ALU_FLAG_S_OUT <= out[7] ^ ALU_FLAG_V_OUT; ALU_FLAG_Z_OUT <= &(~out[7:0]); end if(SEL_INSTRUCTION_INC | SEL_INSTRUCTION_DEC) begin ALU_FLAG_V_OUT <= &{~out[7], out[6:0]}; ALU_FLAG_N_OUT <= out[7]; ALU_FLAG_S_OUT <= out[7] ^ ALU_FLAG_V_OUT; ALU_FLAG_Z_OUT <= &(~out[7:0]); end if(SEL_INSTRUCTION_SBC | SEL_INSTRUCTION_SBCI | SEL_INSTRUCTION_CPC) begin ALU_FLAG_H_OUT <= flag_h_adc_sub_cp; ALU_FLAG_V_OUT <= flag_v_sub_sbc; ALU_FLAG_N_OUT <= out[7]; ALU_FLAG_S_OUT <= out[7] ^ ALU_FLAG_V_OUT; ALU_FLAG_Z_OUT <= &{~out[7:0], ALU_FLAG_Z_IN}; end if(CORE_CONFIG != "REDUCED") begin if(SEL_INSTRUCTION_ADIW | SEL_INSTRUCTION_SBIW) begin ALU_FLAG_V_OUT <= ALU_FLAG_C_OUT; ALU_FLAG_N_OUT <= out[15]; ALU_FLAG_S_OUT <= out[15] ^ ALU_FLAG_C_OUT; ALU_FLAG_Z_OUT <= &(~out[15:0]); end end if(SEL_INSTRUCTION_ANDI_CBR | SEL_INSTRUCTION_ORI_SBR | SEL_INSTRUCTION_AND | SEL_INSTRUCTION_OR | SEL_INSTRUCTION_COM | SEL_INSTRUCTION_EOR) begin ALU_FLAG_V_OUT <= 1'b0; ALU_FLAG_N_OUT <= out[7]; ALU_FLAG_S_OUT <= out[7] ^ ALU_FLAG_V_OUT; ALU_FLAG_Z_OUT <= &(~out[7:0]); end if(SEL_INSTRUCTION_NEG) begin ALU_FLAG_H_OUT <= out[3] + ~in_1[3]; ALU_FLAG_V_OUT <= &{out[7], ~out[6:0]}; ALU_FLAG_N_OUT <= out[7]; ALU_FLAG_S_OUT <= out[7] ^ ALU_FLAG_V_OUT; ALU_FLAG_Z_OUT <= &(~out[7:0]); end if(SEL_INSTRUCTION_ASR) begin ALU_FLAG_V_OUT <= 1'b0; ALU_FLAG_N_OUT <= out[7]; ALU_FLAG_S_OUT <= out[7] ^ ALU_FLAG_V_OUT; ALU_FLAG_Z_OUT <= &(~out[7:0]); end if(SEL_INSTRUCTION_LSR | SEL_INSTRUCTION_ROR) begin ALU_FLAG_H_OUT <= in_1[3]; ALU_FLAG_N_OUT <= 0; ALU_FLAG_V_OUT <= 0 ^ ALU_FLAG_C_OUT; ALU_FLAG_S_OUT <= 0 ^ ALU_FLAG_V_OUT; ALU_FLAG_Z_OUT <= &(~out[7:0]); end if(SEL_INSTRUCTION_SEx_CLx) begin case(inst[2:0]) 3'd1: ALU_FLAG_Z_OUT <= ~inst[3]; 3'd2: ALU_FLAG_N_OUT <= ~inst[3]; 3'd3: ALU_FLAG_V_OUT <= ~inst[3]; 3'd4: ALU_FLAG_S_OUT <= ~inst[3]; 3'd5: ALU_FLAG_H_OUT <= ~inst[3]; 3'd6: ALU_FLAG_T_OUT <= ~inst[3]; 3'd7: ALU_FLAG_I_OUT <= ~inst[3]; endcase end if(CORE_CONFIG != "REDUCED" && CORE_CONFIG != "MINIMAL" && CORE_CONFIG != "CLASSIC_8K" && CORE_CONFIG != "CLASSIC_128K") begin if(SEL_INSTRUCTION_MUL | SEL_INSTRUCTION_FMUL) ALU_FLAG_Z_OUT <= &(~out[15:0]); if(SEL_INSTRUCTION_MULS | SEL_INSTRUCTION_MULSU | SEL_INSTRUCTION_FMULS | SEL_INSTRUCTION_FMULSU) ALU_FLAG_Z_OUT <= &(~out[15:0]); end end endmodule /* * !Asynchronous ALU. */ /* * Interrupt and priority encoder. */ module int_encoder # ( parameter VECTOR_INT_TABLE_SIZE = 0, parameter STORE_INTERUPTS = "FALSE" )( input rst, input [((VECTOR_INT_TABLE_SIZE == 0) ? 0 : VECTOR_INT_TABLE_SIZE-1):0]int_sig_in, output int_request, output reg[((VECTOR_INT_TABLE_SIZE > 127) ? 7 : (VECTOR_INT_TABLE_SIZE > 63) ? 6 : (VECTOR_INT_TABLE_SIZE > 31) ? 5 : (VECTOR_INT_TABLE_SIZE > 15) ? 4 : (VECTOR_INT_TABLE_SIZE > 7) ? 3 : (VECTOR_INT_TABLE_SIZE > 3) ? 2 : (VECTOR_INT_TABLE_SIZE > 1) ? 1 : 0) : 0]int_vect, input executed ); reg [VECTOR_INT_TABLE_SIZE : 0]int_sig_in_int; reg [VECTOR_INT_TABLE_SIZE : 0]int_sig_in_int_n; wire [VECTOR_INT_TABLE_SIZE : 0]int_sig_in_int_active = int_sig_in_int ^ int_sig_in_int_n; genvar i; generate for (i = 0; i < VECTOR_INT_TABLE_SIZE;i = i + 1) begin :int_sig_store always @(posedge rst or posedge int_sig_in[i]) begin if(STORE_INTERUPTS == "TRUE" && VECTOR_INT_TABLE_SIZE != 0) begin if(rst) int_sig_in_int[i] <= 1'b0; else begin if(int_sig_in_int_n[i] == int_sig_in_int[i]) int_sig_in_int[i] <= ~int_sig_in_int_n[i]; end end end always @ (posedge rst or posedge executed) begin if(STORE_INTERUPTS == "TRUE" && VECTOR_INT_TABLE_SIZE != 0) begin if(rst) int_sig_in_int_n[i] <= 1'b0; else if(executed && int_vect == i) int_sig_in_int_n[int_vect] <= int_sig_in_int[int_vect]; end end end endgenerate integer j; always @* begin if(VECTOR_INT_TABLE_SIZE != 0) begin int_vect <= 0; for (j=VECTOR_INT_TABLE_SIZE-1; j>=0; j=j-1) if ((STORE_INTERUPTS == "TRUE") ? int_sig_in_int_active[j] : int_sig_in[j]) int_vect <= j+1; end end assign int_request = (int_vect != 0 && VECTOR_INT_TABLE_SIZE != 'h0); endmodule /* * !Interrupt and priority encoder. */ /* * XMega core. */ `define STEP0 0 `define STEP1 1 `define STEP2 2 module mega_core # ( parameter PLATFORM = "XILINX", parameter CORE_CONFIG = "XMEGA",// Supported: "REDUCED", "MINIMAL", "CLASSIC_8K", "CLASSIC_128K", "ENHANCED_8K", "ENHANCED_128K", "ENHANCED_4M", "XMEGA" parameter BUS_ADDR_PGM_WIDTH = 14, parameter BUS_ADDR_DATA_WIDTH = 13, parameter USE_BRAM_ROM = "FALSE", parameter WATCHDOG_CNT_WIDTH = 0, parameter VECTOR_INT_TABLE_SIZE = 0, parameter STORE_INTERUPTS = "FALSE", parameter MAP_REGS_IN_TO_SRAM_SECTION = "FALSE" )( input rst, output sys_rst, input clk, input clk_wdt, output reg [BUS_ADDR_PGM_WIDTH-1:0]pgm_addr, input [15:0]pgm_data, output reg [BUS_ADDR_DATA_WIDTH-1:0]data_addr, input [7:0]data_in, output [7:0]data_out, output data_we, output data_re, output [5:0]io_addr, input [7:0]io_in, output [7:0]io_out, output io_we, output io_re, input [(VECTOR_INT_TABLE_SIZE == 0 ? 0 : VECTOR_INT_TABLE_SIZE - 1):0]int_sig, output reg [(VECTOR_INT_TABLE_SIZE == 0 ? 0 : VECTOR_INT_TABLE_SIZE - 1):0]int_rst, output reg wdt_rst_out ); reg [7:0]ALU_FLAGS; //Carry Flag wire ALU_FLAG_C_OUT; //Carry Flag wire ALU_FLAG_Z_OUT; //Zero Flag wire ALU_FLAG_N_OUT; //Negative Flag wire ALU_FLAG_V_OUT; //Two's complement overflow indicator wire ALU_FLAG_S_OUT; //N?V for signed tests wire ALU_FLAG_H_OUT; //Half Carry Flag wire ALU_FLAG_T_OUT; //Transfer bit used by BLD and BST instructions wire ALU_FLAG_I_OUT; //Global Interrupt Enable/Disable Flag reg [BUS_ADDR_PGM_WIDTH-1:0]PC; reg [BUS_ADDR_PGM_WIDTH-1:0]pgm_indirect_addr; wire [BUS_ADDR_PGM_WIDTH-1:0]PC_PLUS_ONE = PC + 1; wire [BUS_ADDR_PGM_WIDTH-1:0]PC_PLUS_TWO = PC + 2; wire [BUS_ADDR_PGM_WIDTH-1:0]PC_PLUS_THREE = PC + 3; reg [BUS_ADDR_DATA_WIDTH-1:0]SP; wire [BUS_ADDR_DATA_WIDTH-1:0]SP_PLUS_ONE = SP + 1; wire [BUS_ADDR_DATA_WIDTH-1:0]SP_MINUS_ONE = SP - 1; reg [1:0]step_cnt; reg [15:0]tmp_pgm_data; `ifdef USE_CCP_REG reg [7:0]CCP; /* Configuration Change Protection */ `endif `ifdef USE_EXTENDED_RAMP_REGS reg [7:0]RAMPD; /* Ramp D */ reg [7:0]RAMPX; /* Ramp X */ reg [7:0]RAMPY; /* Ramp Y */ reg [7:0]RAMPZ; /* Ramp Z */ reg [7:0]EIND; /* Extended Indirect Jump */ `endif wire core_rst; assign sys_rst = (WATCHDOG_CNT_WIDTH != 'd0) ? core_rst : rst; wire alu_rdy; wire [7:0]data_in_int; reg [7:0]data_out_int; wire [7:0]io_in_int; reg [7:0]io_out_int; reg data_we_int; reg data_re_int; reg [BUS_ADDR_DATA_WIDTH - 1:0]data_addr_int; reg [BUS_ADDR_DATA_WIDTH - 1:0]data_addr_int_tmp; reg [5:0]io_addr_int; reg io_we_int; reg io_re_int; assign io_we = io_we_int; assign io_re = io_re_int; assign io_addr = io_addr_int; assign io_in_int = io_in; assign io_out = io_out_int; assign data_we = data_we_int; assign data_re = data_re_int; always @ (*) data_addr <= data_addr_int; assign data_out = data_out_int; assign data_in_int = data_in; /* * ! pgm_addr bus switcher */ // REG aditional reg write_to_reg; // REG wires reg [4:0]rw_addr; reg [15:0]rw_data; reg rw_16bit; //wire write; reg [4:0]rd_addr_d; wire [15:0]rd_data_d; reg rd_16bit_d; wire read_d; reg [4:0]rd_addr_r; wire [15:0]rd_data_r; wire [BUS_ADDR_DATA_WIDTH-1:0]rd_data_r_PLUS_ONE = rd_data_r + 1; wire [BUS_ADDR_DATA_WIDTH-1:0]rd_data_r_MINUS_ONE = rd_data_r - 1; reg rd_16bit_r; wire read_r; // ALU wires reg [15:0]alu_in_1; reg [15:0]alu_in_2; wire [15:0]alu_out; //wire alu_c_out; reg [BUS_ADDR_DATA_WIDTH-1:0]indirect_addr_offset; wire [BUS_ADDR_DATA_WIDTH-1:0]indirect_addr_offset_res = rd_data_r + indirect_addr_offset; reg [4:0]reg_clr_cnt; assign alu_rdy = reg_clr_cnt == 16; //`ifdef USE_RAM_READ_DELAY reg rom_read_delay; reg [1:0]ram_read_delay; //`endif reg [15:0]pgm_data_int; always @ (*) begin pgm_data_int <= pgm_data; end localparam int_bus_size = (VECTOR_INT_TABLE_SIZE > 127) ? 8 : (VECTOR_INT_TABLE_SIZE > 63) ? 7 : (VECTOR_INT_TABLE_SIZE > 31) ? 6 : (VECTOR_INT_TABLE_SIZE > 15) ? 5 : (VECTOR_INT_TABLE_SIZE > 7) ? 4 : (VECTOR_INT_TABLE_SIZE > 3) ? 3 : (VECTOR_INT_TABLE_SIZE > 1) ? 2 : 1; reg interrupt_registered; reg current_int_executed; wire [int_bus_size - 1 : 0]current_int_vect; reg [int_bus_size - 1 : 0]current_int_vect_int; wire int_request; /*always @ (posedge interrupt_registered) begin current_int_vect_int <= current_int_vect; end*/ int_encoder # ( .VECTOR_INT_TABLE_SIZE(VECTOR_INT_TABLE_SIZE), .STORE_INTERUPTS(STORE_INTERUPTS) )int_encoder_inst( .rst(rst), .int_sig_in(int_sig), .int_vect(current_int_vect), .int_request(int_request), .executed(current_int_executed) ); /* * pgm_addr bus switcher */ always @ (*) begin if(CORE_CONFIG != "REDUCED") begin `ifdef USE_LPM case(step_cnt) `STEP2: begin casex(tmp_pgm_data) `INSTRUCTION_LPM_R, `INSTRUCTION_LPM_R_P: pgm_addr <= pgm_indirect_addr[{1'b0, BUS_ADDR_PGM_WIDTH-1}:1]; default: pgm_addr <= PC; endcase end default: pgm_addr <= PC; endcase `endif end else begin pgm_addr <= PC; end end wire SEL_S1_INSTRUCTION_MOVW; wire SEL_S1_INSTRUCTION_MULS; wire SEL_S1_INSTRUCTION_MULSU; wire SEL_S1_INSTRUCTION_FMUL; wire SEL_S1_INSTRUCTION_FMULS; wire SEL_S1_INSTRUCTION_FMULSU; wire SEL_S1_INSTRUCTION_CPC; wire SEL_S1_INSTRUCTION_CP; wire SEL_S1_INSTRUCTION_SBC; wire SEL_S1_INSTRUCTION_SUB; wire SEL_S1_INSTRUCTION_ADD; wire SEL_S1_INSTRUCTION_ADC; wire SEL_S1_INSTRUCTION_CPSE; wire SEL_S1_INSTRUCTION_AND; wire SEL_S1_INSTRUCTION_EOR; wire SEL_S1_INSTRUCTION_OR; wire SEL_S1_INSTRUCTION_MOV; wire SEL_S1_INSTRUCTION_CPI; wire SEL_S1_INSTRUCTION_SUBI; wire SEL_S1_INSTRUCTION_SBCI; wire SEL_S1_INSTRUCTION_ORI_SBR; wire SEL_S1_INSTRUCTION_ANDI_CBR; wire SEL_S1_INSTRUCTION_LDD_STD; wire SEL_S1_INSTRUCTION_LDS_STS; wire SEL_S1_INSTRUCTION_LD_ST_YZP; wire SEL_S1_INSTRUCTION_LD_ST_YZN; wire SEL_S1_INSTRUCTION_LPM_R; wire SEL_S1_INSTRUCTION_LPM_R_P; wire SEL_S1_INSTRUCTION_XCH; wire SEL_S1_INSTRUCTION_LAS; wire SEL_S1_INSTRUCTION_LAC; wire SEL_S1_INSTRUCTION_LAT; wire SEL_S1_INSTRUCTION_LD_ST_X; wire SEL_S1_INSTRUCTION_LD_ST_XP; wire SEL_S1_INSTRUCTION_LD_ST_XN; wire SEL_S1_INSTRUCTION_POP_PUSH; wire SEL_S1_INSTRUCTION_COM; wire SEL_S1_INSTRUCTION_NEG; wire SEL_S1_INSTRUCTION_SWAP; wire SEL_S1_INSTRUCTION_INC; wire SEL_S1_INSTRUCTION_ASR; wire SEL_S1_INSTRUCTION_LSR; wire SEL_S1_INSTRUCTION_ROR; wire SEL_S1_INSTRUCTION_SEx_CLx; wire SEL_S1_INSTRUCTION_RET; wire SEL_S1_INSTRUCTION_RETI; wire SEL_S1_INSTRUCTION_SLEEP; wire SEL_S1_INSTRUCTION_BREAK; wire SEL_S1_INSTRUCTION_WDR; wire SEL_S1_INSTRUCTION_LPM_ELPM; wire SEL_S1_INSTRUCTION_SPM; wire SEL_S1_INSTRUCTION_SPM_Z_P; wire SEL_S1_INSTRUCTION_IJMP; wire SEL_S1_INSTRUCTION_ICALL; wire SEL_S1_INSTRUCTION_DEC; wire SEL_S1_INSTRUCTION_DES; wire SEL_S1_INSTRUCTION_JMP; wire SEL_S1_INSTRUCTION_CALL; wire SEL_S1_INSTRUCTION_ADIW; wire SEL_S1_INSTRUCTION_SBIW; wire SEL_S1_INSTRUCTION_CBI_SBI; wire SEL_S1_INSTRUCTION_SBIC_SBIS; wire SEL_S1_INSTRUCTION_MUL; wire SEL_S1_INSTRUCTION_IN_OUT; wire SEL_S1_INSTRUCTION_RJMP; wire SEL_S1_INSTRUCTION_RCALL; wire SEL_S1_INSTRUCTION_LDI; wire SEL_S1_INSTRUCTION_COND_BRANCH; wire SEL_S1_INSTRUCTION_BLD_BST; wire SEL_S1_INSTRUCTION_SBRC_SBRS; inst_dec inst_dec_s1_inst( .inst( `ifdef USE_RAM_READ_DELAY ram_read_delay != `USE_RAM_READ_DELAY || step_cnt != `STEP1 ? tmp_pgm_data : `endif pgm_data_int), .INTERRUPT_IN_EXECUTION(interrupt_registered), .SEL_INSTRUCTION_MOVW(SEL_S1_INSTRUCTION_MOVW), .SEL_INSTRUCTION_MULS(SEL_S1_INSTRUCTION_MULS), .SEL_INSTRUCTION_MULSU(SEL_S1_INSTRUCTION_MULSU), .SEL_INSTRUCTION_FMUL(SEL_S1_INSTRUCTION_FMUL), .SEL_INSTRUCTION_FMULS(SEL_S1_INSTRUCTION_FMULS), .SEL_INSTRUCTION_FMULSU(SEL_S1_INSTRUCTION_FMULSU), .SEL_INSTRUCTION_CPC(SEL_S1_INSTRUCTION_CPC), .SEL_INSTRUCTION_CP(SEL_S1_INSTRUCTION_CP), .SEL_INSTRUCTION_SBC(SEL_S1_INSTRUCTION_SBC), .SEL_INSTRUCTION_SUB(SEL_S1_INSTRUCTION_SUB), .SEL_INSTRUCTION_ADD(SEL_S1_INSTRUCTION_ADD), .SEL_INSTRUCTION_ADC(SEL_S1_INSTRUCTION_ADC), .SEL_INSTRUCTION_CPSE(SEL_S1_INSTRUCTION_CPSE), .SEL_INSTRUCTION_AND(SEL_S1_INSTRUCTION_AND), .SEL_INSTRUCTION_EOR(SEL_S1_INSTRUCTION_EOR), .SEL_INSTRUCTION_OR(SEL_S1_INSTRUCTION_OR), .SEL_INSTRUCTION_MOV(SEL_S1_INSTRUCTION_MOV), .SEL_INSTRUCTION_CPI(SEL_S1_INSTRUCTION_CPI), .SEL_INSTRUCTION_SUBI(SEL_S1_INSTRUCTION_SUBI), .SEL_INSTRUCTION_SBCI(SEL_S1_INSTRUCTION_SBCI), .SEL_INSTRUCTION_ORI_SBR(SEL_S1_INSTRUCTION_ORI_SBR), .SEL_INSTRUCTION_ANDI_CBR(SEL_S1_INSTRUCTION_ANDI_CBR), .SEL_INSTRUCTION_LDD_STD(SEL_S1_INSTRUCTION_LDD_STD), .SEL_INSTRUCTION_LDS_STS(SEL_S1_INSTRUCTION_LDS_STS), .SEL_INSTRUCTION_LD_ST_YZP(SEL_S1_INSTRUCTION_LD_ST_YZP), .SEL_INSTRUCTION_LD_ST_YZN(SEL_S1_INSTRUCTION_LD_ST_YZN), .SEL_INSTRUCTION_LPM_R(SEL_S1_INSTRUCTION_LPM_R), .SEL_INSTRUCTION_LPM_R_P(SEL_S1_INSTRUCTION_LPM_R_P), .SEL_INSTRUCTION_XCH(SEL_S1_INSTRUCTION_XCH), .SEL_INSTRUCTION_LAS(SEL_S1_INSTRUCTION_LAS), .SEL_INSTRUCTION_LAC(SEL_S1_INSTRUCTION_LAC), .SEL_INSTRUCTION_LAT(SEL_S1_INSTRUCTION_LAT), .SEL_INSTRUCTION_LD_ST_X(SEL_S1_INSTRUCTION_LD_ST_X), .SEL_INSTRUCTION_LD_ST_XP(SEL_S1_INSTRUCTION_LD_ST_XP), .SEL_INSTRUCTION_LD_ST_XN(SEL_S1_INSTRUCTION_LD_ST_XN), .SEL_INSTRUCTION_POP_PUSH(SEL_S1_INSTRUCTION_POP_PUSH), .SEL_INSTRUCTION_COM(SEL_S1_INSTRUCTION_COM), .SEL_INSTRUCTION_NEG(SEL_S1_INSTRUCTION_NEG), .SEL_INSTRUCTION_SWAP(SEL_S1_INSTRUCTION_SWAP), .SEL_INSTRUCTION_INC(SEL_S1_INSTRUCTION_INC), .SEL_INSTRUCTION_ASR(SEL_S1_INSTRUCTION_ASR), .SEL_INSTRUCTION_LSR(SEL_S1_INSTRUCTION_LSR), .SEL_INSTRUCTION_ROR(SEL_S1_INSTRUCTION_ROR), .SEL_INSTRUCTION_SEx_CLx(SEL_S1_INSTRUCTION_SEx_CLx), .SEL_INSTRUCTION_RET(SEL_S1_INSTRUCTION_RET), .SEL_INSTRUCTION_RETI(SEL_S1_INSTRUCTION_RETI), .SEL_INSTRUCTION_SLEEP(SEL_S1_INSTRUCTION_SLEEP), .SEL_INSTRUCTION_BREAK(SEL_S1_INSTRUCTION_BREAK), .SEL_INSTRUCTION_WDR(SEL_S1_INSTRUCTION_WDR), .SEL_INSTRUCTION_LPM_ELPM(SEL_S1_INSTRUCTION_LPM_ELPM), .SEL_INSTRUCTION_SPM(SEL_S1_INSTRUCTION_SPM), .SEL_INSTRUCTION_SPM_Z_P(SEL_S1_INSTRUCTION_SPM_Z_P), .SEL_INSTRUCTION_IJMP(SEL_S1_INSTRUCTION_IJMP), .SEL_INSTRUCTION_ICALL(SEL_S1_INSTRUCTION_ICALL), .SEL_INSTRUCTION_DEC(SEL_S1_INSTRUCTION_DEC), .SEL_INSTRUCTION_DES(SEL_S1_INSTRUCTION_DES), .SEL_INSTRUCTION_JMP(SEL_S1_INSTRUCTION_JMP), .SEL_INSTRUCTION_CALL(SEL_S1_INSTRUCTION_CALL), .SEL_INSTRUCTION_ADIW(SEL_S1_INSTRUCTION_ADIW), .SEL_INSTRUCTION_SBIW(SEL_S1_INSTRUCTION_SBIW), .SEL_INSTRUCTION_CBI_SBI(SEL_S1_INSTRUCTION_CBI_SBI), .SEL_INSTRUCTION_SBIC_SBIS(SEL_S1_INSTRUCTION_SBIC_SBIS), .SEL_INSTRUCTION_MUL(SEL_S1_INSTRUCTION_MUL), .SEL_INSTRUCTION_IN_OUT(SEL_S1_INSTRUCTION_IN_OUT), .SEL_INSTRUCTION_RJMP(SEL_S1_INSTRUCTION_RJMP), .SEL_INSTRUCTION_RCALL(SEL_S1_INSTRUCTION_RCALL), .SEL_INSTRUCTION_LDI(SEL_S1_INSTRUCTION_LDI), .SEL_INSTRUCTION_COND_BRANCH(SEL_S1_INSTRUCTION_COND_BRANCH), .SEL_INSTRUCTION_BLD_BST(SEL_S1_INSTRUCTION_BLD_BST), .SEL_INSTRUCTION_SBRC_SBRS(SEL_S1_INSTRUCTION_SBRC_SBRS) ); reg SEL_S2_INSTRUCTION_CPSE; reg SEL_S2_INSTRUCTION_LDS_STS; reg SEL_S2_INSTRUCTION_LD_ST_YZP; reg SEL_S2_INSTRUCTION_LD_ST_YZN; reg SEL_S2_INSTRUCTION_LPM_ELPM; reg SEL_S2_INSTRUCTION_LPM_R; reg SEL_S2_INSTRUCTION_LPM_R_P; reg SEL_S2_INSTRUCTION_LD_ST_X; reg SEL_S2_INSTRUCTION_LD_ST_XP; reg SEL_S2_INSTRUCTION_LD_ST_XN; reg SEL_S2_INSTRUCTION_RET; reg SEL_S2_INSTRUCTION_RETI; reg SEL_S2_INSTRUCTION_ICALL; reg SEL_S2_INSTRUCTION_JMP; reg SEL_S2_INSTRUCTION_CALL; reg SEL_S2_INSTRUCTION_SBIC_SBIS; reg SEL_S2_INSTRUCTION_MUL; reg SEL_S2_INSTRUCTION_MULS; reg SEL_S2_INSTRUCTION_MULSU; reg SEL_S2_INSTRUCTION_FMUL; reg SEL_S2_INSTRUCTION_FMULS; reg SEL_S2_INSTRUCTION_FMULSU; reg SEL_S2_INSTRUCTION_RCALL; reg SEL_S2_INSTRUCTION_SBRC_SBRS; reg select_io_in_stam; integer io_ports_displacement; /* * IO maping switch */ always @* begin if(CORE_CONFIG == "XMEGA") begin if(ram_read_delay == 0) select_io_in_stam = data_addr_int_tmp < 'h40; else select_io_in_stam = pgm_data_int < 'h40; io_ports_displacement = 'h0000; end else begin if(ram_read_delay == 0) select_io_in_stam = data_addr_int_tmp < 'h60; else select_io_in_stam = pgm_data_int < 'h60; io_ports_displacement = 'h0020; end end /* * !IO maping switch */ `ifdef USE_RAM_READ_DELAY wire [15:0]tmp_pgm_data_switched = ram_read_delay == `USE_RAM_READ_DELAY ? pgm_data_int : tmp_pgm_data; `else wire [15:0]tmp_pgm_data_switched = pgm_data_int; `endif /* * Busses switch. */ reg skip_execution; always @ (*) begin rw_addr <= 5'h0; rw_16bit <= 1'b0; rd_addr_d <= 5'h0; rd_16bit_d <= 1'b0; rd_addr_r <= 5'h0; rd_16bit_r <= 1'b0; // Connect busses rw_data <= 16'h0; alu_in_1 <= 16'h0; alu_in_2 <= 16'h0; write_to_reg <= 1'b0; io_we_int <= 1'b0; io_re_int <= 1'b0; io_addr_int <= 16'h0; io_out_int <= 'h0; data_addr_int <= 'hz; data_out_int <= 'hz; data_re_int <= 1'b0; indirect_addr_offset <= 16'h0; data_we_int <= 1'b0; if(~alu_rdy) begin rw_addr <= reg_clr_cnt; rw_16bit <= 1'b1; rw_data <= 16'h0; write_to_reg <= 1'b1; end else begin /* * Data address switch. */ if(!skip_execution | USE_BRAM_ROM != "TRUE") begin case(step_cnt) `STEP1: begin if(CORE_CONFIG != "REDUCED") begin if(SEL_S1_INSTRUCTION_LDD_STD) data_addr_int <= indirect_addr_offset_res; if(SEL_S1_INSTRUCTION_POP_PUSH) begin if(pgm_data_int[9]) data_addr_int <= SP; else data_addr_int <= SP_PLUS_ONE; end end if(CORE_CONFIG != "REDUCED" && CORE_CONFIG != "MINIMAL") begin if(SEL_S1_INSTRUCTION_LD_ST_X | SEL_S1_INSTRUCTION_LD_ST_XP | SEL_S1_INSTRUCTION_LD_ST_YZP) data_addr_int <= rd_data_r; if(SEL_S1_INSTRUCTION_LD_ST_XN | SEL_S1_INSTRUCTION_LD_ST_YZN) data_addr_int <= rd_data_r_MINUS_ONE; end if((SEL_S1_INSTRUCTION_ICALL && (CORE_CONFIG != "REDUCED" && CORE_CONFIG != "MINIMAL")) | (SEL_S1_INSTRUCTION_CALL && (CORE_CONFIG != "REDUCED" && CORE_CONFIG != "MINIMAL" && CORE_CONFIG != "CLASSIC_8K")) | SEL_S1_INSTRUCTION_RCALL | (interrupt_registered && VECTOR_INT_TABLE_SIZE != 0)) data_addr_int <= SP; if(SEL_S1_INSTRUCTION_RET | SEL_S1_INSTRUCTION_RETI) data_addr_int <= {{BUS_ADDR_PGM_WIDTH-1-8{1'b0}}, SP_PLUS_ONE}; if (SEL_S1_INSTRUCTION_XCH | SEL_S1_INSTRUCTION_LAS | SEL_S1_INSTRUCTION_LAC | SEL_S1_INSTRUCTION_LAT) data_addr_int <= rd_data_r; end `STEP2: begin if(interrupt_registered && VECTOR_INT_TABLE_SIZE != 0) data_addr_int <= SP; else begin casex(tmp_pgm_data) `INSTRUCTION_ICALL: begin if(CORE_CONFIG != "REDUCED" && CORE_CONFIG != "MINIMAL") begin data_addr_int <= SP; end end `INSTRUCTION_CALL: begin if(CORE_CONFIG != "REDUCED" && CORE_CONFIG != "MINIMAL" && CORE_CONFIG != "CLASSIC_8K") begin data_addr_int <= SP; end end `INSTRUCTION_RCALL: data_addr_int <= SP; `INSTRUCTION_RET_RETI: data_addr_int <= SP_PLUS_ONE; `INSTRUCTION_LDS_STS: begin `ifdef USE_RAM_READ_DELAY if(ram_read_delay == `USE_RAM_READ_DELAY) `endif data_addr_int <= pgm_data_int[BUS_ADDR_DATA_WIDTH-1:0]; `ifdef USE_RAM_READ_DELAY else data_addr_int <= data_addr_int_tmp; `endif end endcase end end endcase /* * Instruction decode. */ rd_addr_d <= 'h0; rd_addr_r <= 'h0; case(step_cnt) `STEP1: begin if(SEL_S1_INSTRUCTION_MOVW) begin rw_addr <= {pgm_data_int[7:4], 1'b0}; rw_16bit <= 1'b1; rd_addr_d <= {pgm_data_int[7:4], 1'b0}; rd_16bit_d <= 1'b1; rd_addr_r <= {pgm_data_int[3:0], 1'b0}; rd_16bit_r <= 1'b1; // Connect busses alu_in_1 <= rd_data_d; alu_in_2 <= rd_data_r; rw_data <= alu_out; // Signalize write_to_reg; write_to_reg <= 1'b1; end /*if(SEL_S1_INSTRUCTION_CPSE) begin end*/ if(SEL_S1_INSTRUCTION_CPI) begin rd_addr_d <= {1'b1, pgm_data_int[7:4]}; // Connect busses alu_in_1 <= rd_data_d; alu_in_2 <= {pgm_data_int[11:8], pgm_data_int[3:0]}; end if(SEL_S1_INSTRUCTION_CPC | SEL_S1_INSTRUCTION_CP) begin rd_addr_d <= pgm_data_int[8:4]; rd_addr_r <= {pgm_data_int[9], pgm_data_int[3:0]}; // Connect busses alu_in_1 <= rd_data_d; alu_in_2 <= rd_data_r; end if(SEL_S1_INSTRUCTION_SBC | SEL_S1_INSTRUCTION_SUB | SEL_S1_INSTRUCTION_ADD | SEL_S1_INSTRUCTION_ADC | SEL_S1_INSTRUCTION_AND | SEL_S1_INSTRUCTION_EOR | SEL_S1_INSTRUCTION_OR | SEL_S1_INSTRUCTION_MOV) begin rw_addr <= pgm_data_int[8:4]; rd_addr_d <= pgm_data_int[8:4]; rd_addr_r <= {pgm_data_int[9], pgm_data_int[3:0]}; // Connect busses alu_in_1 <= rd_data_d; alu_in_2 <= rd_data_r; rw_data <= alu_out; // Signalize write_to_reg; write_to_reg <= 1'b1; end if(SEL_S1_INSTRUCTION_SUBI | SEL_S1_INSTRUCTION_SBCI | SEL_S1_INSTRUCTION_ORI_SBR | SEL_S1_INSTRUCTION_ANDI_CBR) begin rw_addr <= {1'b1, pgm_data_int[7:4]}; rd_addr_d <= {1'b1, pgm_data_int[7:4]}; // Connect busses alu_in_1 <= rd_data_d; alu_in_2 <= {8'h00, pgm_data_int[11:8], pgm_data_int[3:0]}; rw_data <= alu_out; // Signalize write_to_reg; write_to_reg <= 1'b1; end if(SEL_S1_INSTRUCTION_COM | SEL_S1_INSTRUCTION_NEG | SEL_S1_INSTRUCTION_SWAP | SEL_S1_INSTRUCTION_INC | SEL_S1_INSTRUCTION_DEC | SEL_S1_INSTRUCTION_ASR | SEL_S1_INSTRUCTION_LSR | SEL_S1_INSTRUCTION_ROR) begin rw_addr <= pgm_data_int[8:4]; rd_addr_d <= pgm_data_int[8:4]; // Connect busses alu_in_1 <= rd_data_d; if(SEL_S1_INSTRUCTION_INC) alu_in_2 <= 16'h0001; if(SEL_S1_INSTRUCTION_DEC) alu_in_2 <= 16'hFFFF; rw_data <= alu_out; // Signalize write_to_reg; write_to_reg <= 1'b1; end if(CORE_CONFIG != "REDUCED") begin if(SEL_S1_INSTRUCTION_LDD_STD) begin rd_addr_r <= {{3{1'b1}}, ~tmp_pgm_data_switched[3], 1'b0}; rd_16bit_r <= 1'b1; indirect_addr_offset <= {{10{1'b0}}, tmp_pgm_data_switched[13], tmp_pgm_data_switched[11:10], tmp_pgm_data_switched[2:0]}; if(tmp_pgm_data_switched[9]) begin rd_addr_d <= tmp_pgm_data_switched[8:4]; data_out_int <= rd_data_d; data_we_int <= 1'b1; end else begin rw_addr <= tmp_pgm_data_switched[8:4]; // Connect busses rw_data <= data_in_int; // Signalize write_to_reg; if(ram_read_delay == 0) write_to_reg <= 1'b1; data_re_int <= 1'b1; end end `ifdef USE_LPM if(SEL_S1_INSTRUCTION_LPM_R | SEL_S1_INSTRUCTION_LPM_R_P | SEL_S1_INSTRUCTION_LPM_ELPM) begin rd_addr_d <= 'h1E;//pgm_data_int[8:4]; rd_16bit_d <= 1'b1; if(pgm_data_int[0]) begin // Connect busses alu_in_1 <= rd_data_d; alu_in_2 <= 1; rw_addr <= 'h1E;//pgm_data_int[8:4]; rw_data <= alu_out; rw_16bit <= 1'b1; write_to_reg <= 1'b1; end end `endif end/*!CORE_CONFIG != "REDUCED"*/ if(CORE_CONFIG != "REDUCED" && CORE_CONFIG != "MINIMAL") begin /*if(SEL_S1_INSTRUCTION_LD_ST_X) begin rd_addr_r <= 5'd26; rd_16bit_r <= 1'b1; if(pgm_data_int[9]) begin rd_addr_d <= tmp_pgm_data_switched[8:4]; data_out_int <= rd_data_d; data_we_int <= 1'b1; end else begin rw_addr <= tmp_pgm_data_switched[8:4]; // Connect busses rw_data <= data_in_int; // Signalize write_to_reg; write_to_reg <= 1'b1; data_re_int <= 1'b1; end end*/ if(SEL_S1_INSTRUCTION_LD_ST_YZP | SEL_S1_INSTRUCTION_LD_ST_YZN) begin rd_addr_r <= {{3{1'b1}}, ~tmp_pgm_data_switched[3], 1'b0}; rd_16bit_r <= 1'b1; rw_addr <= {{3{1'b1}}, ~tmp_pgm_data_switched[3], 1'b0}; //rw_16bit <= 1'b1; //rw_16bit <= 1'b1; if(tmp_pgm_data_switched[9]) begin rd_addr_d <= tmp_pgm_data_switched[8:4]; data_out_int <= rd_data_d; data_we_int <= 1'b1; end else begin rw_addr <= tmp_pgm_data_switched[8:4]; // Connect busses rw_data <= data_in_int; // Signalize write_to_reg; if(ram_read_delay == 0) write_to_reg <= 1'b1; data_re_int <= 1'b1; end end if(SEL_S1_INSTRUCTION_LD_ST_X | SEL_S1_INSTRUCTION_LD_ST_XP | SEL_S1_INSTRUCTION_LD_ST_XN) begin rd_addr_r <= 5'd26; rd_16bit_r <= 1'b1; rw_addr <= 5'd26; //rw_16bit <= 1'b1; //rw_16bit <= 1'b1; if(tmp_pgm_data_switched[9]) begin rd_addr_d <= tmp_pgm_data_switched[8:4]; data_out_int <= rd_data_d; data_we_int <= 1'b1; end else begin rw_addr <= tmp_pgm_data_switched[8:4]; // Connect busses rw_data <= data_in_int; // Signalize write_to_reg; if(ram_read_delay == 0) write_to_reg <= 1'b1; data_re_int <= 1'b1; end end if(SEL_S1_INSTRUCTION_ADIW | SEL_S1_INSTRUCTION_SBIW) begin rw_addr <= {2'b11, pgm_data_int[5:4], 1'b0}; rw_16bit <= 1'b1; rd_addr_d <= {2'b11, pgm_data_int[5:4], 1'b0}; rd_16bit_d <= 1'b1; //rd_addr_r <= {5{1'b00}}; rd_16bit_r <= 1'b1; // Connect busses rw_data <= alu_out; alu_in_1 <= rd_data_d; alu_in_2 <= {10'h000, pgm_data_int[7:6], pgm_data_int[3:0]}; // Signalize write_to_reg; write_to_reg <= 1'b1; end if(SEL_S1_INSTRUCTION_POP_PUSH) begin if(tmp_pgm_data_switched[9]) begin rd_addr_d <= tmp_pgm_data_switched[8:4]; data_out_int <= rd_data_d; data_we_int <= 1'b1; // Put "data_we" to high to store the selected register. end else begin rd_addr_d <= tmp_pgm_data_switched[8:4]; rw_addr <= tmp_pgm_data_switched[8:4]; // Connect busses rw_data <= data_in_int; // Signalize write_to_reg; if(ram_read_delay == 0) write_to_reg <= 1'b1; data_re_int <= 1'b1; end end if(SEL_S1_INSTRUCTION_IJMP) begin rd_addr_d <= 5'h1e; rd_16bit_d <= 1'b1; end end/*!CORE_CONFIG != "REDUCED" || CORE_CONFIG != "MINIMAL"*/ if(SEL_S1_INSTRUCTION_IN_OUT) begin rw_addr <= pgm_data_int[8:4]; rd_addr_d <= pgm_data_int[8:4]; if(!pgm_data_int[11]) begin case({pgm_data_int[10:9], pgm_data_int[3:0]}) `ifdef USE_CCP_REG 6'h34: begin if(CORE_CONFIG == "XMEGA") begin rw_data <= CCP; end end `endif `ifdef USE_EXTENDED_RAMP_REGS 6'h38: begin if(CORE_CONFIG == "XMEGA") begin rw_data <= RAMPD; end end 6'h39: begin if(CORE_CONFIG == "XMEGA") begin rw_data <= RAMPX; end end 6'h3A: begin if(CORE_CONFIG == "XMEGA") begin rw_data <= RAMPY; end end 6'h3B: begin if(CORE_CONFIG == "XMEGA") begin rw_data <= RAMPZ; end end 6'h3C: begin if(CORE_CONFIG == "XMEGA") begin rw_data <= EIND; end end `endif 6'h3D: //SPL begin if(CORE_CONFIG != "REDUCED") begin rw_data <= SP[7:0]; end end 6'h3E: //SPH begin if(CORE_CONFIG != "REDUCED" && CORE_CONFIG != "MINIMAL" && BUS_ADDR_DATA_WIDTH > 8) begin rw_data <= {{BUS_ADDR_DATA_WIDTH-1-8{1'b0}}, SP[BUS_ADDR_DATA_WIDTH-1:8]}; end end 6'h3F: rw_data <= ALU_FLAGS; default: begin io_addr_int <= {pgm_data_int[10:9], pgm_data_int[3:0]}; io_re_int <= 1'b1; rw_data <= io_in_int; end endcase // Signalize write_to_reg; write_to_reg <= 1'b1; end else begin case({pgm_data_int[10:9], pgm_data_int[3:0]}) `ifdef USE_CCP_REG 6'h34, `endif `ifdef USE_EXTENDED_RAMP_REGS 6'h38, 6'h39, 6'h3A, 6'h3B, 6'h3C, `endif 6'h3D,// SPL 6'h3E,// SPH 6'h3F:;//SREG default: begin io_addr_int <= {pgm_data_int[10:9], pgm_data_int[3:0]}; io_out_int <= rd_data_d; io_we_int <= 1'b1; // Put "data_we" to high to store the selected register. end endcase end end if(CORE_CONFIG == "XMEGA") begin if(SEL_S1_INSTRUCTION_XCH | SEL_S1_INSTRUCTION_LAS | SEL_S1_INSTRUCTION_LAC | SEL_S1_INSTRUCTION_LAT) begin rd_addr_d <= pgm_data_int[8:4]; rd_addr_r <= 5'h1e; rw_addr <= pgm_data_int[8:4]; data_re_int <= 1'b1; if(SEL_S1_INSTRUCTION_XCH) data_out_int <= rd_data_d; else if(SEL_S1_INSTRUCTION_LAS) data_out_int <= data_in_int | rd_data_d; else if(SEL_S1_INSTRUCTION_LAC) data_out_int <= data_in_int & ~rd_data_d; else if(SEL_S1_INSTRUCTION_LAT) data_out_int <= data_in_int ^ rd_data_d; // Connect busses rw_data <= data_in_int; // Signalize write_to_reg; write_to_reg <= 1'b1; end end if(CORE_CONFIG != "REDUCED" && CORE_CONFIG != "MINIMAL" && CORE_CONFIG != "CLASSIC_8K" && CORE_CONFIG != "CLASSIC_128K") begin if((SEL_S1_INSTRUCTION_MUL | SEL_S1_INSTRUCTION_MULS | SEL_S1_INSTRUCTION_MULSU | SEL_S1_INSTRUCTION_FMUL | SEL_S1_INSTRUCTION_FMULS | SEL_S1_INSTRUCTION_FMULSU)) begin rw_16bit <= 1'b1; rd_addr_d <= pgm_data_int[8:4]; rd_addr_r <= {pgm_data_int[9], pgm_data_int[3:0]}; // Connect busses alu_in_1 <= rd_data_d; alu_in_2 <= rd_data_r; rw_data <= alu_out; // Signalize write_to_reg; //write_to_reg <= 1'b1; // Because the multiply unit has more latency, we will add an extra clock. end end if(SEL_S1_INSTRUCTION_LDI) begin rw_addr <= {1'b1, pgm_data_int[7:4]}; // Connect busses rw_data <= {8'h00, pgm_data_int[11:8], pgm_data_int[3:0]}; // Signalize write_to_reg; write_to_reg <= 1'b1; end if(SEL_S1_INSTRUCTION_CBI_SBI) begin io_addr_int <= {{11{1'b0}}, pgm_data_int[7:3]}; case(pgm_data_int[2:0]) 3'h0: io_out_int <= {io_in_int[7:1], pgm_data_int[9]}; 3'h1: io_out_int <= {io_in_int[7:2], pgm_data_int[9], io_in_int[0]}; 3'h2: io_out_int <= {io_in_int[7:3], pgm_data_int[9], io_in_int[1:0]}; 3'h3: io_out_int <= {io_in_int[7:4], pgm_data_int[9], io_in_int[2:0]}; 3'h4: io_out_int <= {io_in_int[7:5], pgm_data_int[9], io_in_int[3:0]}; 3'h5: io_out_int <= {io_in_int[7:6], pgm_data_int[9], io_in_int[4:0]}; 3'h6: io_out_int <= {io_in_int[7], pgm_data_int[9], io_in_int[5:0]}; 3'h7: io_out_int <= {pgm_data_int[9], io_in_int[6:0]}; endcase io_re_int <= 1'b1; io_we_int <= 1'b1; end if(SEL_S1_INSTRUCTION_BLD_BST) begin rd_addr_d <= pgm_data_int[8:4]; if(~pgm_data_int[9]) begin rw_addr <= pgm_data_int[8:4]; // Signalize write_to_reg; write_to_reg <= 1'b1; case(pgm_data_int[2:0]) 3'h0: rw_data <= {rd_data_d[7:1], ALU_FLAGS[`ALU_FLAG_T]}; 3'h1: rw_data <= {rd_data_d[7:2], ALU_FLAGS[`ALU_FLAG_T], rd_data_d[0]}; 3'h2: rw_data <= {rd_data_d[7:3], ALU_FLAGS[`ALU_FLAG_T], rd_data_d[1:0]}; 3'h3: rw_data <= {rd_data_d[7:4], ALU_FLAGS[`ALU_FLAG_T], rd_data_d[2:0]}; 3'h4: rw_data <= {rd_data_d[7:5], ALU_FLAGS[`ALU_FLAG_T], rd_data_d[3:0]}; 3'h5: rw_data <= {rd_data_d[7:6], ALU_FLAGS[`ALU_FLAG_T], rd_data_d[4:0]}; 3'h6: rw_data <= {rd_data_d[7], ALU_FLAGS[`ALU_FLAG_T], rd_data_d[5:0]}; 3'h7: rw_data <= {ALU_FLAGS[`ALU_FLAG_T], rd_data_d[6:0]}; endcase end end if(SEL_S1_INSTRUCTION_RCALL) begin case(USE_BRAM_ROM) "TRUE" : data_out_int <= PC[7:0];// Put low byte of the PC. default : data_out_int <= PC_PLUS_ONE[7:0];// Put low byte of the PC. endcase data_we_int <= 1'b1; // Put "data_we" to high to store low byte of the PC. end if(SEL_S1_INSTRUCTION_ICALL && (CORE_CONFIG != "REDUCED" && CORE_CONFIG != "MINIMAL")) begin case(USE_BRAM_ROM) "TRUE" : data_out_int <= PC[7:0];// Put low byte of the PC. default : data_out_int <= PC_PLUS_ONE[7:0];// Put low byte of the PC. endcase data_we_int <= 1'b1; // Put "data_we" to high to store low byte of the PC. end if(interrupt_registered && VECTOR_INT_TABLE_SIZE != 0) begin case(USE_BRAM_ROM) "TRUE" : data_out_int <= PC_PLUS_ONE[7:0]; default : data_out_int <= PC[7:0]; endcase data_we_int <= 1'b1; // Put "data_we" to high to store low byte of the PC. end if((SEL_S1_INSTRUCTION_CALL && (CORE_CONFIG != "REDUCED" && CORE_CONFIG != "MINIMAL" && CORE_CONFIG != "CLASSIC_8K"))) begin case(USE_BRAM_ROM) "TRUE" : data_out_int <= PC_PLUS_ONE[7:0]; default : data_out_int <= PC_PLUS_TWO[7:0]; endcase data_we_int <= 1'b1; // Put "data_we" to high to store low byte of the PC. end if(SEL_S1_INSTRUCTION_RET | SEL_S1_INSTRUCTION_RETI) begin data_re_int <= 1'b1; end if(SEL_S1_INSTRUCTION_CPSE) begin rd_addr_d <= pgm_data_int[8:4]; rd_addr_r <= {pgm_data_int[9], pgm_data_int[3:0]}; end if(SEL_S1_INSTRUCTION_SBRC_SBRS) begin rd_addr_d <= pgm_data_int[8:4]; end if(SEL_S1_INSTRUCTION_SBIC_SBIS) begin io_addr_int <= {{11{1'b0}}, pgm_data_int[7:3]}; io_re_int <= 1'b1; end end `STEP2: begin `ifdef USE_LPM if(CORE_CONFIG != "REDUCED") begin if(SEL_S2_INSTRUCTION_LPM_R | SEL_S2_INSTRUCTION_LPM_R_P | SEL_S2_INSTRUCTION_LPM_ELPM) begin if(~rom_read_delay || USE_BRAM_ROM == "FALSE") begin if(SEL_S2_INSTRUCTION_LPM_ELPM) rw_addr <= 0; else rw_addr <= tmp_pgm_data[8:4]; rw_data <= pgm_indirect_addr[0] ? pgm_data_int[15:8] : pgm_data_int[7:0]; rw_16bit <= 1'b0; // Signalize write_to_reg; write_to_reg <= 1'b1; end end end `endif if(CORE_CONFIG != "REDUCED" && CORE_CONFIG != "MINIMAL") begin if(SEL_S2_INSTRUCTION_ICALL) begin case(USE_BRAM_ROM) "TRUE" : data_out_int <= {{BUS_ADDR_PGM_WIDTH-1-8{1'b0}}, PC[BUS_ADDR_PGM_WIDTH-1:8]};// Put high byte of the PC. default : data_out_int <= {{BUS_ADDR_PGM_WIDTH-1-8{1'b0}}, PC_PLUS_ONE[BUS_ADDR_PGM_WIDTH-1:8]};// Put high byte of the PC. endcase rd_addr_d <= 5'h1e; data_we_int <= 1'b1; // Put "data_we" to high to store low byte of the PC. rd_16bit_d <= 1'b1; end if(SEL_S2_INSTRUCTION_LDS_STS) begin if(tmp_pgm_data[9]) begin rd_addr_d <= tmp_pgm_data[8:4]; if(select_io_in_stam) begin case(pgm_data_int[(CORE_CONFIG == "XMEGA" ? 5 : 6):0]) `ifdef USE_CCP_REG 'h34 + io_ports_displacement, `endif `ifdef USE_EXTENDED_RAMP_REGS 'h38 + io_ports_displacement, 'h39 + io_ports_displacement, 'h3A + io_ports_displacement, 'h3B + io_ports_displacement, 'h3C + io_ports_displacement, `endif 'h00, 'h01, 'h02, 'h03, 'h04, 'h05, 'h06, 'h07, 'h08, 'h09, 'h0A, 'h0B, 'h0C, 'h0D, 'h0E, 'h0F, 'h10, 'h11, 'h12, 'h13, 'h14, 'h15, 'h16, 'h17, 'h18, 'h19, 'h1A, 'h1B, 'h1C, 'h1D, 'h1E, 'h1F: begin if(CORE_CONFIG != "XMEGA") begin if(MAP_REGS_IN_TO_SRAM_SECTION == "TRUE") begin rw_addr <= tmp_pgm_data[4:0]; rw_data <= rd_data_d; end end end 'h3D + io_ports_displacement,// SPL 'h3E + io_ports_displacement,// SPH 'h3F + io_ports_displacement:;//SREG default: begin data_out_int <= rd_data_d; data_we_int <= 1'b1; end endcase end else begin data_out_int <= rd_data_d; data_we_int <= 1'b1; end end else begin rw_addr <= tmp_pgm_data[8:4]; // Signalize write_to_reg; //write_to_reg <= 1'b1; if(select_io_in_stam) begin `ifdef USE_RAM_READ_DELAY if(ram_read_delay == `USE_RAM_READ_DELAY) `endif write_to_reg <= 1'b1; case(pgm_data_int[(CORE_CONFIG == "XMEGA" ? 5 : 6):0]) `ifdef USE_CCP_REG 'h34 + io_ports_displacement: rw_data <= CCP; `endif `ifdef USE_EXTENDED_RAMP_REGS 'h38 + io_ports_displacement: rw_data <= RAMPD; 'h39 + io_ports_displacement: rw_data <= RAMPX; 'h3A + io_ports_displacement: rw_data <= RAMPY; 'h3B + io_ports_displacement: rw_data <= RAMPZ; 'h3C + io_ports_displacement: rw_data <= EIND; `endif 'h00, 'h01, 'h02, 'h03, 'h04, 'h05, 'h06, 'h07, 'h08, 'h09, 'h0A, 'h0B, 'h0C, 'h0D, 'h0E, 'h0F, 'h10, 'h11, 'h12, 'h13, 'h14, 'h15, 'h16, 'h17, 'h18, 'h19, 'h1A, 'h1B, 'h1C, 'h1D, 'h1E, 'h1F: begin if(CORE_CONFIG != "XMEGA") begin if(MAP_REGS_IN_TO_SRAM_SECTION == "TRUE") begin rd_addr_d <= tmp_pgm_data[4:0]; rw_data <= rd_data_d; end end end 'h3D + io_ports_displacement: //SPL begin if(CORE_CONFIG != "REDUCED") begin rw_data <= SP[7:0]; end end 'h3E + io_ports_displacement: //SPH begin if(CORE_CONFIG != "REDUCED" && CORE_CONFIG != "MINIMAL" && BUS_ADDR_DATA_WIDTH > 8) begin rw_data <= {{BUS_ADDR_DATA_WIDTH-1-8{1'b0}}, SP[BUS_ADDR_DATA_WIDTH-1:8]}; end end 'h3F + io_ports_displacement: rw_data <= ALU_FLAGS;//SREG default: begin // Connect busses rw_data <= data_in_int; data_re_int <= 1'b1; end endcase end else begin //rd_addr_d <= tmp_pgm_data[4:0]; //rw_data <= rd_data_d; `ifdef USE_RAM_READ_DELAY if(ram_read_delay == 0) `endif write_to_reg <= 1'b1; rw_data <= data_in_int; data_re_int <= 1'b1; end end end if(SEL_S2_INSTRUCTION_LD_ST_X | SEL_S2_INSTRUCTION_LD_ST_XP | SEL_S2_INSTRUCTION_LD_ST_XN) begin rd_addr_r <= 5'd26; rd_16bit_r <= 1'b1; rw_addr <= 5'd26; rw_16bit <= 1'b1; case(tmp_pgm_data[1:0]) 2'b00: rw_data <= rd_data_r; 2'b01: rw_data <= rd_data_r_PLUS_ONE; 2'b10: rw_data <= rd_data_r_MINUS_ONE; endcase // Signalize write_to_reg; write_to_reg <= 1'b1; end if(SEL_S2_INSTRUCTION_LD_ST_YZP | SEL_S2_INSTRUCTION_LD_ST_YZN) begin rd_addr_r <= {{3{1'b1}}, ~tmp_pgm_data[3], 1'b0}; rd_16bit_r <= 1'b1; rw_addr <= {{3{1'b1}}, ~tmp_pgm_data[3], 1'b0}; rw_16bit <= 1'b1; case(tmp_pgm_data[1:0]) 2'b01: rw_data <= rd_data_r_PLUS_ONE; 2'b10: rw_data <= rd_data_r_MINUS_ONE; endcase // Signalize write_to_reg; write_to_reg <= 1'b1; end end/*!CORE_CONFIG != "REDUCED" && CORE_CONFIG != "MINIMAL"*/ if(CORE_CONFIG != "REDUCED" && CORE_CONFIG != "MINIMAL" && CORE_CONFIG != "CLASSIC_8K" && CORE_CONFIG != "CLASSIC_128K") begin if((SEL_S2_INSTRUCTION_MUL | SEL_S2_INSTRUCTION_MULS | SEL_S2_INSTRUCTION_MULSU | SEL_S2_INSTRUCTION_FMUL | SEL_S2_INSTRUCTION_FMULS | SEL_S2_INSTRUCTION_FMULSU)) begin rw_16bit <= 1'b1; rd_addr_d <= pgm_data_int[8:4]; rd_addr_r <= {pgm_data_int[9], pgm_data_int[3:0]}; // Connect busses alu_in_1 <= rd_data_d; alu_in_2 <= rd_data_r; rw_data <= alu_out; // Signalize write_to_reg; write_to_reg <= 1'b1; end end if(SEL_S2_INSTRUCTION_RET | SEL_S2_INSTRUCTION_RETI) begin data_re_int <= 1'b1; end if(interrupt_registered && VECTOR_INT_TABLE_SIZE != 0) begin case(USE_BRAM_ROM) "TRUE" : data_out_int <= {{BUS_ADDR_PGM_WIDTH-1-8{1'b0}}, PC_PLUS_ONE[BUS_ADDR_PGM_WIDTH-1:8]};// Put high byte of the PC. default : data_out_int <= {{BUS_ADDR_PGM_WIDTH-1-8{1'b0}}, PC[BUS_ADDR_PGM_WIDTH-1:8]}; endcase data_we_int <= 1'b1; // Put "data_we" to high to store low byte of the PC. end if(SEL_S2_INSTRUCTION_RCALL) begin case(USE_BRAM_ROM) "TRUE" : data_out_int <= {{BUS_ADDR_PGM_WIDTH-1-8{1'b0}}, PC[BUS_ADDR_PGM_WIDTH-1:8]};// Put high byte of the PC. default : data_out_int <= {{BUS_ADDR_PGM_WIDTH-1-8{1'b0}}, PC_PLUS_ONE[BUS_ADDR_PGM_WIDTH-1:8]};// Put high byte of the PC. endcase data_we_int <= 1'b1; // Put "data_we" to high to store low byte of the PC. end if((SEL_S2_INSTRUCTION_CALL && (CORE_CONFIG != "REDUCED" && CORE_CONFIG != "MINIMAL" && CORE_CONFIG != "CLASSIC_8K"))) begin case(USE_BRAM_ROM) "TRUE" : data_out_int <= {{BUS_ADDR_PGM_WIDTH-1-8{1'b0}}, PC[BUS_ADDR_PGM_WIDTH-1:8]};// Put high byte of the PC. default : data_out_int <= {{BUS_ADDR_PGM_WIDTH-1-8{1'b0}}, PC_PLUS_ONE[BUS_ADDR_PGM_WIDTH-1:8]};// Put high byte of the PC. endcase data_we_int <= 1'b1; // Put "data_we" to high to store low byte of the PC. end if(SEL_S2_INSTRUCTION_CPSE) begin rd_addr_d <= tmp_pgm_data[8:4]; rd_addr_r <= {tmp_pgm_data[9], tmp_pgm_data[3:0]}; end if(SEL_S2_INSTRUCTION_SBRC_SBRS) begin rd_addr_d <= tmp_pgm_data[8:4]; end if(SEL_S2_INSTRUCTION_SBIC_SBIS) begin io_addr_int <= {{11{1'b0}}, tmp_pgm_data[7:3]}; io_re_int <= 1'b1; end end endcase end end end /* * !Busses switch. */ wire [15:0]relative_offset = (USE_BRAM_ROM == "TRUE") ? PC + {{5{tmp_pgm_data[11]}}, tmp_pgm_data[10:0]} : PC_PLUS_ONE + {{5{pgm_data_int[11]}}, pgm_data_int[10:0]}; wire [15:0]relative_offset_rjmp = PC + {{5{pgm_data_int[11]}}, pgm_data_int[10:0]}; reg [BUS_ADDR_PGM_WIDTH-1-8:0]PGM_HI_TMP; /* * Instruction execution sequencer. */ always @ (posedge clk) begin if((WATCHDOG_CNT_WIDTH != 'd0) ? core_rst : rst) begin reg_clr_cnt <= 0; end else if(~alu_rdy) begin ALU_FLAGS[0] <= 1'b0; //Carry Flag ALU_FLAGS[1] <= 1'b0; //Zero Flag ALU_FLAGS[2] <= 1'b0; //Negative Flag ALU_FLAGS[3] <= 1'b0; //Two's complement overflow indicator ALU_FLAGS[4] <= 1'b0; //N?V for signed tests ALU_FLAGS[5] <= 1'b0; //Half Carry Flag ALU_FLAGS[6] <= 1'b0; //Transfer bit used by BLD and BST instructions ALU_FLAGS[7] <= 1'b0; //Global Interrupt Enable/Disable Flag SEL_S2_INSTRUCTION_CPSE <= 'h0; SEL_S2_INSTRUCTION_LDS_STS <= 'h0; SEL_S2_INSTRUCTION_LD_ST_YZP <= 'h0; SEL_S2_INSTRUCTION_LD_ST_YZN <= 'h0; SEL_S2_INSTRUCTION_LPM_ELPM <= 'h0; SEL_S2_INSTRUCTION_LPM_R <= 'h0; SEL_S2_INSTRUCTION_LPM_R_P <= 'h0; SEL_S2_INSTRUCTION_LD_ST_X <= 'h0; SEL_S2_INSTRUCTION_LD_ST_XP <= 'h0; SEL_S2_INSTRUCTION_LD_ST_XN <='h0 ; SEL_S2_INSTRUCTION_RET <= 'h0; SEL_S2_INSTRUCTION_RETI <= 'h0; SEL_S2_INSTRUCTION_ICALL <= 'h0; SEL_S2_INSTRUCTION_JMP <= 'h0; SEL_S2_INSTRUCTION_CALL <= 'h0; SEL_S2_INSTRUCTION_SBIC_SBIS <= 'h0; SEL_S2_INSTRUCTION_MUL <= 'h0; SEL_S2_INSTRUCTION_MULS <= 'h0; SEL_S2_INSTRUCTION_MULSU <= 'h0; SEL_S2_INSTRUCTION_FMUL <= 'h0; SEL_S2_INSTRUCTION_FMULS <= 'h0; SEL_S2_INSTRUCTION_FMULSU <= 'h0; SEL_S2_INSTRUCTION_RCALL <= 'h0; SEL_S2_INSTRUCTION_SBRC_SBRS <= 'h0; PC <= 'h0000; SP <= 'h0000; current_int_executed <= 1'b0; if (USE_BRAM_ROM == "TRUE") skip_execution <= 1'b0; if(CORE_CONFIG == "XMEGA") begin `ifdef USE_CCP_REG CCP <= 8'h0; `endif //!USE_CCP_REG `ifdef USE_EXTENDED_RAMP_REGS RAMPD <= 8'h0; RAMPX <= 8'h0; RAMPY <= 8'h0; RAMPZ <= 8'h0; EIND <= 8'h0; `endif //!USE_EXTENDED_RAMP_REGS end/*!CORE_CONFIG == "XMEGA"*/ step_cnt <= `STEP1; `ifdef USE_RAM_READ_DELAY ram_read_delay <= `USE_RAM_READ_DELAY; `endif rom_read_delay <= 1'b1; reg_clr_cnt <= reg_clr_cnt + 1; wdt_rst_out <= 1'b0; interrupt_registered <= 1'b0; end else begin /* * Preserve flags until otervice specified. */ ALU_FLAGS[0] <= ALU_FLAG_C_OUT; //Carry Flag ALU_FLAGS[1] <= ALU_FLAG_Z_OUT; //Zero Flag ALU_FLAGS[2] <= ALU_FLAG_N_OUT; //Negative Flag ALU_FLAGS[3] <= ALU_FLAG_V_OUT; //Two's complement overflow indicator ALU_FLAGS[4] <= ALU_FLAG_S_OUT; //N?V for signed tests ALU_FLAGS[5] <= ALU_FLAG_H_OUT; //Half Carry Flag ALU_FLAGS[6] <= ALU_FLAG_T_OUT; //Transfer bit used by BLD and BST instructions ALU_FLAGS[7] <= ALU_FLAG_I_OUT; //Global Interrupt Enable/Disable Flag step_cnt <= `STEP1; PC <= PC_PLUS_ONE;// Increment PC by 1 if not specified otherwise. wdt_rst_out <= 1'b0; current_int_executed <= 1'b0; int_rst <= 'h00; `ifdef USE_RAM_READ_DELAY if(ram_read_delay == `USE_RAM_READ_DELAY) begin `endif SEL_S2_INSTRUCTION_CPSE <= SEL_S1_INSTRUCTION_CPSE; SEL_S2_INSTRUCTION_LDS_STS <= SEL_S1_INSTRUCTION_LDS_STS; SEL_S2_INSTRUCTION_LD_ST_YZP <= SEL_S1_INSTRUCTION_LD_ST_YZP; SEL_S2_INSTRUCTION_LD_ST_YZN <= SEL_S1_INSTRUCTION_LD_ST_YZN; SEL_S2_INSTRUCTION_LPM_R <= SEL_S1_INSTRUCTION_LPM_R; SEL_S2_INSTRUCTION_LPM_R_P <= SEL_S1_INSTRUCTION_LPM_R_P; SEL_S2_INSTRUCTION_LPM_ELPM <= SEL_S1_INSTRUCTION_LPM_ELPM; SEL_S2_INSTRUCTION_LD_ST_X <= SEL_S1_INSTRUCTION_LD_ST_X; SEL_S2_INSTRUCTION_LD_ST_XP <= SEL_S1_INSTRUCTION_LD_ST_XP; SEL_S2_INSTRUCTION_LD_ST_XN <=SEL_S1_INSTRUCTION_LD_ST_XN ; SEL_S2_INSTRUCTION_RET <= SEL_S1_INSTRUCTION_RET; SEL_S2_INSTRUCTION_RETI <= SEL_S1_INSTRUCTION_RETI; SEL_S2_INSTRUCTION_ICALL <= SEL_S1_INSTRUCTION_ICALL; SEL_S2_INSTRUCTION_JMP <= SEL_S1_INSTRUCTION_JMP; SEL_S2_INSTRUCTION_CALL <= SEL_S1_INSTRUCTION_CALL; SEL_S2_INSTRUCTION_SBIC_SBIS <= SEL_S1_INSTRUCTION_SBIC_SBIS; SEL_S2_INSTRUCTION_MUL <= SEL_S1_INSTRUCTION_MUL; SEL_S2_INSTRUCTION_MULS <= SEL_S1_INSTRUCTION_MULS; SEL_S2_INSTRUCTION_MULSU <= SEL_S1_INSTRUCTION_MULSU; SEL_S2_INSTRUCTION_FMUL <= SEL_S1_INSTRUCTION_FMUL; SEL_S2_INSTRUCTION_FMULS <= SEL_S1_INSTRUCTION_FMULS; SEL_S2_INSTRUCTION_FMULSU <= SEL_S1_INSTRUCTION_FMULSU; SEL_S2_INSTRUCTION_RCALL <= SEL_S1_INSTRUCTION_RCALL; SEL_S2_INSTRUCTION_SBRC_SBRS <= SEL_S1_INSTRUCTION_SBRC_SBRS; `ifdef USE_RAM_READ_DELAY end `endif `ifdef USE_RAM_READ_DELAY //if(int_request && step_cnt == `STEP1 && ram_read_delay == `USE_RAM_READ_DELAY && ALU_FLAGS[7] && VECTOR_INT_TABLE_SIZE != 0) if(int_request && ALU_FLAGS[7] && VECTOR_INT_TABLE_SIZE != 0) begin case(step_cnt) /*`STEP1: begin if(ram_read_delay == 0 && //(SEL_S1_INSTRUCTION_LDD_STD && ~tmp_pgm_data_switched[9]) || (SEL_S1_INSTRUCTION_POP_PUSH && ~tmp_pgm_data_switched[9])) begin if(current_int_vect) begin interrupt_registered <= 1'b1; current_int_vect_int <= current_int_vect; PC <= PC_PLUS_ONE; int_rst <= 1'b1 << (current_int_vect - 1); end end end */ `STEP2: begin if(ram_read_delay == 0 && (SEL_S2_INSTRUCTION_LPM_R || SEL_S2_INSTRUCTION_LPM_R_P || SEL_S2_INSTRUCTION_LPM_ELPM || (SEL_S2_INSTRUCTION_LDS_STS && ~pgm_data_int[9]) || ((SEL_S2_INSTRUCTION_MUL | SEL_S2_INSTRUCTION_MULS | SEL_S2_INSTRUCTION_MULSU | SEL_S2_INSTRUCTION_FMUL | SEL_S2_INSTRUCTION_FMULS | SEL_S2_INSTRUCTION_FMULSU) && (CORE_CONFIG != "CLASSIC_8K" && CORE_CONFIG != "CLASSIC_128K")) || ((SEL_S2_INSTRUCTION_LD_ST_YZP || SEL_S2_INSTRUCTION_LD_ST_YZN || SEL_S2_INSTRUCTION_LD_ST_X || SEL_S2_INSTRUCTION_LD_ST_XP || SEL_S2_INSTRUCTION_LD_ST_XN) && ~pgm_data_int[9]) || (SEL_S2_INSTRUCTION_JMP && (CORE_CONFIG != "REDUCED" && CORE_CONFIG != "MINIMAL" && CORE_CONFIG != "CLASSIC_8K")) || (SEL_S2_INSTRUCTION_ICALL && (CORE_CONFIG != "REDUCED" && CORE_CONFIG != "MINIMAL")) || (SEL_S2_INSTRUCTION_CALL && (CORE_CONFIG != "REDUCED" && CORE_CONFIG != "MINIMAL" && CORE_CONFIG != "CLASSIC_8K")) || SEL_S2_INSTRUCTION_RCALL || SEL_S2_INSTRUCTION_RET || SEL_S2_INSTRUCTION_RETI || SEL_S2_INSTRUCTION_CPSE || SEL_S2_INSTRUCTION_SBRC_SBRS || SEL_S2_INSTRUCTION_SBIC_SBIS)) begin if(current_int_vect) begin interrupt_registered <= 1'b1; current_int_vect_int <= current_int_vect; PC <= PC_PLUS_ONE; int_rst <= 1'b1 << (current_int_vect - 1); end end end endcase end `else if(int_request && step_cnt == `STEP1 && ALU_FLAGS[7] && VECTOR_INT_TABLE_SIZE != 0) begin interrupt_registered <= 1'b1; current_int_vect_int <= current_int_vect; PC <= PC - 1; int_rst <= 1'b1 << (current_int_vect - 1); end `endif if(skip_execution == 1'b0 || USE_BRAM_ROM != "TRUE") begin case(step_cnt) `STEP1: begin if(SEL_S1_INSTRUCTION_WDR) begin case(WATCHDOG_CNT_WIDTH) 0:; default: wdt_rst_out <= 1'b1; endcase end if(SEL_S1_INSTRUCTION_IN_OUT) begin if(pgm_data_int[11]) begin case({pgm_data_int[10:9], pgm_data_int[3:0]}) `ifdef USE_CCP_REG 6'h34: begin if(CORE_CONFIG == "XMEGA") begin CCP <= rd_data_d; end end `endif `ifdef USE_EXTENDED_RAMP_REGS 6'h38: begin if(CORE_CONFIG == "XMEGA") begin RAMPD <= rd_data_d; end end 6'h39: begin if(CORE_CONFIG == "XMEGA") begin RAMPX <= rd_data_d; end end 6'h3A: begin if(CORE_CONFIG == "XMEGA") begin RAMPY <= rd_data_d; end end 6'h3B: begin if(CORE_CONFIG == "XMEGA") begin RAMPZ <= rd_data_d; end end 6'h3C: begin if(CORE_CONFIG == "XMEGA") begin EIND <= rd_data_d; end end `endif 6'h3D: //SPL begin if(CORE_CONFIG != "REDUCED") begin SP[7:0] <= rd_data_d; end end 6'h3E: //SPH begin if(CORE_CONFIG != "REDUCED" && CORE_CONFIG != "MINIMAL" && BUS_ADDR_DATA_WIDTH > 8) begin SP[BUS_ADDR_DATA_WIDTH-1:8] <= rd_data_d[BUS_ADDR_DATA_WIDTH-1-8:0]; end end 6'h3F: ALU_FLAGS <= rd_data_d;//SREG endcase end end if(CORE_CONFIG != "REDUCED") begin `ifdef USE_RAM_READ_DELAY if(SEL_S1_INSTRUCTION_LDD_STD) begin if(~tmp_pgm_data_switched[9]) begin if(ram_read_delay == `USE_RAM_READ_DELAY) tmp_pgm_data <= pgm_data_int; if(ram_read_delay) begin ram_read_delay <= ram_read_delay - 1; PC <= PC; step_cnt <= step_cnt; end else begin ram_read_delay <= `USE_RAM_READ_DELAY; end end end `endif `ifdef USE_LPM if(SEL_S1_INSTRUCTION_LPM_R | SEL_S1_INSTRUCTION_LPM_R_P | SEL_S1_INSTRUCTION_LPM_ELPM) begin tmp_pgm_data <= pgm_data_int; pgm_indirect_addr <= rd_data_d[BUS_ADDR_PGM_WIDTH-1:0]; case(USE_BRAM_ROM) "TRUE" : PC <= PC; endcase step_cnt <= `STEP2; end `endif if(SEL_S1_INSTRUCTION_POP_PUSH) begin if(tmp_pgm_data_switched[9]) SP <= SP_MINUS_ONE; else begin `ifdef USE_RAM_READ_DELAY if(ram_read_delay == `USE_RAM_READ_DELAY) tmp_pgm_data <= pgm_data_int; if(ram_read_delay) begin ram_read_delay <= ram_read_delay - 1; PC <= PC; step_cnt <= step_cnt; end else begin ram_read_delay <= `USE_RAM_READ_DELAY; SP <= SP_PLUS_ONE; end `else SP <= SP_PLUS_ONE; `endif end end end/*!CORE_CONFIG == "REDUCED"*/ if(CORE_CONFIG != "REDUCED" && CORE_CONFIG != "MINIMAL") begin if(SEL_S1_INSTRUCTION_IJMP) begin PC <= rd_data_d; case(USE_BRAM_ROM) "TRUE" : skip_execution <= 1'b1; endcase end if(SEL_S1_INSTRUCTION_LDS_STS) begin tmp_pgm_data <= pgm_data_int; step_cnt <= `STEP2; end if((SEL_S1_INSTRUCTION_MUL | SEL_S1_INSTRUCTION_MULS | SEL_S1_INSTRUCTION_MULSU | SEL_S1_INSTRUCTION_FMUL | SEL_S1_INSTRUCTION_FMULS | SEL_S1_INSTRUCTION_FMULSU) && (CORE_CONFIG != "CLASSIC_8K" && CORE_CONFIG != "CLASSIC_128K")) begin tmp_pgm_data <= pgm_data_int; step_cnt <= `STEP2; PC <= PC; end if(SEL_S1_INSTRUCTION_LD_ST_YZP | SEL_S1_INSTRUCTION_LD_ST_YZN | SEL_S1_INSTRUCTION_LD_ST_X | SEL_S1_INSTRUCTION_LD_ST_XP | SEL_S1_INSTRUCTION_LD_ST_XN) begin `ifdef USE_RAM_READ_DELAY if((~pgm_data_int[9] && ram_read_delay == `USE_RAM_READ_DELAY) || (~tmp_pgm_data[9] && ram_read_delay != `USE_RAM_READ_DELAY)) begin if(ram_read_delay) begin if(ram_read_delay == `USE_RAM_READ_DELAY) tmp_pgm_data <= pgm_data_int; ram_read_delay <= ram_read_delay - 1; PC <= PC; step_cnt <= step_cnt; end else begin ram_read_delay <= `USE_RAM_READ_DELAY; case(USE_BRAM_ROM) "TRUE" :; default: tmp_pgm_data <= pgm_data_int; endcase step_cnt <= `STEP2; PC <= PC; end end else begin tmp_pgm_data <= pgm_data_int; step_cnt <= `STEP2; PC <= PC; end `else tmp_pgm_data <= pgm_data_int; step_cnt <= `STEP2; PC <= PC; `endif end end/*!CORE_CONFIG != "REDUCED" && CORE_CONFIG != "MINIMAL"*/ if(CORE_CONFIG != "REDUCED" && CORE_CONFIG != "MINIMAL" && CORE_CONFIG != "CLASSIC_8K") begin if(SEL_S1_INSTRUCTION_JMP) begin tmp_pgm_data <= pgm_data_int; step_cnt <= `STEP2; end end if(SEL_S1_INSTRUCTION_RJMP) begin case(USE_BRAM_ROM) "TRUE" : begin skip_execution <= 1'b1; if(PC) PC <= relative_offset_rjmp; else PC <= relative_offset_rjmp + 1; end default : PC <= relative_offset; endcase end if((SEL_S1_INSTRUCTION_ICALL && (CORE_CONFIG != "REDUCED" && CORE_CONFIG != "MINIMAL")) | (SEL_S1_INSTRUCTION_CALL && (CORE_CONFIG != "REDUCED" && CORE_CONFIG != "MINIMAL" && CORE_CONFIG != "CLASSIC_8K")) | SEL_S1_INSTRUCTION_RCALL | interrupt_registered) begin step_cnt <= `STEP2; tmp_pgm_data <= pgm_data_int; SP <= SP_MINUS_ONE; if((SEL_S1_INSTRUCTION_ICALL && (CORE_CONFIG != "REDUCED" && CORE_CONFIG != "MINIMAL")) | SEL_S1_INSTRUCTION_RCALL) PC <= PC; else if(interrupt_registered && VECTOR_INT_TABLE_SIZE != 0) begin ALU_FLAGS[7] <= 1'b0; PC <= PC; end end if(SEL_S1_INSTRUCTION_RET | SEL_S1_INSTRUCTION_RETI) begin `ifdef USE_RAM_READ_DELAY if(ram_read_delay == `USE_RAM_READ_DELAY) tmp_pgm_data <= pgm_data_int; if(ram_read_delay) begin ram_read_delay <= ram_read_delay - 1; PC <= PC; step_cnt <= step_cnt; end else begin step_cnt <= `STEP2; SP <= SP_PLUS_ONE; PGM_HI_TMP <= data_in_int; ram_read_delay <= `USE_RAM_READ_DELAY; end `else tmp_pgm_data <= pgm_data_int; step_cnt <= `STEP2; SP <= SP_PLUS_ONE; PGM_HI_TMP <= data_in_int; PC <= PC; `endif end if(SEL_S1_INSTRUCTION_COND_BRANCH) begin if(~pgm_data_int[10] == ALU_FLAGS[pgm_data_int[2:0]]) begin case(USE_BRAM_ROM) "TRUE" : begin skip_execution <= 1'b1; PC <= PC + {{10{pgm_data_int[9]}}, pgm_data_int[8:3]}; end default : PC <= PC + {{10{pgm_data_int[9]}}, pgm_data_int[8:3]} + 16'h0001; endcase end end if(SEL_S1_INSTRUCTION_CPSE) begin case(USE_BRAM_ROM) "TRUE" : begin if(rd_data_d != rd_data_r) begin tmp_pgm_data <= pgm_data_int; step_cnt <= `STEP2; end end default: begin tmp_pgm_data <= pgm_data_int; step_cnt <= `STEP2; end endcase end if(SEL_S1_INSTRUCTION_SBRC_SBRS) begin case(USE_BRAM_ROM) "TRUE" : begin if(rd_data_d[tmp_pgm_data[2:0]] != tmp_pgm_data[9]) begin tmp_pgm_data <= pgm_data_int; step_cnt <= `STEP2; end end default: begin tmp_pgm_data <= pgm_data_int; step_cnt <= `STEP2; end endcase end if(SEL_S1_INSTRUCTION_SBIC_SBIS) begin case(USE_BRAM_ROM) "TRUE" : begin if(io_in_int[tmp_pgm_data[2:0]] != tmp_pgm_data[9]) begin tmp_pgm_data <= pgm_data_int; step_cnt <= `STEP2; end end default: begin tmp_pgm_data <= pgm_data_int; step_cnt <= `STEP2; end endcase end if(SEL_S1_INSTRUCTION_BLD_BST) begin if(pgm_data_int[9]) ALU_FLAGS[`ALU_FLAG_T] <= rd_data_d[pgm_data_int[2:0]]; end end `STEP2: begin if(CORE_CONFIG != "REDUCED") begin `ifdef USE_LPM if(SEL_S2_INSTRUCTION_LPM_R | SEL_S2_INSTRUCTION_LPM_R_P) begin case(USE_BRAM_ROM) "TRUE": begin if(rom_read_delay) begin rom_read_delay <= 1'b0; step_cnt <= `STEP2; end else begin rom_read_delay <= 1'b1; skip_execution <= 1'b1; end end endcase PC <= PC; end `endif end if(CORE_CONFIG != "REDUCED" && CORE_CONFIG != "MINIMAL") begin if(SEL_S2_INSTRUCTION_LDS_STS) begin if(tmp_pgm_data[9]) begin if(select_io_in_stam) begin case(pgm_data_int[(CORE_CONFIG == "XMEGA" ? 5 : 6):0]) `ifdef USE_CCP_REG 'h34 + io_ports_displacement: begin if(CORE_CONFIG == "XMEGA") begin CCP <= rd_data_d; end end `endif `ifdef USE_EXTENDED_RAMP_REGS 'h38 + io_ports_displacement: begin if(CORE_CONFIG == "XMEGA") begin RAMPD <= rd_data_d; end end 'h39 + io_ports_displacement: begin if(CORE_CONFIG == "XMEGA") begin RAMPX <= rd_data_d; end end 'h3A + io_ports_displacement: begin if(CORE_CONFIG == "XMEGA") begin RAMPY <= rd_data_d; end end 'h3B + io_ports_displacement: begin if(CORE_CONFIG == "XMEGA") begin RAMPZ <= rd_data_d; end end 'h3C + io_ports_displacement: begin if(CORE_CONFIG == "XMEGA") begin EIND <= rd_data_d; end end `endif 'h3D + io_ports_displacement: //SPL begin if(CORE_CONFIG != "REDUCED") begin SP[7:0] <= rd_data_d; end end 'h3E + io_ports_displacement: //SPH begin if(CORE_CONFIG != "REDUCED" && CORE_CONFIG != "MINIMAL" && BUS_ADDR_DATA_WIDTH > 8) begin SP[BUS_ADDR_DATA_WIDTH-1:8] <= rd_data_d[BUS_ADDR_DATA_WIDTH-1-8:0]; end end 'h3F + io_ports_displacement: ALU_FLAGS <= rd_data_d;//SREG endcase end end else begin `ifdef USE_RAM_READ_DELAY if(ram_read_delay) begin ram_read_delay <= ram_read_delay - 1; PC <= PC; step_cnt <= step_cnt; data_addr_int_tmp <= pgm_data_int; end else begin ram_read_delay <= `USE_RAM_READ_DELAY; end `endif end end if(SEL_S2_INSTRUCTION_ICALL) begin SP <= SP_MINUS_ONE; PC <= rd_data_d;// Backup the reg Z value to a 16bit temporary register because the reading section of REG's is asynchronous. case(USE_BRAM_ROM) "TRUE" : skip_execution <= 1'b1; endcase end end/*!CORE_CONFIG != "REDUCED" && CORE_CONFIG != "MINIMAL"*/ if(CORE_CONFIG != "REDUCED" && CORE_CONFIG != "MINIMAL" && CORE_CONFIG != "CLASSIC_8K") begin if(SEL_S2_INSTRUCTION_JMP) begin PC <= pgm_data_int; case(USE_BRAM_ROM) "TRUE" : skip_execution <= 1'b1; endcase end end if((SEL_S2_INSTRUCTION_CALL && (CORE_CONFIG != "REDUCED" && CORE_CONFIG != "MINIMAL" && CORE_CONFIG != "CLASSIC_8K")) | interrupt_registered) begin SP <= SP_MINUS_ONE; if(interrupt_registered && VECTOR_INT_TABLE_SIZE != 0) begin interrupt_registered <= 1'b0; current_int_executed <= 1'b1; if(CORE_CONFIG == "XMEGA") begin PC <= {current_int_vect_int, 1'b0}; end else begin if(BUS_ADDR_PGM_WIDTH > 12) PC <= {current_int_vect_int, 1'b0}; else PC <= current_int_vect_int; end end else begin PC <= pgm_data_int; end case(USE_BRAM_ROM) "TRUE" : skip_execution <= 1'b1; endcase end if(SEL_S2_INSTRUCTION_RCALL) begin SP <= SP_MINUS_ONE; PC <= relative_offset;// If is a relative CALL load the offset to "TEMP16". case(USE_BRAM_ROM) "TRUE" : skip_execution <= 1'b1; endcase end if(SEL_S2_INSTRUCTION_RET | SEL_S2_INSTRUCTION_RETI) begin `ifdef USE_RAM_READ_DELAY if(ram_read_delay == `USE_RAM_READ_DELAY) tmp_pgm_data <= tmp_pgm_data; if(ram_read_delay) begin ram_read_delay <= ram_read_delay - 1; PC <= PC; step_cnt <= step_cnt; end else begin `endif SP <= SP_PLUS_ONE; if(tmp_pgm_data[4]) ALU_FLAGS[7] <= 1'b1; PC <= {PGM_HI_TMP, data_in_int}; case(USE_BRAM_ROM) "TRUE" : skip_execution <= 1'b1; endcase `ifdef USE_RAM_READ_DELAY ram_read_delay <= `USE_RAM_READ_DELAY; end `endif end if(SEL_S2_INSTRUCTION_CPSE) begin if(rd_data_d == rd_data_r) begin if((SEL_S1_INSTRUCTION_CALL && (CORE_CONFIG != "REDUCED" && CORE_CONFIG != "MINIMAL" && CORE_CONFIG != "CLASSIC_8K")) | SEL_S1_INSTRUCTION_LDS_STS | SEL_S1_INSTRUCTION_JMP) begin PC <= PC_PLUS_TWO; case(USE_BRAM_ROM) "TRUE" : skip_execution <= 1'b1; endcase end end else begin case(USE_BRAM_ROM) "TRUE" :; default: PC <= PC; endcase end end if(SEL_S2_INSTRUCTION_SBRC_SBRS) begin if(rd_data_d[tmp_pgm_data[2:0]] == tmp_pgm_data[9]) begin if((SEL_S1_INSTRUCTION_CALL && (CORE_CONFIG != "REDUCED" && CORE_CONFIG != "MINIMAL" && CORE_CONFIG != "CLASSIC_8K")) | SEL_S1_INSTRUCTION_LDS_STS | SEL_S1_INSTRUCTION_JMP) begin PC <= PC_PLUS_TWO; case(USE_BRAM_ROM) "TRUE" : skip_execution <= 1'b1; endcase end end else begin case(USE_BRAM_ROM) "TRUE" :; default: PC <= PC; endcase end end if(SEL_S2_INSTRUCTION_SBIC_SBIS) begin if(io_in_int[tmp_pgm_data[2:0]] == tmp_pgm_data[9]) begin if((SEL_S1_INSTRUCTION_CALL && (CORE_CONFIG != "REDUCED" && CORE_CONFIG != "MINIMAL" && CORE_CONFIG != "CLASSIC_8K")) | SEL_S1_INSTRUCTION_LDS_STS | SEL_S1_INSTRUCTION_JMP) begin PC <= PC_PLUS_TWO; case(USE_BRAM_ROM) "TRUE" : skip_execution <= 1'b1; endcase end end else begin case(USE_BRAM_ROM) "TRUE" :; default: PC <= PC; endcase end end end endcase end else begin case(USE_BRAM_ROM) "TRUE" : skip_execution <= 1'b0; endcase end end end mega_regs #( .PLATFORM(PLATFORM) )regs( .rst(rst), .clk(clk), .rw_addr(rw_addr), .rw_data(rw_data), .rw_16bit(rw_16bit), .write(write_to_reg), .rd_addr_d(rd_addr_d), .rd_data_d(rd_data_d), .rd_16bit_d(rd_16bit_d), .read_d(1'b1), .rd_addr_r(rd_addr_r), .rd_data_r(rd_data_r), .rd_16bit_r(rd_16bit_r), .read_r(1'b1) ); mega_alu #( .CORE_CONFIG(CORE_CONFIG) )alu( .inst(pgm_data_int[7:4]), .in_addr_1(rd_addr_d), .in_addr_2(rd_addr_r), .in_1(alu_in_1), .in_2(alu_in_2), .out(alu_out), .ALU_FLAG_C_IN(ALU_FLAGS[0]), //Carry Flag .ALU_FLAG_Z_IN(ALU_FLAGS[1]), //Zero Flag .ALU_FLAG_N_IN(ALU_FLAGS[2]), //Negative Flag .ALU_FLAG_V_IN(ALU_FLAGS[3]), //Two's complement overflow indicator .ALU_FLAG_S_IN(ALU_FLAGS[4]), //N?V for signed tests .ALU_FLAG_H_IN(ALU_FLAGS[5]), //Half Carry Flag .ALU_FLAG_T_IN(ALU_FLAGS[6]), //Transfer bit used by BLD and BST instructions .ALU_FLAG_I_IN(ALU_FLAGS[7]), //Global Interrupt Enable/Disable Flag .ALU_FLAG_C_OUT(ALU_FLAG_C_OUT), //Carry Flag .ALU_FLAG_Z_OUT(ALU_FLAG_Z_OUT), //Zero Flag .ALU_FLAG_N_OUT(ALU_FLAG_N_OUT), //Negative Flag .ALU_FLAG_V_OUT(ALU_FLAG_V_OUT), //Two's complement overflow indicator .ALU_FLAG_S_OUT(ALU_FLAG_S_OUT), //N?V for signed tests .ALU_FLAG_H_OUT(ALU_FLAG_H_OUT), //Half Carry Flag .ALU_FLAG_T_OUT(ALU_FLAG_T_OUT), //Transfer bit used by BLD and BST instructions .ALU_FLAG_I_OUT(ALU_FLAG_I_OUT), //Global Interrupt Enable/Disable Flag .SEL_INSTRUCTION_MOVW(SEL_S1_INSTRUCTION_MOVW), .SEL_INSTRUCTION_MULS(SEL_S1_INSTRUCTION_MULS), .SEL_INSTRUCTION_MULSU(SEL_S1_INSTRUCTION_MULSU), .SEL_INSTRUCTION_FMUL(SEL_S1_INSTRUCTION_FMUL), .SEL_INSTRUCTION_FMULS(SEL_S1_INSTRUCTION_FMULS), .SEL_INSTRUCTION_FMULSU(SEL_S1_INSTRUCTION_FMULSU), .SEL_INSTRUCTION_CPC(SEL_S1_INSTRUCTION_CPC), .SEL_INSTRUCTION_CP(SEL_S1_INSTRUCTION_CP), .SEL_INSTRUCTION_SBC(SEL_S1_INSTRUCTION_SBC), .SEL_INSTRUCTION_SUB(SEL_S1_INSTRUCTION_SUB), .SEL_INSTRUCTION_ADD(SEL_S1_INSTRUCTION_ADD), .SEL_INSTRUCTION_ADC(SEL_S1_INSTRUCTION_ADC), .SEL_INSTRUCTION_AND(SEL_S1_INSTRUCTION_AND), .SEL_INSTRUCTION_ANDI_CBR(SEL_S1_INSTRUCTION_ANDI_CBR), .SEL_INSTRUCTION_EOR(SEL_S1_INSTRUCTION_EOR), .SEL_INSTRUCTION_OR(SEL_S1_INSTRUCTION_OR), .SEL_INSTRUCTION_ORI_SBR(SEL_S1_INSTRUCTION_ORI_SBR), .SEL_INSTRUCTION_MOV(SEL_S1_INSTRUCTION_MOV), .SEL_INSTRUCTION_CPI(SEL_S1_INSTRUCTION_CPI), .SEL_INSTRUCTION_SUBI(SEL_S1_INSTRUCTION_SUBI), .SEL_INSTRUCTION_SBCI(SEL_S1_INSTRUCTION_SBCI), .SEL_INSTRUCTION_LPM_R_P(SEL_S1_INSTRUCTION_LPM_R_P), .SEL_INSTRUCTION_COM(SEL_S1_INSTRUCTION_COM), .SEL_INSTRUCTION_NEG(SEL_S1_INSTRUCTION_NEG), .SEL_INSTRUCTION_SWAP(SEL_S1_INSTRUCTION_SWAP), .SEL_INSTRUCTION_INC(SEL_S1_INSTRUCTION_INC), .SEL_INSTRUCTION_ASR(SEL_S1_INSTRUCTION_ASR), .SEL_INSTRUCTION_LSR(SEL_S1_INSTRUCTION_LSR), .SEL_INSTRUCTION_ROR(SEL_S1_INSTRUCTION_ROR), .SEL_INSTRUCTION_SEx_CLx(SEL_S1_INSTRUCTION_SEx_CLx), .SEL_INSTRUCTION_DEC(SEL_S1_INSTRUCTION_DEC), .SEL_INSTRUCTION_ADIW(SEL_S1_INSTRUCTION_ADIW), .SEL_INSTRUCTION_SBIW(SEL_S1_INSTRUCTION_SBIW), .SEL_INSTRUCTION_MUL(SEL_S1_INSTRUCTION_MUL) ); watchdog # ( .CNT_WIDTH(WATCHDOG_CNT_WIDTH) )wdt_inst( .rst(rst), .clk(clk), .wdt_clk(clk_wdt), .wdt_rst_in(wdt_rst_out), .wdt_rst_out(core_rst) ); endmodule