Subversion Repositories ngs

Rev

Blame | Last modification | View Log | Download | RSS feed | ?url?

  1. //
  2. // TV80 8-Bit Microprocessor Core
  3. // Based on the VHDL T80 core by Daniel Wallner (jesus@opencores.org)
  4. //
  5. // Copyright (c) 2004 Guy Hutchison (ghutchis@opencores.org)
  6. //
  7. // Permission is hereby granted, free of charge, to any person obtaining a
  8. // copy of this software and associated documentation files (the "Software"),
  9. // to deal in the Software without restriction, including without limitation
  10. // the rights to use, copy, modify, merge, publish, distribute, sublicense,
  11. // and/or sell copies of the Software, and to permit persons to whom the
  12. // Software is furnished to do so, subject to the following conditions:
  13. //
  14. // The above copyright notice and this permission notice shall be included
  15. // in all copies or substantial portions of the Software.
  16. //
  17. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  18. // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  19. // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
  20. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
  21. // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
  22. // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
  23. // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  24.  
  25. module tv80_alu (/*AUTOARG*/
  26.   // Outputs
  27.   Q, F_Out,
  28.   // Inputs
  29.   Arith16, Z16, ALU_Op, IR, ISet, BusA, BusB, F_In
  30.   );
  31.  
  32.   parameter             Mode   = 0;
  33.   parameter             Flag_C = 0;
  34.   parameter             Flag_N = 1;
  35.   parameter             Flag_P = 2;
  36.   parameter             Flag_X = 3;
  37.   parameter             Flag_H = 4;
  38.   parameter             Flag_Y = 5;
  39.   parameter             Flag_Z = 6;
  40.   parameter             Flag_S = 7;
  41.  
  42.   input                 Arith16;
  43.   input                 Z16;
  44.   input [3:0]           ALU_Op ;
  45.   input [5:0]           IR;
  46.   input [1:0]           ISet;
  47.   input [7:0]           BusA;
  48.   input [7:0]           BusB;
  49.   input [7:0]           F_In;
  50.   output [7:0]          Q;
  51.   output [7:0]          F_Out;
  52.   reg [7:0]             Q;
  53.   reg [7:0]             F_Out;
  54.  
  55.   function [4:0] AddSub4;
  56.     input [3:0] A;
  57.     input [3:0] B;
  58.     input Sub;
  59.     input Carry_In;
  60.     begin
  61.       AddSub4 = { 1'b0, A } + { 1'b0, (Sub)?~B:B } + {4'h0,Carry_In};
  62.     end
  63.   endfunction // AddSub4
  64.  
  65.   function [3:0] AddSub3;
  66.     input [2:0] A;
  67.     input [2:0] B;
  68.     input Sub;
  69.     input Carry_In;
  70.     begin
  71.       AddSub3 = { 1'b0, A } + { 1'b0, (Sub)?~B:B } + {3'h0,Carry_In};
  72.     end
  73.   endfunction // AddSub4
  74.  
  75.   function [1:0] AddSub1;
  76.     input A;
  77.     input B;
  78.     input Sub;
  79.     input Carry_In;
  80.     begin
  81.       AddSub1 = { 1'b0, A } + { 1'b0, (Sub)?~B:B } + {1'h0,Carry_In};
  82.     end
  83.   endfunction // AddSub4
  84.  
  85.   // AddSub variables (temporary signals)
  86.   reg UseCarry;
  87.   reg Carry7_v;
  88.   reg OverFlow_v;
  89.   reg HalfCarry_v;
  90.   reg Carry_v;
  91.   reg [7:0] Q_v;
  92.  
  93.   reg [7:0] BitMask;
  94.  
  95.  
  96.   always @(/*AUTOSENSE*/ALU_Op or BusA or BusB or F_In or IR)
  97.     begin
  98.       case (IR[5:3])
  99.         3'b000 : BitMask = 8'b00000001;
  100.         3'b001 : BitMask = 8'b00000010;
  101.         3'b010 : BitMask = 8'b00000100;
  102.         3'b011 : BitMask = 8'b00001000;
  103.         3'b100 : BitMask = 8'b00010000;
  104.         3'b101 : BitMask = 8'b00100000;
  105.         3'b110 : BitMask = 8'b01000000;
  106.         default: BitMask = 8'b10000000;
  107.       endcase // case(IR[5:3])
  108.      
  109.       UseCarry = ~ ALU_Op[2] && ALU_Op[0];
  110.       { HalfCarry_v, Q_v[3:0] } = AddSub4(BusA[3:0], BusB[3:0], ALU_Op[1], ALU_Op[1] ^ (UseCarry && F_In[Flag_C]) );
  111.       { Carry7_v, Q_v[6:4]  } = AddSub3(BusA[6:4], BusB[6:4], ALU_Op[1], HalfCarry_v);
  112.       { Carry_v, Q_v[7] } = AddSub1(BusA[7], BusB[7], ALU_Op[1], Carry7_v);
  113.       OverFlow_v = Carry_v ^ Carry7_v;
  114.     end // always @ *
  115.  
  116.   reg [7:0] Q_t;
  117.   reg [8:0] DAA_Q;
  118.  
  119.   always @ (/*AUTOSENSE*/ALU_Op or Arith16 or BitMask or BusA or BusB
  120.             or Carry_v or F_In or HalfCarry_v or IR or ISet
  121.             or OverFlow_v or Q_v or Z16)
  122.     begin
  123.       Q_t = 8'hxx;
  124.       DAA_Q = {9{1'bx}};
  125.      
  126.       F_Out = F_In;
  127.       case (ALU_Op)
  128.         4'b0000, 4'b0001,  4'b0010, 4'b0011, 4'b0100, 4'b0101, 4'b0110, 4'b0111 :
  129.           begin
  130.             F_Out[Flag_N] = 1'b0;
  131.             F_Out[Flag_C] = 1'b0;
  132.            
  133.             case (ALU_Op[2:0])
  134.              
  135.               3'b000, 3'b001 : // ADD, ADC
  136.                 begin
  137.                   Q_t = Q_v;
  138.                   F_Out[Flag_C] = Carry_v;
  139.                   F_Out[Flag_H] = HalfCarry_v;
  140.                   F_Out[Flag_P] = OverFlow_v;
  141.                 end
  142.              
  143.               3'b010, 3'b011, 3'b111 : // SUB, SBC, CP
  144.                 begin
  145.                   Q_t = Q_v;
  146.                   F_Out[Flag_N] = 1'b1;
  147.                   F_Out[Flag_C] = ~ Carry_v;
  148.                   F_Out[Flag_H] = ~ HalfCarry_v;
  149.                   F_Out[Flag_P] = OverFlow_v;
  150.                 end
  151.              
  152.               3'b100 : // AND
  153.                 begin
  154.                   Q_t[7:0] = BusA & BusB;
  155.                   F_Out[Flag_H] = 1'b1;
  156.                 end
  157.              
  158.               3'b101 : // XOR
  159.                 begin
  160.                   Q_t[7:0] = BusA ^ BusB;
  161.                   F_Out[Flag_H] = 1'b0;
  162.                 end
  163.              
  164.               default : // OR 3'b110
  165.                 begin
  166.                   Q_t[7:0] = BusA | BusB;
  167.                   F_Out[Flag_H] = 1'b0;
  168.                 end
  169.              
  170.             endcase // case(ALU_OP[2:0])
  171.            
  172.             if (ALU_Op[2:0] == 3'b111 )
  173.               begin // CP
  174.                 F_Out[Flag_X] = BusB[3];
  175.                 F_Out[Flag_Y] = BusB[5];
  176.               end
  177.             else
  178.               begin
  179.                 F_Out[Flag_X] = Q_t[3];
  180.                 F_Out[Flag_Y] = Q_t[5];
  181.               end
  182.            
  183.             if (Q_t[7:0] == 8'b00000000 )
  184.               begin
  185.                 F_Out[Flag_Z] = 1'b1;
  186.                 if (Z16 == 1'b1 )
  187.                   begin
  188.                     F_Out[Flag_Z] = F_In[Flag_Z];       // 16 bit ADC,SBC
  189.                   end
  190.               end
  191.             else
  192.               begin
  193.                 F_Out[Flag_Z] = 1'b0;
  194.               end // else: !if(Q_t[7:0] == 8'b00000000 )
  195.            
  196.             F_Out[Flag_S] = Q_t[7];
  197.             case (ALU_Op[2:0])
  198.               3'b000, 3'b001, 3'b010, 3'b011, 3'b111 : // ADD, ADC, SUB, SBC, CP
  199.                 ;
  200.              
  201.               default :
  202.                 F_Out[Flag_P] = ~(^Q_t);                    
  203.             endcase // case(ALU_Op[2:0])
  204.            
  205.             if (Arith16 == 1'b1 )
  206.               begin
  207.                 F_Out[Flag_S] = F_In[Flag_S];
  208.                 F_Out[Flag_Z] = F_In[Flag_Z];
  209.                 F_Out[Flag_P] = F_In[Flag_P];
  210.               end
  211.           end // case: 4'b0000, 4'b0001,  4'b0010, 4'b0011, 4'b0100, 4'b0101, 4'b0110, 4'b0111
  212.        
  213.         4'b1100 :
  214.           begin
  215.             // DAA
  216.             F_Out[Flag_H] = F_In[Flag_H];
  217.             F_Out[Flag_C] = F_In[Flag_C];
  218.             DAA_Q[7:0] = BusA;
  219.             DAA_Q[8] = 1'b0;
  220.             if (F_In[Flag_N] == 1'b0 )
  221.               begin
  222.                 // After addition
  223.                 // Alow > 9 || H == 1
  224.                 if (DAA_Q[3:0] > 9 || F_In[Flag_H] == 1'b1 )
  225.                   begin
  226.                     if ((DAA_Q[3:0] > 9) )
  227.                       begin
  228.                         F_Out[Flag_H] = 1'b1;
  229.                       end
  230.                     else
  231.                       begin
  232.                         F_Out[Flag_H] = 1'b0;
  233.                       end
  234.                     DAA_Q = DAA_Q + 6;
  235.                   end // if (DAA_Q[3:0] > 9 || F_In[Flag_H] == 1'b1 )
  236.                
  237.                 // new Ahigh > 9 || C == 1
  238.                 if (DAA_Q[8:4] > 9 || F_In[Flag_C] == 1'b1 )
  239.                   begin
  240.                     DAA_Q = DAA_Q + 96; // 0x60
  241.                   end
  242.               end
  243.             else
  244.               begin
  245.                 // After subtraction
  246.                 if (DAA_Q[3:0] > 9 || F_In[Flag_H] == 1'b1 )
  247.                   begin
  248.                     if (DAA_Q[3:0] > 5 )
  249.                       begin
  250.                         F_Out[Flag_H] = 1'b0;
  251.                       end
  252.                     DAA_Q[7:0] = DAA_Q[7:0] - 6;
  253.                   end
  254.                 if (BusA > 153 || F_In[Flag_C] == 1'b1 )
  255.                   begin
  256.                     DAA_Q = DAA_Q - 352; // 0x160
  257.                   end
  258.               end // else: !if(F_In[Flag_N] == 1'b0 )
  259.            
  260.             F_Out[Flag_X] = DAA_Q[3];
  261.             F_Out[Flag_Y] = DAA_Q[5];
  262.             F_Out[Flag_C] = F_In[Flag_C] || DAA_Q[8];
  263.             Q_t = DAA_Q[7:0];
  264.            
  265.             if (DAA_Q[7:0] == 8'b00000000 )
  266.               begin
  267.                 F_Out[Flag_Z] = 1'b1;
  268.               end
  269.             else
  270.               begin
  271.                 F_Out[Flag_Z] = 1'b0;
  272.               end
  273.            
  274.             F_Out[Flag_S] = DAA_Q[7];
  275.             F_Out[Flag_P] = ~ (^DAA_Q);
  276.           end // case: 4'b1100
  277.        
  278.         4'b1101, 4'b1110 :
  279.           begin
  280.             // RLD, RRD
  281.             Q_t[7:4] = BusA[7:4];
  282.             if (ALU_Op[0] == 1'b1 )
  283.               begin
  284.                 Q_t[3:0] = BusB[7:4];
  285.               end
  286.             else
  287.               begin
  288.                 Q_t[3:0] = BusB[3:0];
  289.               end
  290.             F_Out[Flag_H] = 1'b0;
  291.             F_Out[Flag_N] = 1'b0;
  292.             F_Out[Flag_X] = Q_t[3];
  293.             F_Out[Flag_Y] = Q_t[5];
  294.             if (Q_t[7:0] == 8'b00000000 )
  295.               begin
  296.                 F_Out[Flag_Z] = 1'b1;
  297.               end
  298.             else
  299.               begin
  300.                 F_Out[Flag_Z] = 1'b0;
  301.               end
  302.             F_Out[Flag_S] = Q_t[7];
  303.             F_Out[Flag_P] = ~(^Q_t);
  304.           end // case: when 4'b1101, 4'b1110
  305.        
  306.         4'b1001 :
  307.           begin
  308.             // BIT
  309.             Q_t[7:0] = BusB & BitMask;
  310.             F_Out[Flag_S] = Q_t[7];
  311.             if (Q_t[7:0] == 8'b00000000 )
  312.               begin
  313.                 F_Out[Flag_Z] = 1'b1;
  314.                 F_Out[Flag_P] = 1'b1;
  315.               end
  316.             else
  317.               begin
  318.                 F_Out[Flag_Z] = 1'b0;
  319.                 F_Out[Flag_P] = 1'b0;
  320.               end
  321.             F_Out[Flag_H] = 1'b1;
  322.             F_Out[Flag_N] = 1'b0;
  323.             F_Out[Flag_X] = 1'b0;
  324.             F_Out[Flag_Y] = 1'b0;
  325.             if (IR[2:0] != 3'b110 )
  326.               begin
  327.                 F_Out[Flag_X] = BusB[3];
  328.                 F_Out[Flag_Y] = BusB[5];
  329.               end
  330.           end // case: when 4'b1001
  331.        
  332.         4'b1010 :
  333.           // SET
  334.           Q_t[7:0] = BusB | BitMask;
  335.        
  336.         4'b1011 :
  337.           // RES
  338.           Q_t[7:0] = BusB & ~ BitMask;
  339.        
  340.         4'b1000 :
  341.           begin
  342.             // ROT
  343.             case (IR[5:3])
  344.               3'b000 : // RLC
  345.                 begin
  346.                   Q_t[7:1] = BusA[6:0];
  347.                   Q_t[0] = BusA[7];
  348.                   F_Out[Flag_C] = BusA[7];
  349.                 end
  350.              
  351.               3'b010 : // RL
  352.                 begin
  353.                   Q_t[7:1] = BusA[6:0];
  354.                   Q_t[0] = F_In[Flag_C];
  355.                   F_Out[Flag_C] = BusA[7];
  356.                 end
  357.              
  358.               3'b001 : // RRC
  359.                 begin
  360.                   Q_t[6:0] = BusA[7:1];
  361.                   Q_t[7] = BusA[0];
  362.                   F_Out[Flag_C] = BusA[0];
  363.                 end
  364.              
  365.               3'b011 : // RR
  366.                 begin                        
  367.                   Q_t[6:0] = BusA[7:1];
  368.                   Q_t[7] = F_In[Flag_C];
  369.                   F_Out[Flag_C] = BusA[0];
  370.                 end
  371.              
  372.               3'b100 : // SLA
  373.                 begin
  374.                   Q_t[7:1] = BusA[6:0];
  375.                   Q_t[0] = 1'b0;
  376.                   F_Out[Flag_C] = BusA[7];
  377.                 end
  378.              
  379.               3'b110 : // SLL (Undocumented) / SWAP
  380.                 begin
  381.                   if (Mode == 3 )
  382.                     begin
  383.                       Q_t[7:4] = BusA[3:0];
  384.                       Q_t[3:0] = BusA[7:4];
  385.                       F_Out[Flag_C] = 1'b0;                            
  386.                     end
  387.                   else
  388.                     begin
  389.                       Q_t[7:1] = BusA[6:0];
  390.                       Q_t[0] = 1'b1;
  391.                       F_Out[Flag_C] = BusA[7];
  392.                     end // else: !if(Mode == 3 )
  393.                 end // case: 3'b110
  394.              
  395.               3'b101 : // SRA
  396.                 begin
  397.                   Q_t[6:0] = BusA[7:1];
  398.                   Q_t[7] = BusA[7];
  399.                   F_Out[Flag_C] = BusA[0];
  400.                 end
  401.              
  402.               default : // SRL
  403.                 begin
  404.                   Q_t[6:0] = BusA[7:1];
  405.                   Q_t[7] = 1'b0;
  406.                   F_Out[Flag_C] = BusA[0];
  407.                 end
  408.             endcase // case(IR[5:3])
  409.            
  410.             F_Out[Flag_H] = 1'b0;
  411.             F_Out[Flag_N] = 1'b0;
  412.             F_Out[Flag_X] = Q_t[3];
  413.             F_Out[Flag_Y] = Q_t[5];
  414.             F_Out[Flag_S] = Q_t[7];
  415.             if (Q_t[7:0] == 8'b00000000 )
  416.               begin
  417.                 F_Out[Flag_Z] = 1'b1;
  418.               end
  419.             else
  420.               begin
  421.                 F_Out[Flag_Z] = 1'b0;
  422.               end
  423.             F_Out[Flag_P] = ~(^Q_t);
  424.  
  425.             if (ISet == 2'b00 )
  426.               begin
  427.                 F_Out[Flag_P] = F_In[Flag_P];
  428.                 F_Out[Flag_S] = F_In[Flag_S];
  429.                 F_Out[Flag_Z] = F_In[Flag_Z];
  430.               end
  431.           end // case: 4'b1000
  432.        
  433.        
  434.         default :
  435.           ;
  436.        
  437.       endcase // case(ALU_Op)
  438.      
  439.       Q = Q_t;
  440.     end // always @ (Arith16, ALU_OP, F_In, BusA, BusB, IR, Q_v, Carry_v, HalfCarry_v, OverFlow_v, BitMask, ISet, Z16)
  441.  
  442. endmodule // T80_ALU
  443.