Skip to content

Instantly share code, notes, and snippets.

@mkatsimpris
Last active January 21, 2016 14:05
Show Gist options
  • Save mkatsimpris/8826cc5c518fd3ccfd22 to your computer and use it in GitHub Desktop.
Save mkatsimpris/8826cc5c518fd3ccfd22 to your computer and use it in GitHub Desktop.
Simple rgb2ycbcr module in myHLD. Any comments and corrections are welcome!!
constant C_Y_1 : signed(14 downto 0) := to_signed(4899, 15);
constant C_Y_2 : signed(14 downto 0) := to_signed(9617, 15);
constant C_Y_3 : signed(14 downto 0) := to_signed(1868, 15);
constant C_Cb_1 : signed(14 downto 0) := to_signed(-2764, 15);
constant C_Cb_2 : signed(14 downto 0) := to_signed(-5428, 15);
constant C_Cb_3 : signed(14 downto 0) := to_signed(8192, 15);
constant C_Cr_1 : signed(14 downto 0) := to_signed(8192, 15);
constant C_Cr_2 : signed(14 downto 0) := to_signed(-6860, 15);
constant C_Cr_3 : signed(14 downto 0) := to_signed(-1332, 15);
R_s <= signed('0' & fram1_q(7 downto 0));
G_s <= signed('0' & fram1_q(15 downto 8));
B_s <= signed('0' & fram1_q(23 downto 16));
signal Y_reg_1 : signed(23 downto 0);
signal Y_reg_2 : signed(23 downto 0);
signal Y_reg_3 : signed(23 downto 0);
signal Cb_reg_1 : signed(23 downto 0);
signal Cb_reg_2 : signed(23 downto 0);
signal Cb_reg_3 : signed(23 downto 0);
signal Cr_reg_1 : signed(23 downto 0);
signal Cr_reg_2 : signed(23 downto 0);
signal Cr_reg_3 : signed(23 downto 0);
signal Y_reg : signed(23 downto 0);
signal Cb_reg : signed(23 downto 0);
signal Cr_reg : signed(23 downto 0);
signal R_s : signed(8 downto 0);
signal G_s : signed(8 downto 0);
signal B_s : signed(8 downto 0);
-------------------------------------------------------------------
-- RGB to YCbCr conversion
-------------------------------------------------------------------
p_rgb2ycbcr : process(CLK, RST)
begin
if RST = '1' then
Y_Reg_1 <= (others => '0');
Y_Reg_2 <= (others => '0');
Y_Reg_3 <= (others => '0');
Cb_Reg_1 <= (others => '0');
Cb_Reg_2 <= (others => '0');
Cb_Reg_3 <= (others => '0');
Cr_Reg_1 <= (others => '0');
Cr_Reg_2 <= (others => '0');
Cr_Reg_3 <= (others => '0');
Y_Reg <= (others => '0');
Cb_Reg <= (others => '0');
Cr_Reg <= (others => '0');
elsif CLK'event and CLK = '1' then
Y_Reg_1 <= R_s*C_Y_1;
Y_Reg_2 <= G_s*C_Y_2;
Y_Reg_3 <= B_s*C_Y_3;
Cb_Reg_1 <= R_s*C_Cb_1;
Cb_Reg_2 <= G_s*C_Cb_2;
Cb_Reg_3 <= B_s*C_Cb_3;
Cr_Reg_1 <= R_s*C_Cr_1;
Cr_Reg_2 <= G_s*C_Cr_
Cr_Reg_3 <= B_s*C_Cr_3;
Y_Reg <= Y_Reg_1 + Y_Reg_2 + Y_Reg_3;
Cb_Reg <= Cb_Reg_1 + Cb_Reg_2 + Cb_Reg_3 + to_signed(128*16384,Cb_Reg'length);
Cr_Reg <= Cr_Reg_1 + Cr_Reg_2 + Cr_Reg_3 + to_signed(128*16384,Cr_Reg'length);
end if;
end process;
Y_8bit <= unsigned(Y_Reg(21 downto 14));
Cb_8bit <= unsigned(Cb_Reg(21 downto 14));
Cr_8bit <= unsigned(Cr_Reg(21 downto 14));
#!/bin/python
from myhdl import *
from commons import *
from math import *
from math import *
#Fixed point representation with 1 sign bit and 14 fractional bits
fract_bits = 14
sign_bits=1
Y_COEFF=[0.2999,0.587,0.114]
CB_COEFF=[-0.1687,-0.3313,0.5]
CR_COEFF=[0.5,-0.4187,-0.0813]
OFFSET=[0,128,128]
Y=[int(round(Y_COEFF[i]*(2**fract_bits )))for i in range(3)]
Cb=[int(round(CB_COEFF[i]*(2**fract_bits ))) for i in range(3)]
Cr=[int(round(CR_COEFF[i]*(2**fract_bits ))) for i in range(3)]
Offset=[int(round(OFFSET[i]*(2**fract_bits ))) for i in range(3)]
class RGB(object):
def __init__(self, nbits=8):
self.nbits=nbits
self.red = Signal(intbv(0)[nbits:])
self.green = Signal(intbv(0)[nbits:])
self.blue = Signal(intbv(0)[nbits:])
def next(self, r, g, b):
self.red.next = r
self.green.next = g
self.blue.next = b
def bitLength(self): return self.nbits
class YCbCr(object):
def __init__(self, nbits=8):
self.nbits = nbits
self.y = Signal(intbv(0)[nbits:])
self.cb = Signal(intbv(0)[nbits:])
self.cr = Signal(intbv(0)[nbits:])
def bitLength(self): return self.nbits
def rgb2ycbcr(ycbcr, enable_out, rgb, enable_in, clk, reset):
""" A RGB to YCbCr converter with reset.
I/O pins:
--------
y : output 8-bit unsigned value in range of 0-127
cb : output 8-bit unsigned value in range of 0-128
cr : output 8-bit unsigned value in range of 0-128
enable_out : output True when output is available
r : input 8-bit unsigned value in range of 0-255
g : input 8-bit unsigned value in range of 0-255
b : input 8-bit unsigned value in range of 0-255
enable_in : input True when input is available
clk : input clock boolean signal
reset : input reset boolean signal
"""
#signals for y,cb,cr registers
Y_reg,Cb_reg,Cr_reg=[[Signal(intbv(0,-2**(23),2**(23)-1)) for _ in range(3)] for _ in range(3)]
Y_sum,Cb_sum,Cr_sum=[Signal(intbv(0,-2**(23),2**(23)-1)) for _ in range(3)]
#signals for signed input RGB
R_s,G_s,B_s=[Signal(intbv(0,-2**8,2**8-1)) for _ in range(3)]
#signals for coefficient signed conversion
Y1_s,Y2_s,Y3_s=[Signal(intbv(Y[i],-2**14,2**14-1)) for i in range(3)]
Cb1_s,Cb2_s,Cb3_s=[Signal(intbv(Cb[i],-2**14,2**14-1)) for i in range(3)]
Cr1_s,Cr2_s,Cr3_s=[Signal(intbv(Cr[i],-2**14,2**14-1)) for i in range(3)]
offset_y,offset_cb,offset_cr=[Signal(intbv(Offset[i],-2**23,2**23-1)) for i in range(3)]
@always_comb
def logic2():
#input RGB signed conversion
R_s.next=rgb.red
G_s.next=rgb.green
B_s.next=rgb.blue
@always_seq(clk.posedge, reset=reset)
def logic():
enable_out.next = INACTIVE_LOW
if enable_in == ACTIVE_HIGH:
Y_reg[0].next=R_s*Y1_s
Y_reg[1].next=G_s*Y2_s
Y_reg[2].next=B_s*Y3_s
Cb_reg[0].next=R_s*Cb1_s
Cb_reg[1].next=G_s*Cb2_s
Cb_reg[2].next=B_s*Cb3_s
Cr_reg[0].next=R_s*Cr1_s
Cr_reg[1].next=G_s*Cr2_s
Cr_reg[2].next=B_s*Cr3_s
Y_sum.next=Y_reg[0]+Y_reg[1]+Y_reg[2]+offset_y
Cb_sum.next=Cb_reg[0]+Cb_reg[1]+Cb_reg[2]+offset_cb
Cr_sum.next=Cr_reg[0]+Cr_reg[1]+Cr_reg[2]+offset_cr
#outputs y,cr,cb unsigned 8 MSB
ycbcr.y.next=Y_sum[22:14]
ycbcr.cb.next=Cb_sum[22:14]
ycbcr.cr.next=Cr_sum[22:14]
enable_out.next = ACTIVE_HIGH
return logic,logic2
def convert():
ycbcr = YCbCr()
rgb = RGB()
clk, enable_in, enable_out = [Signal(INACTIVE_LOW) for _ in range(3)]
reset = ResetSignal(1, active=ACTIVE_LOW, async=True)
toVHDL(rgb2ycbcr,ycbcr, enable_out, rgb, enable_in, clk, reset)
convert()
-- File: rgb2ycbcr.vhd
-- Generated by MyHDL 0.9.0
-- Date: Thu Jan 21 14:21:38 2016
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
use std.textio.all;
use work.pck_myhdl_090.all;
entity rgb2ycbcr is
port (
enable_out: out std_logic;
enable_in: in std_logic;
clk: in std_logic;
reset: in std_logic;
ycbcr_y: out unsigned(7 downto 0);
ycbcr_cb: out unsigned(7 downto 0);
ycbcr_cr: out unsigned(7 downto 0);
rgb_blue: in unsigned(7 downto 0);
rgb_green: in unsigned(7 downto 0);
rgb_red: in unsigned(7 downto 0)
);
end entity rgb2ycbcr;
-- A RGB to YCbCr converter with reset.
--
-- I/O pins:
-- --------
-- y : output 8-bit unsigned value in range of 0-127
-- cb : output 8-bit unsigned value in range of 0-128
-- cr : output 8-bit unsigned value in range of 0-128
-- enable_out : output True when output is available
-- r : input 8-bit unsigned value in range of 0-255
-- g : input 8-bit unsigned value in range of 0-255
-- b : input 8-bit unsigned value in range of 0-255
-- enable_in : input True when input is available
-- clk : input clock boolean signal
-- reset : input reset boolean signal
architecture MyHDL of rgb2ycbcr is
constant ACTIVE_HIGH: integer := 1;
constant INACTIVE_LOW: integer := 0;
signal Y2_s: signed (14 downto 0);
signal Y3_s: signed (14 downto 0);
signal Y1_s: signed (14 downto 0);
signal Cr1_s: signed (14 downto 0);
signal G_s: signed (8 downto 0);
signal Cr_sum: signed (23 downto 0);
signal Cr2_s: signed (14 downto 0);
signal offset_y: signed (23 downto 0);
signal Cr3_s: signed (14 downto 0);
signal Cb_sum: signed (23 downto 0);
signal R_s: signed (8 downto 0);
signal offset_cr: signed (23 downto 0);
signal Cb1_s: signed (14 downto 0);
signal Y_sum: signed (23 downto 0);
signal Cb2_s: signed (14 downto 0);
signal offset_cb: signed (23 downto 0);
signal Cb3_s: signed (14 downto 0);
signal B_s: signed (8 downto 0);
type t_array_Cb_reg is array(0 to 3-1) of signed (23 downto 0);
signal Cb_reg: t_array_Cb_reg;
type t_array_Cr_reg is array(0 to 3-1) of signed (23 downto 0);
signal Cr_reg: t_array_Cr_reg;
type t_array_Y_reg is array(0 to 3-1) of signed (23 downto 0);
signal Y_reg: t_array_Y_reg;
begin
Y2_s <= to_signed(9617, 15);
Y3_s <= to_signed(1868, 15);
Y1_s <= to_signed(4914, 15);
Cr1_s <= to_signed(8192, 15);
Cr2_s <= to_signed(-6860, 15);
offset_y <= to_signed(0, 24);
Cr3_s <= to_signed(-1332, 15);
offset_cr <= to_signed(2097152, 24);
Cb1_s <= to_signed(-2764, 15);
Cb2_s <= to_signed(-5428, 15);
offset_cb <= to_signed(2097152, 24);
Cb3_s <= to_signed(8192, 15);
RGB2YCBCR_LOGIC: process (clk, reset) is
begin
if (reset = '0') then
Y_sum <= to_signed(0, 24);
Cb_sum <= to_signed(0, 24);
ycbcr_cb <= to_unsigned(0, 8);
enable_out <= '0';
Cr_reg(0) <= to_signed(0, 24);
Cr_reg(1) <= to_signed(0, 24);
Cr_reg(2) <= to_signed(0, 24);
Y_reg(0) <= to_signed(0, 24);
Y_reg(1) <= to_signed(0, 24);
Y_reg(2) <= to_signed(0, 24);
Cr_sum <= to_signed(0, 24);
ycbcr_cr <= to_unsigned(0, 8);
Cb_reg(0) <= to_signed(0, 24);
Cb_reg(1) <= to_signed(0, 24);
Cb_reg(2) <= to_signed(0, 24);
ycbcr_y <= to_unsigned(0, 8);
elsif rising_edge(clk) then
enable_out <= '0';
if (enable_in = '1') then
Y_reg(0) <= (R_s * Y1_s);
Y_reg(1) <= (G_s * Y2_s);
Y_reg(2) <= (B_s * Y3_s);
Cb_reg(0) <= (R_s * Cb1_s);
Cb_reg(1) <= (G_s * Cb2_s);
Cb_reg(2) <= (B_s * Cb3_s);
Cr_reg(0) <= (R_s * Cr1_s);
Cr_reg(1) <= (G_s * Cr2_s);
Cr_reg(2) <= (B_s * Cr3_s);
Y_sum <= (((Y_reg(0) + Y_reg(1)) + Y_reg(2)) + offset_y);
Cb_sum <= (((Cb_reg(0) + Cb_reg(1)) + Cb_reg(2)) + offset_cb);
Cr_sum <= (((Cr_reg(0) + Cr_reg(1)) + Cr_reg(2)) + offset_cr);
ycbcr_y <= unsigned(Y_sum(22-1 downto 14));
ycbcr_cb <= unsigned(Cb_sum(22-1 downto 14));
ycbcr_cr <= unsigned(Cr_sum(22-1 downto 14));
end if;
enable_out <= '1';
end if;
end process RGB2YCBCR_LOGIC;
R_s <= signed(resize(rgb_red, 9));
G_s <= signed(resize(rgb_green, 9));
B_s <= signed(resize(rgb_blue, 9));
end architecture MyHDL;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment