forked from MiSTer-devel/MegaCD_MiSTer
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathascal.vhd
2871 lines (2541 loc) · 96.8 KB
/
ascal.vhd
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
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
--------------------------------------------------------------------------------
-- AVALON SCALER
--------------------------------------------------------------------------------
-- TEMLIB 2018 - 2020
--------------------------------------------------------------------------------
-- This code can be freely distributed and used for any purpose, but, if you
-- find any bug, or want to suggest an enhancement, you ought to send a mail
-- to [email protected].
--------------------------------------------------------------------------------
-- Features
-- - Arbitrary output video format
-- - Autodetect input image size or fixed window
-- - Progressive and interlaced input
-- - Interpolation
-- Upscaling : Nearest, Bilinear, Sharp Bilinear, Bicubic, Polyphase
-- Downscaling : Nearest, Bilinear
-- - Avalon bus interface with 128 or 64 bits DATA
-- - Optional triple buffering
-- - Support for external low lag syntonization
--------------------------------------------
-- Downscaling
-- - Horizontal and vertical up-/down-scaling are independant.
-- - Downscaling, H and/or V, supports only nearest-neighbour and bilinear
-- filtering.
-- - For interlaced video, when the vertical size is lower than a deinterlaced
-- frame size (2x half-frame), the scaler processes only half-frames
-- and upscales (when the output size is between 1x an 2x) or downscales (size
-- below 1x) them.
--------------------------------------------
-- 5 clock domains
-- i_xxx : Input video
-- o_xxx : Output video
-- avl_xxx : Avalon memory bus
-- poly_xxx : Polyphase filters memory
-- pal_xxx : Framebuffer mode 8bpp palette.
--------------------------------------------
-- O_FB_FORMAT : Framebuffer format
-- [2:0] : 011=8bpp(palette) 100=16bpp 101=24bpp 110=32bpp
-- [3] : 0=16bits 565 1=16bits 1555
-- [4] : 0=RGB 1=BGR (for 16/24/32 modes)
-- [5] : TBD
--------------------------------------------
-- Image header. When HEADER = TRUE
-- Header Address = RAMBASE
-- Image Address = RAMBASE + HEADER_SIZE
-- Header (Bytes. Big Endian.)
-- 0 : Type = 1
-- 1 : Pixel format
-- 0 : 16 bits/pixel, RGB : RRRRRGGGGGGBBBBB
-- 1 : 24 bits/pixel, RGB
-- 2 : 32 bits/pixel, RGB0
-- 3:2 : Header size : Offset to start of picture (= N_BURST). 12 bits
-- 5:4 : Attributes
-- b0 ; Interlaced
-- b1 : Field number
-- b2 : Horizontal downscaled
-- b3 : Vertical downscaled
-- b4 : Triple buffered
-- b7-5 : Frame counter
-- 7:6 : Image width. Pixels. 12 bits
-- 9:8 : Image height. Pixels. 12 bits
-- 11:10 : Line length. Bytes.
-- 13:12 : Output width. Pixels. 12 bits
-- 15:14 : Output height. Pixels. 12 bits
--------------------------------------------
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE ieee.numeric_std.ALL;
-- MODE[2:0]
-- 000 : Nearest
-- 001 : Bilinear
-- 010 : Sharp Bilinear
-- 011 : Bicubic
-- 100 : Polyphase
-- 101 : TBD
-- 110 : TBD
-- 111 : TBD
-- MODE[3]
-- 0 : Direct. Single framebuffer.
-- 1 : Triple buffering
-- MODE[4] : TBD
-- MASK : Enable / Disable selected interpoler
-- 0:Nearest 1:Bilinear 2:SharpBilinear 3:Bicubic 4:Polyphase
-- RAMBASE : RAM base address for framebuffer
-- RAMSIZE : RAM allocated for one framebuffer (needs x3 if triple-buffering)
-- Must be a power of two
-- INTER : True=Autodetect interlaced video False=Force progressive scan
-- HEADER : True=Add image properties header
-- PALETTE : Enable palette for framebuffer 8bpp mode
-- PALETTE2 : Enable palette for framebuffer 8bpp mode supplied by core
-- DOWNSCALE : True=Support downscaling False=Downscaling disabled
-- BYTESWAP : Little/Big endian byte swap
-- FRAC : Fractional bits, subpixel resolution
-- OHRES : Max. output horizontal resolution. Must be a power of two.
-- (Used for sizing line buffers)
-- IHRES : Max. input horizontal resolution. Must be a power of two.
-- (Used for sizing line buffers)
-- N_DW : Avalon data bus width. 64 or 128 bits
-- N_AW : Avalon address bus width
-- N_BURST : Burst size in bytes. Power of two.
ENTITY ascal IS
GENERIC (
MASK : unsigned(7 DOWNTO 0) :=x"FF";
RAMBASE : unsigned(31 DOWNTO 0);
RAMSIZE : unsigned(31 DOWNTO 0) := x"0080_0000"; -- =8MB
INTER : boolean := true;
HEADER : boolean := true;
DOWNSCALE : boolean := true;
BYTESWAP : boolean := true;
PALETTE : boolean := true;
PALETTE2 : boolean := true;
ADAPTIVE : boolean := true;
DOWNSCALE_NN : boolean := false;
FRAC : natural RANGE 4 TO 8 :=4;
OHRES : natural RANGE 1 TO 4096 :=2048;
IHRES : natural RANGE 1 TO 2048 :=2048;
N_DW : natural RANGE 64 TO 128 := 128;
N_AW : natural RANGE 8 TO 32 := 32;
N_BURST : natural := 256 -- 256 bytes per burst
);
PORT (
------------------------------------
-- Input video
i_r : IN unsigned(7 DOWNTO 0);
i_g : IN unsigned(7 DOWNTO 0);
i_b : IN unsigned(7 DOWNTO 0);
i_hs : IN std_logic; -- H sync
i_vs : IN std_logic; -- V sync
i_fl : IN std_logic; -- Interlaced field
i_de : IN std_logic; -- Display Enable
i_ce : IN std_logic; -- Clock Enable
i_clk : IN std_logic; -- Input clock
------------------------------------
-- Output video
o_r : OUT unsigned(7 DOWNTO 0);
o_g : OUT unsigned(7 DOWNTO 0);
o_b : OUT unsigned(7 DOWNTO 0);
o_hs : OUT std_logic; -- H sync
o_vs : OUT std_logic; -- V sync
o_de : OUT std_logic; -- Display Enable
o_vbl : OUT std_logic; -- V blank
o_brd : OUT std_logic; -- border enable
o_ce : IN std_logic; -- Clock Enable
o_clk : IN std_logic; -- Output clock
-- Border colour R G B
o_border : IN unsigned(23 DOWNTO 0) := x"000000";
------------------------------------
-- Framebuffer mode
o_fb_ena : IN std_logic :='0'; -- Enable Framebuffer Mode
o_fb_hsize : IN natural RANGE 0 TO 4095 :=0;
o_fb_vsize : IN natural RANGE 0 TO 4095 :=0;
o_fb_format : IN unsigned(5 DOWNTO 0) :="000100";
o_fb_base : IN unsigned(31 DOWNTO 0) :=x"0000_0000";
o_fb_stride : IN unsigned(13 DOWNTO 0) :=(OTHERS =>'0');
-- Framebuffer palette in 8bpp mode
pal1_clk : IN std_logic :='0';
pal1_dw : IN unsigned(47 DOWNTO 0) :=x"000000000000"; -- R1 G1 B1 R0 G0 B0
pal1_dr : OUT unsigned(47 DOWNTO 0) :=x"000000000000";
pal1_a : IN unsigned(6 DOWNTO 0) :="0000000"; -- Colour index/2
pal1_wr : IN std_logic :='0';
pal_n : IN std_logic :='0';
pal2_clk : IN std_logic :='0';
pal2_dw : IN unsigned(23 DOWNTO 0) :=x"000000"; -- R G B
pal2_dr : OUT unsigned(23 DOWNTO 0) :=x"000000";
pal2_a : IN unsigned(7 DOWNTO 0) :="00000000"; -- Colour index
pal2_wr : IN std_logic :='0';
------------------------------------
-- Low lag PLL tuning
o_lltune : OUT unsigned(15 DOWNTO 0);
------------------------------------
-- Input video parameters
iauto : IN std_logic :='1'; -- 1=Autodetect image size 0=Choose window
himin : IN natural RANGE 0 TO 4095 :=0; -- MIN < MAX, MIN >=0, MAX < DISP
himax : IN natural RANGE 0 TO 4095 :=0;
vimin : IN natural RANGE 0 TO 4095 :=0;
vimax : IN natural RANGE 0 TO 4095 :=0;
-- Detected input image size
i_hdmax : OUT natural RANGE 0 TO 4095;
i_vdmax : OUT natural RANGE 0 TO 4095;
-- Output video parameters
run : IN std_logic :='1'; -- 1=Enable output image. 0=No image
freeze : IN std_logic :='0'; -- 1=Disable framebuffer writes
mode : IN unsigned(4 DOWNTO 0);
-- SYNC |_________________________/"""""""""\_______|
-- DE |""""""""""""""""""\________________________|
-- RGB | <#IMAGE#> ^HDISP |
-- ^HMIN ^HMAX ^HSSTART ^HSEND ^HTOTAL
htotal : IN natural RANGE 0 TO 4095;
hsstart : IN natural RANGE 0 TO 4095;
hsend : IN natural RANGE 0 TO 4095;
hdisp : IN natural RANGE 0 TO 4095;
hmin : IN natural RANGE 0 TO 4095;
hmax : IN natural RANGE 0 TO 4095; -- 0 <= hmin < hmax < hdisp
vtotal : IN natural RANGE 0 TO 4095;
vsstart : IN natural RANGE 0 TO 4095;
vsend : IN natural RANGE 0 TO 4095;
vdisp : IN natural RANGE 0 TO 4095;
vmin : IN natural RANGE 0 TO 4095;
vmax : IN natural RANGE 0 TO 4095; -- 0 <= vmin < vmax < vdisp
-- Scaler format. 00=16bpp 565, 01=24bpp 10=32bpp
format : IN unsigned(1 DOWNTO 0) :="01";
------------------------------------
-- Polyphase filter coefficients
-- Order :
-- [Horizontal] [Vertical] [Horizontal2] [Vertical2]
-- [0]...[2**FRAC-1]
-- [-1][0][1][2]
poly_clk : IN std_logic;
poly_dw : IN unsigned(9 DOWNTO 0);
poly_a : IN unsigned(FRAC+3 DOWNTO 0);
poly_wr : IN std_logic;
------------------------------------
-- Avalon
avl_clk : IN std_logic; -- Avalon clock
avl_waitrequest : IN std_logic;
avl_readdata : IN std_logic_vector(N_DW-1 DOWNTO 0);
avl_readdatavalid : IN std_logic;
avl_burstcount : OUT std_logic_vector(7 DOWNTO 0);
avl_writedata : OUT std_logic_vector(N_DW-1 DOWNTO 0);
avl_address : OUT std_logic_vector(N_AW-1 DOWNTO 0);
avl_write : OUT std_logic;
avl_read : OUT std_logic;
avl_byteenable : OUT std_logic_vector(N_DW/8-1 DOWNTO 0);
------------------------------------
reset_na : IN std_logic
);
BEGIN
ASSERT N_DW=64 OR N_DW=128 REPORT "DW" SEVERITY failure;
END ENTITY ascal;
--##############################################################################
ARCHITECTURE rtl OF ascal IS
CONSTANT MASK_NEAREST : natural :=0;
CONSTANT MASK_BILINEAR : natural :=1;
CONSTANT MASK_SHARP_BILINEAR : natural :=2;
CONSTANT MASK_BICUBIC : natural :=3;
CONSTANT MASK_POLY : natural :=4;
----------------------------------------------------------
FUNCTION ilog2 (CONSTANT v : natural) RETURN natural IS
VARIABLE r : natural := 1;
VARIABLE n : natural := 0;
BEGIN
WHILE v>r LOOP
n:=n+1;
r:=r*2;
END LOOP;
RETURN n;
END FUNCTION ilog2;
FUNCTION to_std_logic (a : boolean) RETURN std_logic IS
BEGIN
IF a THEN RETURN '1';
ELSE RETURN '0';
END IF;
END FUNCTION to_std_logic;
----------------------------------------------------------
CONSTANT NB_BURST : natural :=ilog2(N_BURST);
CONSTANT NB_LA : natural :=ilog2(N_DW/8); -- Low address bits
CONSTANT BLEN : natural :=N_BURST / N_DW * 8; -- Burst length
----------------------------------------------------------
TYPE arr_dw IS ARRAY (natural RANGE <>) OF unsigned(N_DW-1 DOWNTO 0);
TYPE type_pix IS RECORD
r,g,b : unsigned(7 DOWNTO 0); -- 0.8
END RECORD;
TYPE arr_pix IS ARRAY (natural RANGE <>) OF type_pix;
TYPE arr_pixq IS ARRAY(natural RANGE <>) OF arr_pix(0 TO 3);
ATTRIBUTE ramstyle : string;
SUBTYPE uint12 IS natural RANGE 0 TO 4095;
SUBTYPE uint13 IS natural RANGE 0 TO 8191;
TYPE arr_uv48 IS ARRAY (natural RANGE <>) OF unsigned(47 DOWNTO 0);
TYPE arr_uv24 IS ARRAY (natural RANGE <>) OF unsigned(23 DOWNTO 0);
TYPE arr_uv40 IS ARRAY (natural RANGE <>) OF unsigned(39 DOWNTO 0);
TYPE arr_int9 IS ARRAY (natural RANGE <>) OF integer RANGE -256 TO 255;
TYPE arr_uint12 IS ARRAY (natural RANGE <>) OF uint12;
TYPE arr_frac IS ARRAY (natural RANGE <>) OF unsigned(11 DOWNTO 0);
TYPE arr_div IS ARRAY (natural RANGE <>) OF unsigned(20 DOWNTO 0);
----------------------------------------------------------
-- Input image
SIGNAL i_pvs,i_pfl,i_pde,i_pce : std_logic;
SIGNAL i_ppix : type_pix;
SIGNAL i_freeze : std_logic;
SIGNAL i_count : unsigned(2 DOWNTO 0);
SIGNAL i_hsize,i_hmin,i_hmax,i_hcpt : uint12;
SIGNAL i_hrsize,i_vrsize : uint12;
SIGNAL i_himax,i_vimax : uint12;
SIGNAL i_vsize,i_vmaxmin,i_vmin,i_vmax,i_vcpt : uint12;
SIGNAL i_iauto : std_logic;
SIGNAL i_mode : unsigned(4 DOWNTO 0);
SIGNAL i_format : unsigned(1 DOWNTO 0);
SIGNAL i_ven,i_sof : std_logic;
SIGNAL i_wr : std_logic;
SIGNAL i_divstart,i_divrun : std_logic;
SIGNAL i_de_pre,i_vs_pre,i_fl_pre : std_logic;
SIGNAL i_de_delay : natural RANGE 0 TO 31;
SIGNAL i_intercnt : natural RANGE 0 TO 3;
SIGNAL i_inter,i_half,i_flm : std_logic;
SIGNAL i_write,i_wreq,i_alt,i_line,i_wline,i_wline_mem : std_logic;
SIGNAL i_walt,i_walt_mem,i_wreq_mem : std_logic;
SIGNAL i_wdelay : natural RANGE 0 TO 7;
SIGNAL i_push,i_pushend,i_pushend2 : std_logic;
SIGNAL i_eol : std_logic;
SIGNAL i_pushhead,i_pushhead2,i_pushhead3 : std_logic;
SIGNAL i_hburst,i_hbcpt : natural RANGE 0 TO 31;
SIGNAL i_shift : unsigned(0 TO 119) := (OTHERS =>'0');
SIGNAL i_head : unsigned(127 DOWNTO 0);
SIGNAL i_acpt : natural RANGE 0 TO 15;
SIGNAL i_dpram : arr_dw(0 TO BLEN*2-1);
ATTRIBUTE ramstyle OF i_dpram : SIGNAL IS "no_rw_check";
SIGNAL i_endframe0,i_endframe1,i_vss : std_logic;
SIGNAL i_wad : natural RANGE 0 TO BLEN*2-1;
SIGNAL i_dw : unsigned(N_DW-1 DOWNTO 0);
SIGNAL i_adrs,i_adrsi,i_wadrs,i_wadrs_mem : unsigned(31 DOWNTO 0);
SIGNAL i_reset_na : std_logic;
SIGNAL i_hnp,i_vnp : std_logic;
SIGNAL i_mem : arr_pix(0 TO IHRES-1); -- Downscale line buffer
ATTRIBUTE ramstyle OF i_mem : SIGNAL IS "no_rw_check";
SIGNAL i_ohsize,i_ovsize : uint12;
SIGNAL i_vdivi : unsigned(12 DOWNTO 0);
SIGNAL i_vdivr : unsigned(24 DOWNTO 0);
SIGNAL i_div : unsigned(16 DOWNTO 0);
SIGNAL i_dir : unsigned(11 DOWNTO 0);
SIGNAL i_h_frac,i_v_frac : unsigned(11 DOWNTO 0);
SIGNAL i_hacc,i_vacc : uint13;
SIGNAL i_hdown,i_vdown : std_logic;
SIGNAL i_divcpt : natural RANGE 0 TO 36;
SIGNAL i_lwad,i_lrad : natural RANGE 0 TO OHRES-1;
SIGNAL i_lwr,i_bil : std_logic;
SIGNAL i_ldw,i_ldrm : type_pix;
SIGNAL i_hpixp,i_hpix0,i_hpix1,i_hpix2,i_hpix3,i_hpix4 : type_pix;
SIGNAL i_hpix,i_pix : type_pix;
SIGNAL i_hnp1,i_hnp2,i_hnp3,i_hnp4 : std_logic;
SIGNAL i_ven1,i_ven2,i_ven3,i_ven4,i_ven5,i_ven6 : std_logic;
----------------------------------------------------------
-- Avalon
TYPE type_avl_state IS (sIDLE,sWRITE,sREAD);
SIGNAL avl_state : type_avl_state;
SIGNAL avl_write_i,avl_write_sync,avl_write_sync2 : std_logic;
SIGNAL avl_read_i,avl_read_sync,avl_read_sync2 : std_logic;
SIGNAL avl_read_pulse,avl_write_pulse : std_logic;
SIGNAL avl_read_sr,avl_write_sr,avl_read_clr,avl_write_clr : std_logic;
SIGNAL avl_rad,avl_rad_c,avl_wad : natural RANGE 0 TO 2*BLEN-1;
SIGNAL avl_walt,avl_wline,avl_rline : std_logic;
SIGNAL avl_dw,avl_dr : unsigned(N_DW-1 DOWNTO 0);
SIGNAL avl_wr : std_logic;
SIGNAL avl_readdataack,avl_readack : std_logic;
SIGNAL avl_radrs,avl_wadrs : unsigned(31 DOWNTO 0);
SIGNAL avl_i_offset0,avl_o_offset0 : unsigned(31 DOWNTO 0);
SIGNAL avl_i_offset1,avl_o_offset1 : unsigned(31 DOWNTO 0);
SIGNAL avl_reset_na : std_logic;
SIGNAL avl_o_vs_sync,avl_o_vs : std_logic;
SIGNAL avl_fb_ena : std_logic;
FUNCTION buf_next(a,b : natural RANGE 0 TO 2; freeze : std_logic := '0') RETURN natural IS
BEGIN
IF (freeze='1') THEN RETURN a; END IF;
IF (a=0 AND b=1) OR (a=1 AND b=0) THEN RETURN 2; END IF;
IF (a=1 AND b=2) OR (a=2 AND b=1) THEN RETURN 0; END IF;
RETURN 1;
END FUNCTION;
FUNCTION buf_offset(b : natural RANGE 0 TO 2;
base : unsigned(31 DOWNTO 0);
size : unsigned(31 DOWNTO 0)) RETURN unsigned IS
BEGIN
IF b=1 THEN RETURN base+size; END IF;
IF b=2 THEN RETURN base+(size(30 DOWNTO 0) & '0'); END IF;
RETURN base;
END FUNCTION;
----------------------------------------------------------
-- Output
SIGNAL o_run : std_logic;
SIGNAL o_freeze : std_logic;
SIGNAL o_mode,o_hmode,o_vmode : unsigned(4 DOWNTO 0);
SIGNAL o_format : unsigned(5 DOWNTO 0);
SIGNAL o_fb_pal_dr : unsigned(23 DOWNTO 0);
SIGNAL o_fb_pal_dr2 : unsigned(23 DOWNTO 0);
SIGNAL o_fb_pal_dr_x2 : unsigned(47 DOWNTO 0);
SIGNAL pal_idx: unsigned(7 DOWNTO 0);
SIGNAL pal_idx_lsb: std_logic;
SIGNAL pal1_mem : arr_uv48(0 TO 127);
SIGNAL pal2_mem : arr_uv24(0 TO 255);
ATTRIBUTE ramstyle of pal1_mem : signal is "no_rw_check";
ATTRIBUTE ramstyle of pal2_mem : signal is "no_rw_check";
SIGNAL o_htotal,o_hsstart,o_hsend : uint12;
SIGNAL o_hmin,o_hmax,o_hdisp,o_v_hmin_adj : uint12;
SIGNAL o_hsize,o_vsize : uint12;
SIGNAL o_vtotal,o_vsstart,o_vsend : uint12;
SIGNAL o_vmin,o_vmax,o_vdisp : uint12;
SIGNAL o_divcpt : natural RANGE 0 TO 36;
SIGNAL o_iendframe0,o_iendframe02,o_iendframe1,o_iendframe12 : std_logic;
SIGNAL o_bufup0,o_bufup1,o_inter : std_logic;
SIGNAL o_ibuf0,o_ibuf1,o_obuf0,o_obuf1 : natural RANGE 0 TO 2;
TYPE enum_o_state IS (sDISP,sHSYNC,sREAD,sWAITREAD);
SIGNAL o_state : enum_o_state;
TYPE enum_o_copy IS (sWAIT,sSHIFT,sCOPY);
SIGNAL o_copy : enum_o_copy;
SIGNAL o_pshift : natural RANGE 0 TO 15;
SIGNAL o_readack,o_readack_sync,o_readack_sync2 : std_logic;
SIGNAL o_readdataack,o_readdataack_sync,o_readdataack_sync2 : std_logic;
SIGNAL o_copyv : unsigned(0 TO 12);
SIGNAL o_adrs : unsigned(31 DOWNTO 0); -- Avalon address
SIGNAL o_adrs_pre : natural RANGE 0 TO 2**24-1;
SIGNAL o_stride : unsigned(13 DOWNTO 0);
SIGNAL o_adrsa,o_adrsb,o_rline : std_logic;
SIGNAL o_ad,o_ad1,o_ad2,o_ad3 : natural RANGE 0 TO 2*BLEN-1;
SIGNAL o_adturn : std_logic;
SIGNAL o_dr : unsigned(N_DW-1 DOWNTO 0);
SIGNAL o_shift : unsigned(0 TO N_DW+15);
SIGNAL o_sh,o_sh1,o_sh2,o_sh3,o_sh4 : std_logic;
SIGNAL o_reset_na : std_logic;
SIGNAL o_dpram : arr_dw(0 TO BLEN*2-1);
ATTRIBUTE ramstyle OF o_dpram : SIGNAL IS "no_rw_check";
SIGNAL o_line0,o_line1,o_line2,o_line3 : arr_pix(0 TO OHRES-1);
ATTRIBUTE ramstyle OF o_line0 : SIGNAL IS "no_rw_check";
ATTRIBUTE ramstyle OF o_line1 : SIGNAL IS "no_rw_check";
ATTRIBUTE ramstyle OF o_line2 : SIGNAL IS "no_rw_check";
ATTRIBUTE ramstyle OF o_line3 : SIGNAL IS "no_rw_check";
SIGNAL o_wadl,o_radl0,o_radl1,o_radl2,o_radl3 : natural RANGE 0 TO OHRES-1;
SIGNAL o_ldw,o_ldr0,o_ldr1,o_ldr2,o_ldr3 : type_pix;
SIGNAL o_wr : unsigned(3 DOWNTO 0);
SIGNAL o_hcpt,o_vcpt,o_vcpt_pre,o_vcpt_pre2,o_vcpt_pre3 : uint12;
SIGNAL o_ihsize,o_ihsizem,o_ivsize : uint12;
SIGNAL o_ihsize_temp, o_ihsize_temp2 : natural RANGE 0 TO 32767;
SIGNAL o_vfrac : unsigned(11 DOWNTO 0);
SIGNAL o_hfrac : arr_frac(0 TO 8);
ATTRIBUTE ramstyle OF o_hfrac : SIGNAL IS "logic"; -- avoid blockram shift register
SIGNAL o_hacc,o_hacc_ini,o_hacc_next,o_vacc,o_vacc_next,o_vacc_ini : natural RANGE 0 TO 4*OHRES-1;
SIGNAL o_hsv,o_vsv,o_dev,o_pev,o_end : unsigned(0 TO 9);
SIGNAL o_hsp,o_vss : std_logic;
SIGNAL o_vcarrym,o_prim : boolean;
SIGNAL o_read,o_read_pre : std_logic;
SIGNAL o_readlev,o_copylev : natural RANGE 0 TO 2;
SIGNAL o_hburst,o_hbcpt : natural RANGE 0 TO 31;
SIGNAL o_fload : natural RANGE 0 TO 3;
SIGNAL o_acpt,o_acpt1,o_acpt2,o_acpt3,o_acpt4 : natural RANGE 0 TO 15; -- Alternance pixels FIFO
SIGNAL o_dshi : natural RANGE 0 TO 3;
SIGNAL o_first,o_last,o_last1,o_last2 : std_logic;
SIGNAL o_lastt1,o_lastt2,o_lastt3,o_lastt4 : std_logic;
SIGNAL o_alt,o_altx : unsigned(3 DOWNTO 0);
SIGNAL o_hdown,o_vdown : std_logic;
SIGNAL o_primv,o_lastv,o_bibv : unsigned(0 TO 2);
TYPE arr_uint4 IS ARRAY (natural RANGE <>) OF natural RANGE 0 TO 15;
SIGNAL o_off : arr_uint4(0 TO 2);
SIGNAL o_bibu : std_logic :='0';
SIGNAL o_dcptv : arr_uint12(1 TO 12);
SIGNAL o_dcpt : uint12;
SIGNAL o_hpixs,o_hpix0,o_hpix1,o_hpix2,o_hpix3 : type_pix;
SIGNAL o_hpixq : arr_pixq(2 TO 6);
ATTRIBUTE ramstyle OF o_hpixq : SIGNAL IS "logic"; -- avoid blockram shift register
SIGNAL o_vpixq : arr_pix(0 TO 3);
SIGNAL o_vpix_outer : arr_pix(0 TO 2);
SIGNAL o_vpix_inner : arr_pix(0 TO 5);
-- ATTRIBUTE ramstyle OF o_hpixq : SIGNAL IS "logic";
SIGNAL o_vpe : std_logic;
SIGNAL o_div : arr_div(0 TO 2); --uint12;
SIGNAL o_dir : arr_frac(0 TO 2);
ATTRIBUTE ramstyle OF o_div, o_dir : SIGNAL IS "logic"; -- avoid blockram shift register
SIGNAL o_vdivi : unsigned(12 DOWNTO 0);
SIGNAL o_vdivr : unsigned(24 DOWNTO 0);
SIGNAL o_divstart : std_logic;
SIGNAL o_divrun : std_logic;
SIGNAL o_hacpt,o_vacpt : unsigned(11 DOWNTO 0);
SIGNAL o_vacptl : unsigned(1 DOWNTO 0);
-----------------------------------------------------------------------------
FUNCTION shift_ishift(shift : unsigned(0 TO 119);
pix : type_pix;
format : unsigned(1 DOWNTO 0)) RETURN unsigned IS
BEGIN
CASE format IS
WHEN "01" => -- 24bpp
RETURN shift(24 TO 119) & pix.r & pix.g & pix.b;
WHEN "10" => -- 32bpp
RETURN shift(32 TO 119) & pix.r & pix.g & pix.b & x"00";
WHEN OTHERS => -- 16bpp 565
RETURN shift(16 TO 119) &
pix.g(4 DOWNTO 2) & pix.r(7 DOWNTO 3) &
pix.b(7 DOWNTO 3) & pix.g(7 DOWNTO 5);
END CASE;
END FUNCTION;
FUNCTION shift_ipack(i_dw : unsigned(N_DW-1 DOWNTO 0);
acpt : natural RANGE 0 TO 15;
shift : unsigned(0 TO 119);
pix : type_pix;
format : unsigned(1 DOWNTO 0)) RETURN unsigned IS
VARIABLE dw : unsigned(N_DW-1 DOWNTO 0);
BEGIN
dw:=i_dw;
CASE format IS
WHEN "01" => -- 24bpp
IF N_DW=128 THEN
IF acpt=5 THEN dw:=shift(0 TO 119) & pix.r;
ELSIF acpt=10 THEN dw:=shift(8 TO 119) & pix.r & pix.g;
ELSIF acpt=15 THEN dw:=shift(16 TO 119) & pix.r & pix.g & pix.b;
END IF;
ELSE -- N_DW=64
IF (acpt MOD 8)=2 THEN dw:=shift(72 TO 119) & pix.r & pix.g;
ELSIF (acpt MOD 8)=5 THEN dw:=shift(64 TO 119) & pix.r;
ELSIF (acpt MOD 8)=7 THEN dw:=shift(80 TO 119) & pix.r & pix.g & pix.b;
END IF;
END IF;
WHEN "10" => -- 32bpp
IF (N_DW=128 AND (acpt MOD 4)=3) OR (N_DW=64 AND (acpt MOD 8)=7) THEN
dw:=shift(128-N_DW+24 TO 119) & pix.r & pix.g & pix.b & x"00";
END IF;
WHEN OTHERS => -- 16bpp 565
IF (N_DW=128 AND (acpt MOD 8)=7) OR (N_DW=64 AND (acpt MOD 4)=3) THEN
dw:=shift(128-N_DW+8 TO 119) & pix.g(4 DOWNTO 2) & pix.r(7 DOWNTO 3) &
pix.b(7 DOWNTO 3) & pix.g(7 DOWNTO 5);
END IF;
END CASE;
RETURN dw;
END FUNCTION;
FUNCTION shift_inext (acpt : natural RANGE 0 TO 15;
format : unsigned(1 DOWNTO 0)) RETURN boolean IS
BEGIN
CASE format IS
WHEN "01" => -- 24bpp
RETURN (N_DW=128 AND (acpt=5 OR acpt=10 OR acpt=15)) OR
(N_DW=64 AND ((acpt MOD 8)=2 OR (acpt MOD 8)=5 OR (acpt MOD 8)=7));
WHEN "10" => -- 32bpp
RETURN (N_DW=128 AND ((acpt MOD 4)=3)) OR
(N_DW=64 AND ((acpt MOD 2)=1));
WHEN OTHERS => -- 16bpp
RETURN (N_DW=128 AND ((acpt MOD 8)=7)) OR
(N_DW=64 AND ((acpt MOD 4)=3));
END CASE;
END FUNCTION;
FUNCTION shift_opack(acpt : natural RANGE 0 TO 15;
shift : unsigned(0 TO N_DW+15);
dr : unsigned(N_DW-1 DOWNTO 0);
format : unsigned(5 DOWNTO 0)) RETURN unsigned IS
VARIABLE shift_v : unsigned(0 TO N_DW+15);
BEGIN
CASE format(2 DOWNTO 0) IS
WHEN "011" => -- 8bpp
IF (N_DW=128 AND acpt=0) OR (N_DW=64 AND (acpt MOD 8)=0) THEN
shift_v:=dr & dr(15 DOWNTO 0);
ELSE
shift_v:=shift(8 TO N_DW+15) & dr(7 DOWNTO 0);
END IF;
WHEN "100" => -- 16bpp
IF (N_DW=128 AND (acpt MOD 8)=0) OR (N_DW=64 AND (acpt MOD 4)=0) THEN
shift_v:=dr & dr(15 DOWNTO 0);
ELSE
shift_v:=shift(16 TO N_DW+15) & dr(15 DOWNTO 0);
END IF;
WHEN "101" => -- 24bpp
IF N_DW=128 THEN
IF acpt=0 THEN
shift_v:=dr & dr(15 DOWNTO 0);
ELSIF acpt=5 THEN
shift_v:=shift(24 TO 31) & dr & dr(7 DOWNTO 0);
ELSIF acpt=10 THEN
shift_v:=shift(24 TO 39) & dr;
ELSE
shift_v:=shift(24 TO N_DW+15) & dr(23 DOWNTO 0);
END IF;
ELSE -- N_DW=64
IF (acpt MOD 8)=0 THEN
shift_v:=dr & dr(15 DOWNTO 0);
ELSIF (acpt MOD 8)=2 THEN
shift_v:=shift(24 TO 39) & dr;
ELSIF (acpt MOD 8)=5 THEN
shift_v:=shift(24 TO 31) & dr & dr(7 DOWNTO 0);
ELSE
shift_v:=shift(24 TO N_DW+15) & dr(23 DOWNTO 0);
END IF;
END IF;
WHEN OTHERS => -- 32bpp
IF (N_DW=128 AND (acpt MOD 4)=0) OR (N_DW=64 AND (acpt MOD 2)=0) THEN
shift_v:=dr & dr(15 DOWNTO 0);
ELSE
shift_v:=shift(32 TO N_DW+15) & dr(31 DOWNTO 0);
END IF;
END CASE;
RETURN shift_v;
END FUNCTION;
FUNCTION shift_onext (acpt : natural RANGE 0 TO 15;
format : unsigned(5 DOWNTO 0)) RETURN boolean IS
BEGIN
CASE format(2 DOWNTO 0) IS
WHEN "011" => -- 8bpp
RETURN (N_DW=128 AND acpt=0) OR
(N_DW=64 AND ((acpt MOD 8)=0));
WHEN "100" => -- 16bpp
RETURN (N_DW=128 AND ((acpt MOD 8)=0)) OR
(N_DW=64 AND ((acpt MOD 4)=0));
WHEN "101" => -- 24bpp
RETURN (N_DW=128 AND (acpt=0 OR acpt=5 OR acpt=10)) OR
(N_DW=64 AND ((acpt MOD 8)=0 OR (acpt MOD 8)=2 OR (acpt MOD 8)=5));
WHEN OTHERS => -- 32bpp
RETURN (N_DW=128 AND ((acpt MOD 4)=0)) OR
(N_DW=64 AND ((acpt MOD 2)=0));
END CASE;
END FUNCTION;
FUNCTION shift_opix (shift : unsigned(0 TO N_DW+15);
format : unsigned(5 DOWNTO 0)) RETURN type_pix IS
BEGIN
CASE format(3 DOWNTO 0) IS
WHEN "0100" => -- 16bpp 565
RETURN (b=>shift(8 TO 12) & shift(8 TO 10),
g=>shift(13 TO 15) & shift(0 TO 2) & shift(13 TO 14),
r=>shift(3 TO 7) & shift(3 TO 5));
WHEN "1100" => -- 16bpp 1555
RETURN (b=>shift(9 TO 13) & shift(9 TO 11),
g=>shift(14 TO 15) & shift(0 TO 2) & shift(14 TO 15) & shift(0),
r=>shift(3 TO 7) & shift(3 TO 5));
WHEN "0101" | "0110" => -- 24bpp / 32bpp
RETURN (r=>shift(0 TO 7),g=>shift(8 TO 15),b=>shift(16 TO 23));
WHEN OTHERS =>
RETURN (r=>shift(0 TO 7),g=>shift(8 TO 15),b=>shift(16 TO 23));
END CASE;
END FUNCTION;
FUNCTION pixoffset(adrs : unsigned(31 DOWNTO 0);
format : unsigned (5 DOWNTO 0)) RETURN natural IS
BEGIN
CASE format(2 DOWNTO 0) IS
WHEN "011" => -- 8bbp
RETURN to_integer(adrs(NB_LA-1 DOWNTO 0));
WHEN "100" => -- 16bpp 565
RETURN to_integer(adrs(NB_LA-1 DOWNTO 1));
WHEN OTHERS => -- 32bpp
RETURN to_integer(adrs(NB_LA-1 DOWNTO 2));
END CASE;
END FUNCTION;
FUNCTION swap(d : unsigned(N_DW-1 DOWNTO 0)) RETURN unsigned IS
VARIABLE e : unsigned(N_DW-1 DOWNTO 0);
BEGIN
IF BYTESWAP THEN
FOR i IN 0 TO N_DW/8-1 LOOP
e(i*8+7 DOWNTO i*8):=d(N_DW-i*8-1 DOWNTO N_DW-i*8-8);
END LOOP;
RETURN e;
ELSE
RETURN d;
END IF;
END FUNCTION swap;
-----------------------------------------------------------------------------
FUNCTION altx (a : unsigned(1 DOWNTO 0)) RETURN unsigned IS
BEGIN
CASE a IS
WHEN "00" => RETURN "0001";
WHEN "01" => RETURN "0010";
WHEN "10" => RETURN "0100";
WHEN OTHERS => RETURN "1000";
END CASE;
END FUNCTION;
-----------------------------------------------------------------------------
FUNCTION bound(a : unsigned;
s : natural) RETURN unsigned IS
BEGIN
IF a(a'left)='1' THEN
RETURN x"00";
ELSIF a(a'left DOWNTO s)/=0 THEN
RETURN x"FF";
ELSE
RETURN a(s-1 DOWNTO s-8);
END IF;
END FUNCTION bound;
-----------------------------------------------------------------------------
-- Nearest
FUNCTION near_frac(f : unsigned) RETURN unsigned IS
VARIABLE x : unsigned(FRAC-1 DOWNTO 0);
BEGIN
x:=(OTHERS =>f(f'left));
RETURN x;
END FUNCTION;
SIGNAL o_h_near_frac,o_v_near_frac : unsigned(FRAC-1 DOWNTO 0);
SIGNAL o_h_bil_frac,o_v_bil_frac : unsigned(FRAC-1 DOWNTO 0);
SIGNAL o_h_bil_pix,o_v_bil_pix : type_pix;
-----------------------------------------------------------------------------
-- Nearest + Bilinear + Sharp Bilinear
FUNCTION bil_frac(f : unsigned) RETURN unsigned IS
BEGIN
RETURN f(f'left DOWNTO f'left+1-FRAC);
END FUNCTION;
TYPE type_bil_t IS RECORD
r,g,b : unsigned(8+FRAC DOWNTO 0);
END RECORD;
FUNCTION bil_calc(f : unsigned(FRAC-1 DOWNTO 0);
p : arr_pix(0 TO 3)) RETURN type_bil_t IS
VARIABLE fp,fn : unsigned(FRAC DOWNTO 0);
VARIABLE u : unsigned(8+FRAC DOWNTO 0);
VARIABLE x : type_bil_t;
CONSTANT Z : unsigned(FRAC-1 DOWNTO 0):=(OTHERS =>'0');
BEGIN
fp:=('0' & f) + (Z & f(FRAC-1));
fn:=('1' & Z) - fp;
u:=p(2).r * fp + p(1).r * fn;
x.r:=u;
u:=p(2).g * fp + p(1).g * fn;
x.g:=u;
u:=p(2).b * fp + p(1).b * fn;
x.b:=u;
RETURN x;
END FUNCTION;
FUNCTION near_calc(f : unsigned(FRAC-1 DOWNTO 0);
p : arr_pix(0 TO 3)) RETURN type_bil_t IS
VARIABLE fp,fn : unsigned(FRAC DOWNTO 0);
VARIABLE u : unsigned(8+FRAC DOWNTO 0);
VARIABLE x : type_bil_t;
CONSTANT Z : unsigned(FRAC-1 DOWNTO 0):=(OTHERS =>'0');
BEGIN
IF f(FRAC-1)='0' THEN
x.r := '0' & p(1).r & Z;
x.g := '0' & p(1).g & Z;
x.b := '0' & p(1).b & Z;
ELSE
x.r := '0' & p(2).r & Z;
x.g := '0' & p(2).g & Z;
x.b := '0' & p(2).b & Z;
END IF;
RETURN x;
END FUNCTION;
SIGNAL o_h_bil_t,o_v_bil_t : type_bil_t;
SIGNAL o_h_near_t,o_v_near_t : type_bil_t;
SIGNAL i_h_bil_t : type_bil_t;
-----------------------------------------------------------------------------
-- Sharp Bilinear
-- <0.5 : x*x*x*4
-- >0.5 : 1 - (1-x)*(1-x)*(1-x)*4
TYPE type_sbil_tt IS RECORD
f : unsigned(FRAC-1 DOWNTO 0);
s : unsigned(FRAC-1 DOWNTO 0);
END RECORD;
SIGNAL o_h_sbil_t,o_v_sbil_t : type_sbil_tt;
FUNCTION sbil_frac1(f : unsigned(11 DOWNTO 0)) RETURN type_sbil_tt IS
VARIABLE u : unsigned(FRAC-1 DOWNTO 0);
VARIABLE v : unsigned(2*FRAC-1 DOWNTO 0);
VARIABLE x : type_sbil_tt;
BEGIN
IF f(11)='0' THEN
u:=f(11 DOWNTO 12-FRAC);
ELSE
u:=NOT f(11 DOWNTO 12-FRAC);
END IF;
v:=u*u;
x.f:=u;
x.s:=v(2*FRAC-2 DOWNTO FRAC-1);
RETURN x;
END FUNCTION;
FUNCTION sbil_frac2(f : unsigned(11 DOWNTO 0);
t : type_sbil_tt) RETURN unsigned IS
VARIABLE v : unsigned(2*FRAC-1 DOWNTO 0);
BEGIN
v:=t.f*t.s;
IF f(11)='0' THEN
RETURN v(2*FRAC-2 DOWNTO FRAC-1);
ELSE
RETURN NOT v(2*FRAC-2 DOWNTO FRAC-1);
END IF;
END FUNCTION;
-----------------------------------------------------------------------------
-- Bicubic
TYPE type_bic_abcd IS RECORD
a : unsigned(7 DOWNTO 0); -- 0.8
b : signed(8 DOWNTO 0); -- 0.9
c : signed(11 DOWNTO 0); -- 3.9
d : signed(10 DOWNTO 0); -- 2.9
xx : signed(8 DOWNTO 0); -- X.X 1.8
END RECORD;
TYPE type_bic_pix_abcd IS RECORD
r,g,b : type_bic_abcd;
END RECORD;
TYPE type_bic_tt1 IS RECORD -- Intermediate result
r_bx,g_bx,b_bx : signed(8 DOWNTO 0); -- B.X 1.8
r_cxx,g_cxx,b_cxx : signed(11 DOWNTO 0); -- C.XX 3.9
r_dxx,g_dxx,b_dxx : signed(10 DOWNTO 0); -- D.XX 2.9
END RECORD;
TYPE type_bic_tt2 IS RECORD -- Intermediate result
r_abxcxx,g_abxcxx,b_abxcxx : signed(9 DOWNTO 0); -- A + B.X + C.XX 2.8
r_dxxx,g_dxxx,b_dxxx : signed(9 DOWNTO 0); -- D.X.X.X 2.8
END RECORD;
----------------------------------------------------------
-- Y = A + B.X + C.X.X + D.X.X.X = A + X.(B + X.(C + X.D))
-- A = Y(0) 0 .. 1 unsigned
-- B = Y(1)/2 - Y(-1)/2 -1/2 .. +1/2 signed
-- C = Y(-1) - 5*Y(0)/2 + 2*Y(1) - Y(2)/2 -3 .. +3 signed
-- D = -Y(-1)/2 + 3*Y(0)/2 - 3*Y(1)/2 + Y(2)/2 -2 .. +2 signed
FUNCTION bic_calc0(f : unsigned(11 DOWNTO 0);
pm,p0,p1,p2 : unsigned(7 DOWNTO 0)) RETURN type_bic_abcd IS
VARIABLE xx : signed(2*FRAC+1 DOWNTO 0); -- 2.(2*FRAC)
BEGIN
xx := signed('0' & f(11 DOWNTO 12-FRAC)) *
signed('0' & f(11 DOWNTO 12-FRAC)); -- 2.(2*FRAC)
RETURN type_bic_abcd'(
a=>p0,-- 0.8
b=>signed(('0' & p1) - ('0' & pm)), -- 0.9
c=>signed(("000" & pm & '0') - ("00" & p0 & "00") - ("0000" & p0) +
("00" & p1 & "00") - ("0000" & p2)), -- 3.9
d=>signed(("00" & p0 & '0') - ("00" & p1 & '0') - ("000" & p1) +
("000" & p0) + ("000" & p2) - ("000" & pm)), -- 2.9
xx=>xx(2*FRAC DOWNTO 2*FRAC-8)); -- 1.8
END FUNCTION;
FUNCTION bic_calc0(f : unsigned(11 DOWNTO 0);
p : arr_pix(0 TO 3)) RETURN type_bic_pix_abcd IS
BEGIN
RETURN type_bic_pix_abcd'(r=>bic_calc0(f,p(0).r,p(1).r,p(2).r,p(3).r),
g=>bic_calc0(f,p(0).g,p(1).g,p(2).g,p(3).g),
b=>bic_calc0(f,p(0).b,p(1).b,p(2).b,p(3).b));
END FUNCTION;
----------------------------------------------------------
-- Calc : B.X, C.XX, D.XX
FUNCTION bic_calc1(f : unsigned(11 DOWNTO 0);
abcd : type_bic_pix_abcd) RETURN type_bic_tt1 IS
VARIABLE t : type_bic_tt1;
VARIABLE bx : signed(9+FRAC DOWNTO 0); -- 1.(FRAC+9)
VARIABLE cxx : signed(20 DOWNTO 0); -- 4.17
VARIABLE dxx : signed(19 DOWNTO 0); -- 3.17
BEGIN
bx := abcd.r.b * signed('0' & f(11 DOWNTO 12-FRAC)); -- 1.(FRAC+9)
t.r_bx:=bx(9+FRAC DOWNTO 9+FRAC-8); -- 1.8
cxx:= abcd.r.c * abcd.r.xx; -- 3.9 * 1.8 = 4.17
t.r_cxx:=cxx(19 DOWNTO 8); -- 3.9
dxx:= abcd.r.d * abcd.r.xx; -- 2.9 * 1.8 = 3.17
t.r_dxx:=dxx(18 DOWNTO 8); -- 2.9
bx := abcd.g.b * signed('0' & f(11 DOWNTO 12-FRAC)); -- 1.(FRAC+9)
t.g_bx:=bx(9+FRAC DOWNTO 9+FRAC-8); -- 1.8
cxx:= abcd.g.c * abcd.g.xx; -- 3.9 * 1.8 = 4.17
t.g_cxx:=cxx(19 DOWNTO 8); -- 3.9
dxx:= abcd.g.d * abcd.g.xx; -- 2.9 * 1.8 = 3.17
t.g_dxx:=dxx(18 DOWNTO 8); -- 2.9
bx := abcd.b.b * signed('0' & f(11 DOWNTO 12-FRAC)); -- 1.(FRAC+9)
t.b_bx:=bx(9+FRAC DOWNTO 9+FRAC-8); -- 1.8
cxx:= abcd.b.c * abcd.b.xx; -- 3.9 * 1.8 = 4.17
t.b_cxx:=cxx(19 DOWNTO 8); -- 3.9
dxx:= abcd.b.d * abcd.b.xx; -- 2.9 * 1.8 = 3.17
t.b_dxx:=dxx(18 DOWNTO 8); -- 2.9
RETURN t;
END FUNCTION;
----------------------------------------------------------
-- Calc A + BX + CXX , X.DXX
FUNCTION bic_calc2(f : unsigned(11 DOWNTO 0);
t : type_bic_tt1;
abcd : type_bic_pix_abcd) RETURN type_bic_tt2 IS
VARIABLE u : type_bic_tt2;
VARIABLE x : signed(11+FRAC DOWNTO 0); -- 3.(9+FRAC)
BEGIN
u.r_abxcxx:=(t.r_bx(8) & t.r_bx) + ("00" & signed(abcd.r.a)) + t.r_cxx(10 DOWNTO 1); -- 2.8
u.g_abxcxx:=(t.g_bx(8) & t.g_bx) + ("00" & signed(abcd.g.a)) + t.g_cxx(10 DOWNTO 1); -- 2.8
u.b_abxcxx:=(t.b_bx(8) & t.b_bx) + ("00" & signed(abcd.b.a)) + t.b_cxx(10 DOWNTO 1); -- 2.8
x:=t.r_dxx * signed('0' & f(11 DOWNTO 12-FRAC)); --2.9 * 1.FRAC =3.(9+FRAC)
u.r_dxxx:=x(10+FRAC DOWNTO 9+FRAC-8); -- 2.8
x:=t.g_dxx * signed('0' & f(11 DOWNTO 12-FRAC)); --2.9 * 1.FRAC =3.(9+FRAC)
u.g_dxxx:=x(10+FRAC DOWNTO 9+FRAC-8); -- 2.8
x:=t.b_dxx * signed('0' & f(11 DOWNTO 12-FRAC)); --2.9 * 1.FRAC =3.(9+FRAC)
u.b_dxxx:=x(10+FRAC DOWNTO 9+FRAC-8); -- 2.8
RETURN u;
END FUNCTION;
----------------------------------------------------------
-- Calc (A + BX + CXX) + (DXXX)
FUNCTION bic_calc3(f : unsigned(11 DOWNTO 0);
t : type_bic_tt2;
abcd : type_bic_pix_abcd) RETURN type_pix IS
VARIABLE x : type_pix;
VARIABLE v : signed(9 DOWNTO 0); -- 2.8
BEGIN
v:=t.r_abxcxx + t.r_dxxx;
x.r:=bound(unsigned(v),8);
v:=t.g_abxcxx + t.g_dxxx;
x.g:=bound(unsigned(v),8);
v:=t.b_abxcxx + t.b_dxxx;
x.b:=bound(unsigned(v),8);
RETURN x;
END FUNCTION;
-----------------------------------------------------------------------------
SIGNAL o_h_bic_pix,o_v_bic_pix : type_pix;
SIGNAL o_h_bic_abcd1,o_h_bic_abcd2 : type_bic_pix_abcd;
SIGNAL o_v_bic_abcd1,o_v_bic_abcd2 : type_bic_pix_abcd;
SIGNAL o_h_bic_tt1,o_v_bic_tt1 : type_bic_tt1;
SIGNAL o_h_bic_tt2,o_v_bic_tt2 : type_bic_tt2;
-----------------------------------------------------------------------------
-- Polyphase
-- 2.7
TYPE poly_phase_t IS RECORD
t0, t1, t2, t3 : signed(9 DOWNTO 0);
END RECORD;
-- 4.14
TYPE poly_phase_interp_t IS RECORD
t0, t1, t2, t3 : signed(17 DOWNTO 0);
END RECORD;
-- 5.22
TYPE type_poly_t IS RECORD
r0,r1,b0,b1,g0,g1 : signed(26 DOWNTO 0);
END RECORD;
SIGNAL o_h_poly_mem : arr_uv40(0 TO 2**FRAC-1);
SIGNAL o_v_poly_mem : arr_uv40(0 TO 2**FRAC-1);
SIGNAL o_a_poly_mem : arr_uv40(0 TO 2**FRAC-1);
ATTRIBUTE ramstyle OF o_h_poly_mem : SIGNAL IS "no_rw_check";
ATTRIBUTE ramstyle OF o_v_poly_mem : SIGNAL IS "no_rw_check";
ATTRIBUTE ramstyle OF o_a_poly_mem : SIGNAL IS "no_rw_check";
SIGNAL o_a_poly_addr, o_v_poly_addr, o_h_poly_addr : integer RANGE 0 TO 2**FRAC-1;
SIGNAL o_h_poly_phase_a,o_h_poly_phase_a2,o_h_poly_phase_a3 : poly_phase_t;
SIGNAL o_v_poly_phase_a,o_v_poly_phase_a2,o_v_poly_phase_a3 : poly_phase_t;
SIGNAL o_poly_phase_a, o_poly_phase_a2, o_poly_phase_a3 : poly_phase_t;
SIGNAL o_poly_phase_b,o_poly_phase_b2,o_poly_phase_b3 : poly_phase_t;
SIGNAL o_v_poly_phase, o_v_poly_phase2, o_h_poly_phase, o_poly_phase : poly_phase_interp_t;
SIGNAL o_v_poly_pix, o_h_poly_pix : type_pix;
SIGNAL o_v_poly_lum, o_h_poly_lum, o_poly_lum : unsigned(7 DOWNTO 0);
SIGNAL o_poly_lerp_ta, o_poly_lerp_tb, o_poly_lerp_tb3 : signed(9 DOWNTO 0);
SIGNAL o_h_poly_t,o_h_poly_t2,o_v_poly_t : type_poly_t;
SIGNAL o_v_poly_adaptive, o_h_poly_adaptive, o_v_poly_use_adaptive, o_h_poly_use_adaptive : std_logic;
SIGNAL poly_wr_mode : std_logic_vector(2 DOWNTO 0);
SIGNAL poly_tdw : unsigned(39 DOWNTO 0);
SIGNAL poly_a2 : unsigned(FRAC-1 DOWNTO 0);
FUNCTION poly_unpack(a : unsigned(39 DOWNTO 0)) RETURN poly_phase_t IS
VARIABLE v : poly_phase_t;
BEGIN
v.t0 := signed(a(39 DOWNTO 30));
v.t1 := signed(a(29 DOWNTO 20));
v.t2 := signed(a(19 DOWNTO 10));
v.t3 := signed(a( 9 DOWNTO 0));
RETURN v;
END FUNCTION;