aboutsummaryrefslogtreecommitdiffstats
path: root/techlibs/intel/cyclonev/cells_arith.v
blob: 89fb4561f83df37177b6f78d5af7513fdc4281af (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
/*
 *  yosys -- Yosys Open SYnthesis Suite
 *
 *  Copyright (C) 2012  Clifford Wolf <clifford@clifford.at>
 *
 *  Permission to use, copy, modify, and/or distribute this software for any
 *  purpose with or without fee is hereby granted, provided that the above
 *  copyright notice and this permission notice appear in all copies.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 *  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 *  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 *  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 *  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 *  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 *  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 *
 */

// NOTE: This is still WIP.
(* techmap_celltype = "$alu" *)
module _80_altera_a10gx_alu (A, B, CI, BI, X, Y, CO);
   parameter A_SIGNED = 0;
   parameter B_SIGNED = 0;
   parameter A_WIDTH  = 1;
   parameter B_WIDTH  = 1;
   parameter Y_WIDTH  = 1;

	input [A_WIDTH-1:0] A;
	input [B_WIDTH-1:0] B;
	output [Y_WIDTH-1:0] X, Y;

	input CI, BI;
	//output [Y_WIDTH-1:0] CO;
        output                 CO;

	wire _TECHMAP_FAIL_ = Y_WIDTH <= 4;

	wire [Y_WIDTH-1:0] A_buf, B_buf;
	\$pos #(.A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(Y_WIDTH)) A_conv (.A(A), .Y(A_buf));
	\$pos #(.A_SIGNED(B_SIGNED), .A_WIDTH(B_WIDTH), .Y_WIDTH(Y_WIDTH)) B_conv (.A(B), .Y(B_buf));

	wire [Y_WIDTH-1:0] AA = A_buf;
	wire [Y_WIDTH-1:0] BB = BI ? ~B_buf : B_buf;
	//wire [Y_WIDTH:0] C = {CO, CI};
        wire [Y_WIDTH+1:0] COx;
        wire [Y_WIDTH+1:0] C = {COx, CI};

	/* Start implementation */
	(* keep *) fiftyfivenm_lcell_comb #(.lut_mask(16'b0000_0000_1010_1010), .sum_lutc_input("cin")) carry_start (.cout(COx[0]), .dataa(C[0]), .datab(1'b1), .datac(1'b1), .datad(1'b1));

	genvar i;
	generate for (i = 0; i < Y_WIDTH; i = i + 1) begin: slice
	  if(i==Y_WIDTH-1) begin
	    (* keep *) fiftyfivenm_lcell_comb #(.lut_mask(16'b1111_0000_1110_0000), .sum_lutc_input("cin")) carry_end (.combout(COx[Y_WIDTH]), .dataa(1'b1), .datab(1'b1), .datac(1'b1), .datad(1'b1), .cin(C[Y_WIDTH]));
            assign CO = COx[Y_WIDTH];
          end
	  else
	    fiftyfivenm_lcell_comb #(.lut_mask(16'b1001_0110_1110_1000), .sum_lutc_input("cin")) arith_cell (.combout(Y[i]), .cout(COx[i+1]), .dataa(AA[i]), .datab(BB[i]), .datac(1'b1), .datad(1'b1), .cin(C[i+1]));
	  end: slice
	endgenerate
	/* End implementation */
	assign X = AA ^ BB;

endmodule
{ uint8_t blo; uint8_t bhi; }; } u; //in effect u.b = blo + (256 * bhi); u.blo = data[ sectionX4 ]; u.bhi = data[ sectionX4 + 1]; m = data[ sectionX4 + 2]; uint8_t secoffset8 = (uint8_t)(offset) / 2; uint16_t mx = m * secoffset8; int16_t y = mx + u.b; if( theta & 0x8000 ) y = -y; return y; } /// Fast 16-bit approximation of sin(x). This approximation never varies more than /// 0.69% from the floating point value you'd get by doing /// /// float s = sin(x) * 32767.0; /// /// @param theta input angle from 0-65535 /// @returns sin of theta, value between -32767 to 32767. LIB8STATIC int16_t sin16_C( uint16_t theta ) { static const uint16_t base[] = { 0, 6393, 12539, 18204, 23170, 27245, 30273, 32137 }; static const uint8_t slope[] = { 49, 48, 44, 38, 31, 23, 14, 4 }; uint16_t offset = (theta & 0x3FFF) >> 3; // 0..2047 if( theta & 0x4000 ) offset = 2047 - offset; uint8_t section = offset / 256; // 0..7 uint16_t b = base[section]; uint8_t m = slope[section]; uint8_t secoffset8 = (uint8_t)(offset) / 2; uint16_t mx = m * secoffset8; int16_t y = mx + b; if( theta & 0x8000 ) y = -y; return y; } /// Fast 16-bit approximation of cos(x). This approximation never varies more than /// 0.69% from the floating point value you'd get by doing /// /// float s = cos(x) * 32767.0; /// /// @param theta input angle from 0-65535 /// @returns sin of theta, value between -32767 to 32767. LIB8STATIC int16_t cos16( uint16_t theta) { return sin16( theta + 16384); } /////////////////////////////////////////////////////////////////////// // sin8 & cos8 // Fast 8-bit approximations of sin(x) & cos(x). // Input angle is an unsigned int from 0-255. // Output is an unsigned int from 0 to 255. // // This approximation can vary to to 2% // from the floating point value you'd get by doing // float s = (sin( x ) * 128.0) + 128; // // Don't use this approximation for calculating the // "real" trigonometric calculations, but it's great // for art projects and LED displays. // // On Arduino/AVR, this approximation is more than // 20X faster than floating point sin(x) and cos(x) #if defined(__AVR__) && !defined(LIB8_ATTINY) #define sin8 sin8_avr #else #define sin8 sin8_C #endif static const uint8_t b_m16_interleave[8] = { 0, 49, 49, 41, 90, 27, 117, 10 }; /// Fast 8-bit approximation of sin(x). This approximation never varies more than /// 2% from the floating point value you'd get by doing /// /// float s = (sin(x) * 128.0) + 128; /// /// @param theta input angle from 0-255 /// @returns sin of theta, value between 0 and 255 LIB8STATIC uint8_t sin8_avr( uint8_t theta) { uint8_t offset = theta; asm volatile( "sbrc %[theta],6 \n\t" "com %[offset] \n\t" : [theta] "+r" (theta), [offset] "+r" (offset) ); offset &= 0x3F; // 0..63 uint8_t secoffset = offset & 0x0F; // 0..15 if( theta & 0x40) secoffset++; uint8_t m16; uint8_t b; uint8_t section = offset >> 4; // 0..3 uint8_t s2 = section * 2; const uint8_t* p = b_m16_interleave; p += s2; b = *p; p++; m16 = *p; uint8_t mx; uint8_t xr1; asm volatile( "mul %[m16],%[secoffset] \n\t" "mov %[mx],r0 \n\t" "mov %[xr1],r1 \n\t" "eor r1, r1 \n\t" "swap %[mx] \n\t" "andi %[mx],0x0F \n\t" "swap %[xr1] \n\t" "andi %[xr1], 0xF0 \n\t" "or %[mx], %[xr1] \n\t" : [mx] "=d" (mx), [xr1] "=d" (xr1) : [m16] "d" (m16), [secoffset] "d" (secoffset) ); int8_t y = mx + b; if( theta & 0x80 ) y = -y; y += 128; return y; } /// Fast 8-bit approximation of sin(x). This approximation never varies more than /// 2% from the floating point value you'd get by doing /// /// float s = (sin(x) * 128.0) + 128; /// /// @param theta input angle from 0-255 /// @returns sin of theta, value between 0 and 255 LIB8STATIC uint8_t sin8_C( uint8_t theta) { uint8_t offset = theta; if( theta & 0x40 ) { offset = (uint8_t)255 - offset; } offset &= 0x3F; // 0..63 uint8_t secoffset = offset & 0x0F; // 0..15 if( theta & 0x40) secoffset++; uint8_t section = offset >> 4; // 0..3 uint8_t s2 = section * 2; const uint8_t* p = b_m16_interleave; p += s2; uint8_t b = *p; p++; uint8_t m16 = *p; uint8_t mx = (m16 * secoffset) >> 4; int8_t y = mx + b; if( theta & 0x80 ) y = -y; y += 128; return y; } /// Fast 8-bit approximation of cos(x). This approximation never varies more than /// 2% from the floating point value you'd get by doing /// /// float s = (cos(x) * 128.0) + 128; /// /// @param theta input angle from 0-255 /// @returns sin of theta, value between 0 and 255 LIB8STATIC uint8_t cos8( uint8_t theta) { return sin8( theta + 64); } /// Fast 16-bit approximation of atan2(x). /// @returns atan2, value between 0 and 255 LIB8STATIC uint8_t atan2_8(int16_t dy, int16_t dx) { if (dy == 0) { if (dx >= 0) return 0; else return 128; } int16_t abs_y = dy > 0 ? dy : -dy; int8_t a; if (dx >= 0) a = 32 - (32 * (dx - abs_y) / (dx + abs_y)); else a = 96 - (32 * (dx + abs_y) / (abs_y - dx)); if (dy < 0) return -a; // negate if in quad III or IV return a; } ///@} #endif