Exemple #1
0
def PWM(clk_i,
        d_i,
        pwm_o,
        CLK_FREC,
        PWM_FREC) :


    n = len(d_i)

    CUENTA_DIVISOR = int(round(CLK_FREC / ( PWM_FREC * 2**n )))

    cuenta_div = Signal(intbv(0, 0, CUENTA_DIVISOR + 1))

    cuenta_pwm = Signal(intbv(0)[n:])

    dato = Signal(intbv(0)[n:])
    rst_pwm = Signal(Lo)
    ce_pwm = Signal(Lo)

    contador_div = CB_R(clk_i = clk_i,           # "Divisor de frecuencia" 
                        rst_i = ce_pwm,
                        q_o = cuenta_div)

    @always(cuenta_div)
    def gen_ce_pwm() :
        if cuenta_div == CUENTA_DIVISOR - 1 :
            ce_pwm.next = Hi
        else :
            ce_pwm.next = Lo                     
                        

    contador_pwm = CB_RE(clk_i = clk_i,              
                         rst_i = rst_pwm,
                         ce_i = ce_pwm,
                         q_o = cuenta_pwm)

    reg_dato = FD_E(clk_i = clk_i,
                    ce_i = rst_pwm,
                    d_i = d_i,
                    q_o = dato)
    
    @always(cuenta_pwm, ce_pwm)
    def gen_rst_pwm() :
        if ce_pwm and cuenta_pwm == 2**n - 1 :
            rst_pwm.next = Hi
        else :
            rst_pwm.next = Lo

    @always(cuenta_pwm, dato)
    def gen_pwm_o() :
        if cuenta_pwm < dato :
            pwm_o.next = Hi
        else :
            pwm_o.next = Lo


    return instances()
Exemple #2
0
def Monoestable(clk_i, rst_i, a_i, q_o, FREC_CLK=27e6, TIEMPO=240e-9):
    """Este modulo genera una senal que dura un tiempo determinado cuando es disparada por a_i 

    :Parametros:            
        - `clk_i`    : entrada de clock
        - `rst_i`    : senal de reset
        - `a_i`      : senal de disparo
        - `q_o`      : salida triguereada

    Funcionamiento::

                    _   _   _   _   _   _       _   _   _   _   _   _
        clk_i      | |_| |_| |_| |_| |_| | ... | |_| |_| |_| |_| |_| |
                        __                            
        a_i      ______|  |_______________ ... _______________________

                           _______________ ... __________         
        q_o      _________|                              |______________


    :Nota: a_i debe estar sincronica con el clk
                                     
    """
    CUENTA_MAX = int(round(TIEMPO * FREC_CLK))
    cuenta = Signal(intbv(0, 0, CUENTA_MAX + 1))
    ena = Signal(Lo)
    flanco = Signal(Lo)

    e = enum("ESP_FLANCO", "CUENTA")
    estado = Signal(e.ESP_FLANCO)

    cont_1 = CB_RE(clk_i=clk_i, rst_i=flanco, ce_i=ena, q_o=cuenta)

    flanco_1 = detecta_flanco_subida(clk_i=clk_i, a_i=a_i, flanco_o=flanco)

    @always(clk_i.posedge)
    def FSM():
        if rst_i:
            estado.next = e.ESP_FLANCO

        else:
            if estado == e.ESP_FLANCO:
                if flanco:
                    estado.next = e.CUENTA
                    ena.next = Hi
                    q_o.next = Hi

            elif estado == e.CUENTA:
                if cuenta == CUENTA_MAX - 1:
                    ena.next = Lo
                    q_o.next = Lo
                    estado.next = e.ESP_FLANCO

    return instances()
Exemple #3
0
def conversion_half_precision(clk_i, x_i, signo_x_i, bits_entero, ini_i,
                              fl_x_o, done_o):
    """Conversor a punto flotante half-precision::

        signo_x : 0 = +, 1 = -
    
        x       : bn --- b16 b15 b14 . b13 b12 b11 b10 b9 b8 b7 b6 b5 b4 b3 b2 b1 b0
                   |______________|  
                          |
                    bits_entero

        fl_x    :   S | Exp + 15 | mantisa              
                    |       |         |                      
        cant_bits   1       5        10   

        x = (-1)^S * 2^Exp * 1.mantisa


    :Nota: la parte fraccionaria de x_i debe tener 14 bits, ya que el valor minimo positivo que se puede representar en half precision es 2**-14
           y como el maximo es 65504, la parte entera de x_i puede tener hasta 16 bits (Tener en cuenta que esta implementacion solo convierte
           los numeros normalizados y el cero, si x_i > 65504, el conversor no funciona)

    """

    n = len(x_i)
    m = len(fl_x_o)  # 16 para half precision
    fl_x = Signal(intbv(0)[m:])  # Flotante Half Precision
    x_q = Signal(intbv(0)[n:])
    pos = Signal(intbv(0, 0, n + 1))  # Pos del primer 1 de x_i
    exp = Signal(intbv(0)[5:])
    mantisa = Signal(intbv(0)[10:])

    k = 15 + bits_entero - 1  # exponente real = bits_entero - 1 - pos
    # exponente desplazado por norma = 15 + exponente real = k - pos

    fin_contador = Signal(
        Lo)  # fin_contador indica que x_i es cero => expo = 0
    encontrado = Signal(
        Lo
    )  # Indica que se encontro la pos en x_i que tiene el 1 de mayor peso
    fin_busqueda = Signal(
        Lo
    )  # Indica que se encontro la pos en x_i que tiene el 1 de mayor peso o x_i es cero
    cargar = Signal(Lo)  # Carga x_i en el shift register
    despl_y_contar = Signal(
        Lo
    )  # Desplaza a la izquierda x y cuenta la pos para saber donde esta el 1 de mayor peso en x
    latch = Signal(Lo)  # Antes de levantar la bandera de done, "latcheo" fl_x

    # Datapath

    reg = SR_LE_PiPo_Izq(
        clk_i=clk_i, load_i=cargar, d_i=x_i, ce_i=despl_y_contar,
        q_o=x_q)  # Desplazo x a la izquierda para encontrar el 1 de mayor peso

    @always_comb
    def extrae_mantisa():
        mantisa.next = x_q[
            n - 1:n -
            11]  # La mantisa son los 10 bits despues del 1 de mayor peso

    @always_comb
    def conexion_encontrado():
        encontrado.next = x_q[n - 1]

    @always_comb
    def fin_busq():
        fin_busqueda.next = fin_contador | encontrado

    contador = CB_RE(
        clk_i=clk_i, rst_i=cargar, ce_i=despl_y_contar, q_o=pos
    )  # Contador para conocer la pos del 1 de mayor peso de x_i y luego calcular el exponente

    @always(pos)
    def fin_cont():
        if pos == n:
            fin_contador.next = Hi
        else:
            fin_contador.next = Lo

    @always_comb
    def restador():
        exp.next = k - pos

    @always_comb
    def conex_fl():
        fl_x.next = concat(signo_x_i, exp, mantisa)

    reg_fl = FD_E(clk_i=clk_i, ce_i=latch, d_i=fl_x, q_o=fl_x_o)

    ######## Unidad de control del conversor

    e = enum("ESPERA_INICIO", "BUSQUEDA", "FIN")

    estado = Signal(e.ESPERA_INICIO)

    @always(clk_i.posedge)
    def FSM_estados():
        "Logica de cambio de estados"
        ##############################
        if estado == e.ESPERA_INICIO:
            if ini_i:
                estado.next = e.BUSQUEDA
        ##############################
        elif estado == e.BUSQUEDA:
            if fin_busqueda:
                estado.next = e.FIN
        ##############################
        elif estado == e.FIN:
            estado.next = e.ESPERA_INICIO

        else:
            estado.next = e.ESPERA_INICIO

    @always(estado, ini_i, fin_busqueda)
    def FSM_salidas():
        "Logica de salida"
        ##############################
        if estado == e.ESPERA_INICIO:
            done_o.next = Hi
            latch.next = Lo
            despl_y_contar.next = Lo
            if ini_i:
                cargar.next = Hi
            else:
                cargar.next = Lo
        ##############################
        elif estado == e.BUSQUEDA:
            done_o.next = Lo
            cargar.next = Lo
            if fin_busqueda:
                despl_y_contar.next = Lo
                latch.next = Hi
            else:
                despl_y_contar.next = Hi
                latch.next = Lo
        #############################
        elif estado == e.FIN:
            done_o.next = Lo
            latch.next = Lo
            despl_y_contar.next = Lo
            cargar.next = Lo

        else:
            done_o.next = Lo
            latch.next = Lo
            despl_y_contar.next = Lo
            cargar.next = Lo

    return instances()
Exemple #4
0
def FIFO(clk_i, ce_i, d_i, q_o, k):
    """Estrucutra FIFO de k etapas y n bits de datos 
    con clock enable 
    ::

            ________________________
       ____|                        |____
       ____| d_i                q_o |____
           |                        |
       ----|> clk_i                 |
           |                        |
       ----| ce_i                   |
           |________________________|
 
    :Parametros:
        - `clk_i` :  entrada de clock
        - `ce_i`  :  clock enable
        - `d_i`   :  data in (n bits)
        - `q_o`   :  data out (n bits)
        - `k`     :  longitud de la cola

    """

    # Descripcion estructural
    #

    n = len(d_i)
    addr_max = k - 1

    rst_cont = Signal(Lo)
    w_addr = Signal(intbv(0, 0,
                          k))  # Puntero de llenado de la cola  (Puerto A)
    r_addr = Signal(intbv(1, 0,
                          k))  # Puntero de vaciado o lectura   (Puerto B)

    p = len(w_addr)

    if n == 1:
        ram = [Signal(Lo) for i in range(2**p)]
    else:
        ram = [Signal(intbv(0)[n:]) for i in range(2**p)]

    ###############################################

    gen_w_addr = CB_RE(clk_i=clk_i, rst_i=rst_cont, ce_i=ce_i,
                       q_o=w_addr)  # Puntero de llenado

    @always(w_addr, ce_i)
    def gen_r_addr():
        if w_addr == addr_max:
            rst_cont.next = ce_i
            r_addr.next = 0
        else:
            rst_cont.next = Lo
            r_addr.next = w_addr + 1  # El puntero de vaciado esta uno por delante del de llenado

    @always(clk_i.posedge)
    def RAM_access():
        if ce_i:
            ram[int(w_addr)].next = d_i
            q_o.next = ram[int(r_addr)]

    return instances()
Exemple #5
0
def genera_coord_PAL(clk27_i, vs_i, hs_i, odd_even_i, pix_ce_o, pixel_x_o,
                     pixel_y_o, video_activo_o, ini_frame_o):
    """Este modulo genera las coordenadas (x,y) del pixel activo actual de un sistema PAL (720x576i).  
    ::

             x
         *--->
         |  -------------------------
       y v |(0,0)                    |
           |                         |
           |                         |
           |       Zona activa       | 
           |        de video         | 
           |                         | 
           |                         |
           |                (719,575)|
            -------------------------

    :Parametros:
        - `clk27_i`        -- entrada de clock de pixel x2 ( 27Mhz )
        - `vs_i`           -- entrada de sincronismo vertical
        - `hs_i`           -- entrada de sincronismo horizontal
        - `odd_even_i`     -- entrada de campo odd/even
        - `pix_ce_o`       -- salida de pixel clock enable  
        - `pixel_x_o`      -- salida de la coordenada x del pixel activo actual [0 .. 720] 
        - `pixel_y_o`      -- salida de la coordenada y del pixel activo actual [0 .. 576]
        - `video_activo_o` -- salida que determina la ventana temporal del video activo  
        - `ini_frame_o`    -- inicio del frame  

    """

    # Info del Horiz
    PIXELS_x_LINEA = 864  # Cantidad de pixels de una linea de video
    PIXELS_x_LINEA_ACTIVA = 720  # Cantidad de pixels activos de una linea de video
    PIXELS_x_SYNC_H = 64  # Cantidad de pixels del pulso de sinc h.
    PIXELS_x_BP = 68  # Cantidad de pixels de back porch
    INICIO_X = PIXELS_x_SYNC_H + PIXELS_x_BP - 6  # Comienzo del pixel activo en la linea (Nota el -6 es por atraso en el tracker analogico)

    # Info del Vert
    TOTAL_LINEAS = 625  # Total de lineas del PAL
    LINEAS_ACTIVAS = 576  # Cantidad de lineas activas de video

    LINEA_INI_VIDEO_ACTIVO_ODD = 21  # Linea de comienzo del video activo en el campo impar
    LINEA_FIN_VIDEO_ACTIVO_ODD = 308  # Linea de finalizacion del video activo en el campo impar

    LINEA_INI_VIDEO_ACTIVO_EVEN = 334  # Linea de comienzo del video activo en el campo par
    LINEA_FIN_VIDEO_ACTIVO_EVEN = 621  # Linea de finalizacion del video activo en el campo par

    # Senales y registros

    ini_hs = Signal(Lo)  # Pulso de inicio de sincronismo horizontal
    ini_vs = Signal(Lo)  # Inicio de sincronismo vertical
    pix_ce = Signal(Lo)  # Clock enable para contar pixels

    barrido_x = Signal(intbv(
        0, 0, PIXELS_x_LINEA))  # Registros para llevar la posicion del barrido
    nro_linea = Signal(intbv(0, 0, TOTAL_LINEAS))  #

    ini_odd = Signal(Lo)  # Pulso de inicio de campo impar
    rst_aux = Signal(Lo)
    rst_n_lineas = Signal(Lo)  # Reset del contador de lineas

    video_activo_x = Signal(Lo)
    video_activo_y = Signal(Lo)

    ########################################################################################################
    #
    # Horizontal
    # ==========
    #                   _____________                                   __________________________________
    #    hs                          |_____________________________ ***
    #                     _   _   _   _   _   _   _   _   _   _   _       _   _   _   _   _   _   _   _
    #    clk @ 27MHz    _| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_|  *** _| |_| |_| |_| |_| |_| |_| |_| |_|
    #                                 ___
    #    ini_hs         _____________|   |_________________________ *** __________________________________
    #                         ___     ___     ___     ___     ___       _     ___     ___     ___     ___
    #    pix_ce          |___|   |___|   |___|   |___|   |___|   |_ ***  |___|   |___|   |___|   |___|   |
    #
    #    barrido_x       ]  862  ]  863  ]   0   ]   1   ]   2   ]  ***  ]  131  ]  132  ]  133  ]  134  ]
    #                                                                             ________________________
    #    video_activo_x ___________________________________________ *** _________|
    #
    #    pixel_x                                0                                [   0   ]   1   ]   2   ]
    #

    gen_ini_hs = detecta_flanco_bajada(clk_i=clk27_i,
                                       a_i=hs_i,
                                       flanco_o=ini_hs)

    gen_pix_ena = FT_R(clk_i=clk27_i, rst_i=ini_hs, t_i=Signal(Hi),
                       q_o=pix_ce)  # Divide x2 la frec de clock

    gen_barrido_x = CB_RE(
        clk_i=clk27_i, rst_i=ini_hs, ce_i=pix_ce, q_o=barrido_x
    )  # Cuenta los "pixels" (tanto activos como los de blanking)
    # en una linea de video, comenzando desde el flanco de bajada de hs

    @always_comb
    def gen_video_activo_x():
        if INICIO_X <= barrido_x and barrido_x < INICIO_X + PIXELS_x_LINEA_ACTIVA:  # Comparador para determinar la ventana temporal de la linea activa
            video_activo_x.next = Hi
        else:
            video_activo_x.next = Lo

    ########################################################################################################################
    #
    # Vertical
    # ========
    #                ___      _      _      _      _      _   ______   ______   ______   ______   ______   ____________   _
    #   mix_sync        |____| |____| |____| |____| |____| |_|      |_|      |_|      |_|      |_|      |_|            |_|
    #                ___   ___________   ___________   _____________   _______________   _______________   ____________   _
    #   hs_i            |_|           |_|           |_|             |_|               |_|               |_|            |_|
    #                ________                                          ____________________________________________________
    #   vs_i                 |________________________________________|
    #                         _____________________________________________________________________________________________
    #   odd_even_i   ________|
    #
    #   nro_linea       ]     624     ]      0      ]       1       ]        2        ]        3        ]      4       ]
    #

    gen_ini_vs = detecta_flanco_bajada(clk_i=clk27_i,
                                       a_i=vs_i,
                                       flanco_o=ini_vs)

    @always_comb
    def gen_ini_odd(
    ):  # Genera un pulso al comienzo del campo impar para resetear el contador de lineas
        ini_odd.next = ini_vs & odd_even_i

    gen_rst_n_linea = FJK(clk_i=clk27_i, j_i=ini_odd, k_i=ini_hs, q_o=rst_aux)

    @always_comb
    def gen_rst_vert():
        rst_n_lineas.next = rst_aux & ini_hs  # un pulsito al comienzo del primer hs dentro del vs del campo impar

    gen_nro_linea = CB_RE(
        clk_i=clk27_i, rst_i=rst_n_lineas, ce_i=ini_hs, q_o=nro_linea
    )  # Cuenta las lineas de video desde el comienzo del campo impar

    @always_comb
    def gen_video_activo_y():
        if (LINEA_INI_VIDEO_ACTIVO_EVEN <= nro_linea
                and nro_linea <= LINEA_FIN_VIDEO_ACTIVO_EVEN) or (
                    LINEA_INI_VIDEO_ACTIVO_ODD <= nro_linea
                    and nro_linea <= LINEA_FIN_VIDEO_ACTIVO_ODD):
            video_activo_y.next = Hi
        else:
            video_activo_y.next = Lo

    @always_comb
    def gen_video_activo():
        video_activo_o.next = video_activo_x & video_activo_y  # Parte util de la senal de video

    @always(barrido_x, video_activo_x)
    def gen_pixel_x():
        if video_activo_x:
            pixel_x_o.next = barrido_x - INICIO_X
        else:
            pixel_x_o.next = 0

    @always(nro_linea, video_activo_y, odd_even_i)
    def gen_pixel_y():
        if video_activo_y:
            if odd_even_i:
                pixel_y_o.next = (
                    nro_linea - LINEA_INI_VIDEO_ACTIVO_ODD
                ) * 2  # el "* 2" es debido al barrido entrelazado y el campo impar tiene la primer linea
            else:
                pixel_y_o.next = (nro_linea -
                                  LINEA_INI_VIDEO_ACTIVO_EVEN) * 2 + 1
        else:
            pixel_y_o.next = 0

    @always_comb
    def conex_pix_ce_o():
        pix_ce_o.next = pix_ce

    @always_comb
    def gen_ini_frame():
        ini_frame_o.next = odd_even_i and ini_vs

    return instances()
Exemple #6
0
def VGA_control(clk50_i, hs_o, vs_o, video_activo_o, pix_address_o, RGB_data_i,
                red_o, green_o, blue_o):
    """Modulo que genera las senales de sincronismo de un sistema VGA (800x600 @ 72Hz) 

    :Parametros:
        - `clk50_i`        -- Entrada de clock de pixel @ 50Mhz
        - `hs_o`           -- Sincronismo horizontal
        - `vs_o`           -- Sincronismo vertical
        - `video_activo_o` -- Salida que determina la ventana temporal del video activo (nBlank)  
        - `pix_address_o`  -- Direccion del proximo pixel a leer 
        - `RGB_data_i`     -- Valor del pixel leido desde la memoria
        - `red_o`          -- Salida de rojo
        - `green_o`        -- Salida de verde
        - `blue_o`         -- Salida de azul
    """

    ######################################
    # Parametros del Horizontal (en pixels)
    H_FRONT = 56
    H_SYNC = 120
    H_BACK = 64
    H_ACT = 800
    H_BLANK = H_FRONT + H_SYNC + H_BACK
    H_TOTAL = H_FRONT + H_SYNC + H_BACK + H_ACT
    ######################################
    # Parametros del Vertical (en lineas)
    V_FRONT = 37
    V_SYNC = 6
    V_BACK = 23
    V_ACT = 600
    V_BLANK = V_FRONT + V_SYNC + V_BACK
    V_TOTAL = V_FRONT + V_SYNC + V_BACK + V_ACT

    ###################
    # Senales y registros

    h_cont = Signal(intbv(
        0, 0, H_TOTAL))  # registros para llevar la pos. del barrido
    v_cont = Signal(intbv(0, 0, V_TOTAL))

    rst_h = Signal(Lo)  # Reset del contador horizontal y clock ena del vert
    rst_v = Signal(Lo)  # Reset del vertical

    ####################################################
    #

    contador_H = CB_R(clk_i=clk50_i, rst_i=rst_h,
                      q_o=h_cont)  # Cuenta pix horiz

    contador_V = CB_RE(clk_i=clk50_i, rst_i=rst_v, ce_i=rst_h,
                       q_o=v_cont)  # Cuenta lineas

    @always_comb
    def gen_rst():
        if h_cont == H_TOTAL - 1:
            rst_h.next = Hi
        else:
            rst_h.next = Lo
        if v_cont == (V_TOTAL - 1) and rst_h == Hi:
            rst_v.next = Hi
        else:
            rst_v.next = Lo

#    @always_comb
#    def gen_sync() :
#        if <h_cont

    return instances()
Exemple #7
0
def ITU_656_deco(clk27_i, data_i, pixel_x_o, pixel_y_o, pix_ena_o,
                 video_activo_o, Y_o, Cb_o, Cr_o, ini_frame_o):
    """Decodifica la norma ITU-656 (PAL), obteniendo las coordenadas del pixel actual y su valor de YCbCr

    :Parametros:
        - `clk27_i`        -- entrada de clock de 27Mhz 
        - `data_i`         -- entrada de datos en norma itu 656 (PAL)
        - `pix_ena_o`      -- salida de pixel enable  
        - `pixel_x_o`      -- salida de la coordenada x del pixel activo actual [0 .. 720] 
        - `pixel_y_o`      -- salida de la coordenada y del pixel activo actual [0 .. 576]
        - `video_activo_o` -- salida que determina la ventana temporal del video activo  
        - `Y_o`            -- valor de luma del pixel actual (unsigned)     
        - `Cb_o`           -- valor de croma del pixel actual (signed)    
        - `Cr_o`           -- valor de croma del pixel actual (signed)    
        - `ini_frame_o`    -- salida de inicio del cuadro (inicio del campo impar)

    """

    # Info del Horiz
    PIXELS_x_LINEA = 864  # Cantidad de pixels de una linea de video PAL
    PIXELS_x_LINEA_ACTIVA = 720  # Cantidad de pixels activos de una linea de video

    # Info del Vert
    TOTAL_LINEAS = 625  # Total de lineas del PAL
    LINEAS_ACTIVAS = 576  # Cantidad de lineas activas de video PAL

    LINEA_INI_VIDEO_ACTIVO_ODD = 22  # Linea de comienzo del video activo en el campo impar
    LINEA_FIN_VIDEO_ACTIVO_ODD = 309  # Linea de finalizacion del video activo en el campo impar

    LINEA_INI_VIDEO_ACTIVO_EVEN = 335  # Linea de comienzo del video activo en el campo par
    LINEA_FIN_VIDEO_ACTIVO_EVEN = 622  # Linea de finalizacion del video activo en el campo par

    n = len(data_i)

    #################################
    ### Senales y registros

    data_q1 = Signal(
        intbv(0)[n:]
    )  # Registros para la ventana de deteccion de los codigos de sincronismo
    data_q2 = Signal(intbv(0)[n:])
    data_q3 = Signal(intbv(0)[n:])
    sav = Signal(Lo)  # Deteccion del start active video SAV
    sav_q1 = Signal(Lo)
    sav_q2 = Signal(Lo)
    eav = Signal(Lo)  # Deteccion del end active video
    n_f = Signal(Lo)  # Bit de Frame
    v = Signal(Lo)  # Bit de Vertical

    Y = Signal(intbv(0)[n:])
    Cb = Signal(intbv(0)[n:])
    Cb_q = Signal(intbv(0)[n:])

    ena_Y = Signal(Lo)  # Para muestrear la informacion de luma
    ena_x = Signal(Lo)  # Para contar la coordenada x
    ena_Y_2 = Signal(Lo)  # Aux para generar ena_Cb
    ena_Cb = Signal(Lo)  # Para muestrear la informacion de croma blue
    ena_Cb_q = Signal(Lo)  # Aux para generar ena_Cr
    ena_Cr = Signal(Lo)  # Para muestrear la informacion de croma red

    pos_x = Signal(intbv(0, 0, PIXELS_x_LINEA))
    nro_linea = Signal(intbv(0, 0, TOTAL_LINEAS))

    rst_x = Signal(Lo)  # Reset del contador horizontal
    rst_y = Signal(Lo)  # Reset del contador de lineas

    odd_even = Signal(Lo)  # 1 Impar (Trama 1), 0 Par (Trama 2)

    video_activo_x = Signal(Lo)
    video_activo_y = Signal(Lo)

    ena_aux = Signal(Lo)
    ini_frame = Signal(Lo)
    ena_ini_frame = Signal(Lo)
    rst_ini_frame = Signal(Lo)
    cuenta_ini_frame = Signal(intbv(0, 0, 15 + 1))

    #################################
    ### Datapath

    #########################################################################################
    ### Descripcion del codigo SAV de referencia para la temporizacion de la senal de video
    #
    #                   ____      ____      ____      ____      ____      ____      ____
    #   clk27_i    ____|    |____|    |____|    |____|    |____|    |____|    |____|    |
    #
    #   data_i              |   FF    |   00    |    00   |    XY   |   Cb    |   Y0    |
    #
    #              H Blank  |                  SAV                  |    Video activo
    #
    #
    #    Descripcion de los bits del byte XY del SAV :
    #    -------------------------------------------
    #
    #       XY[6] = F : 0 durante la trama (campo ) 1
    #                   1 durante la trama 2
    #
    #       XY[5] = V : 0 fuera de la supresion vertical
    #                   1 durante la supresion vertical
    #
    #       XY[4] = H : 0 en SAV  (Start Active Video)
    #                   1 en EAV  (End Active Video)
    #

    # Ventana de 4 bytes para la deteccion del codigo de ref. para la temp
    reg_1 = FD(clk_i=clk27_i, d_i=data_i, q_o=data_q1)

    reg_2 = FD(clk_i=clk27_i, d_i=data_q1, q_o=data_q2)

    reg_3 = FD(clk_i=clk27_i, d_i=data_q2, q_o=data_q3)

    @always_comb
    def detec_cod_ref():
        if data_q3 == 0xFF and data_q2 == 0 and data_q1 == 0:
            sav.next = not data_i[4]
            eav.next = data_i[4]
            n_f.next = not data_i[6]
            v.next = not data_i[5]
        else:
            v.next = Lo
            n_f.next = Lo
            sav.next = Lo
            eav.next = Lo

    ##########################################################################################################
    #
    #
    #   data_i     |    XY   |   Cb0   |   Y0    |   Cr    |    Y1   |    Cb1  |   Y2    |   Cr1   |   Y3    |
    #
    #             _      ____      ____      ____      ____      ____      ____      ____      ____      ____
    #   clk27_i    |____|    |____|    |____|    |____|    |____|    |____|    |____|    |____|    |____|    |
    #
    #               ____
    #   sav       _|    |____________________________________________________________________________________
    #
    #                              _________           _________            ________           ________
    #   ena_Y     * * * |_________|         |_________|         |__________|        |_________|        |_____
    #
    #
    #   Y                * * * * * *        |        Y0         |       Y1          |       Y2         |   Y3
    #
    #                    _________                               __________                             _____
    #   ena_Cb    ______|         |_____________________________|          |___________________________|
    #
    #
    #   Cb           * * *        |                Cb0                     |                Cb1
    #
    #                                        _________                               _________
    #   ena_Cr    __________________________|         |_____________________________|         |______________
    #
    #
    #   Cr                               * * *        |               Cr0                     |          Cr1
    #
    #
    #   Nota : La frecuencia de ena_Y es la mitad de clk27_i y la frec de ena_Cx es la mitad de ena_Y
    #

    gen_ena_Y = FT_R(
        clk_i=clk27_i, rst_i=sav, t_i=Signal(Hi), q_o=ena_Y
    )  # Divide por 2 la frec de clk comenzando en bajo luego de sav

    reg_Y = FD_E(clk_i=clk27_i, ce_i=ena_Y, d_i=data_i,
                 q_o=Y)  # Registro la luma

    gen_ena_Y_2 = FT_S(
        clk_i=clk27_i, set_i=sav, t_i=ena_Y, q_o=ena_Y_2
    )  # Divide por 2 la frec de ena_Y comenzando en alto luego de sav

    @always_comb
    def gen_ena_Cb():
        ena_Cb.next = ena_Y_2 and (not ena_Y)  # Arma ena_Cb

    reg_Cb = FD_E(clk_i=clk27_i, ce_i=ena_Cb, d_i=data_i,
                  q_o=Cb)  # Registro la croma

    gen_ena_Cb_q = FD(clk_i=clk27_i, d_i=ena_Cb, q_o=ena_Cb_q)

    gen_ena_Cr = FD(
        clk_i=clk27_i, d_i=ena_Cb_q,
        q_o=ena_Cr)  # Demora la senal ena_Cb 2 clocks para generar ena_Cr

    reg_Cr = FD_E(clk_i=clk27_i, ce_i=ena_Cr, d_i=data_i,
                  q_o=Cr_o)  # Registro la croma

    # Ahora para acomodar temporalmente Y, Cb, Cr aplico el delay necesario a cada una
    # Cr : sin delay
    # Y  : 1 clk de delay
    # Cb : 2 clk de delay

    out_Y = FD(clk_i=clk27_i, d_i=Y, q_o=Y_o)

    q_Cb = FD(clk_i=clk27_i, d_i=Cb, q_o=Cb_q)

    out_Cb = FD(clk_i=clk27_i, d_i=Cb_q, q_o=Cb_o)

    #######################################################################
    ### Generacion de las coordenadas del pixel actual
    #
    #             _      ____      ____      ____      ____      ____      ____      ____      ____      ____
    #   clk27_i    |____|    |____|    |____|    |____|    |____|    |____|    |____|    |____|    |____|    |
    #
    #               ____
    #   sav       _|    |____________________________________________________________________________________
    #
    #                              _________           _________            ________           ________
    #   ena_Y     * * * |_________|         |_________|         |__________|        |_________|        |_____
    #
    #
    #   Y                * * * * * *        |        Y0         |       Y1          |       Y2         |   Y3
    #
    #                                        _________           _________            ________           ____
    #   ena_x                     |_________|         |_________|         |__________|        |_________|
    #
    #
    #   Y_o                             * * *         |        Y0         |       Y1          |       Y2
    #
    #                                        _________
    #   rst_x       ________________________|         |______________________________________________________
    #
    #   pixel_x        862        |       863         |         0         |        1          |        2

    gen_sav_q1 = FD(clk_i=clk27_i, d_i=sav, q_o=sav_q1)

    gen_sav_q2 = FD(clk_i=clk27_i, d_i=sav_q1, q_o=sav_q2)

    gen_rst_x = FD(clk_i=clk27_i, d_i=sav_q2, q_o=rst_x)

    gen_ena_x = FD(clk_i=clk27_i, d_i=ena_Y, q_o=ena_x)

    gen_pos_x = CB_RE(clk_i=clk27_i, rst_i=rst_x, ce_i=ena_x,
                      q_o=pos_x)  # Contador para la coordenada X

    ####################################################################################
    #
    #   data_i             |   FF    |   00    |    00   |    XY   |   Cb    |   Y0    |
    #
    #                      |                  EAV                  |    H Blank
    #                  ____      ____      ____      ____      ____      ____      ____
    #   clk27_i    ___|    |____|    |____|    |____|    |____|    |____|    |____|    |
    #                                                          _________________________
    #   odd_even   ___________________________________________|
    #                                                     ____
    #   eav        ______________________________________|    |_________________________
    #                                                     ____
    #   n_f        ______________________________________|    |_________________________
    #                                                     ____
    #   rst_y      ______________________________________|    |_________________________

    gen_odd_even = FD_E(clk_i=clk27_i, ce_i=eav, d_i=n_f, q_o=odd_even)

    @always_comb
    def gen_rst_y():
        rst_y.next = not odd_even and eav and n_f

    gen_nro_linea = CB_RE(clk_i=clk27_i, rst_i=rst_y, ce_i=eav, q_o=nro_linea)

    gen_video_activo_y = FD_E(clk_i=clk27_i,
                              ce_i=eav,
                              d_i=v,
                              q_o=video_activo_y)

    @always(pos_x)
    def gen_video_activo_x():
        if pos_x < PIXELS_x_LINEA_ACTIVA:
            video_activo_x.next = Hi
        else:
            video_activo_x.next = Lo

    @always(pos_x, video_activo_x)
    def gen_pixel_x():
        if video_activo_x:
            pixel_x_o.next = pos_x
        else:
            pixel_x_o.next = 0

    @always(clk27_i.posedge)
    def gen_pixel_y():
        if video_activo_y:
            if odd_even:
                pixel_y_o.next = (
                    nro_linea - LINEA_INI_VIDEO_ACTIVO_ODD
                ) * 2  # el "* 2" es debido al barrido entrelazado y el campo impar tiene la primer linea
            else:
                pixel_y_o.next = (
                    nro_linea - LINEA_INI_VIDEO_ACTIVO_EVEN
                ) * 2 + 1  # el + 1 es porque el campo par tiene la segunda linea
        else:
            pixel_y_o.next = 0

    @always_comb
    def gen_pix_ena():
        pix_ena_o.next = ena_x

    @always_comb
    def gen_video_activo():
        video_activo_o.next = video_activo_x and video_activo_y

    ######################################################################################
    ### Generacion de ini_frame

    gen_ena_aux = FJK(clk_i=clk27_i, j_i=rst_y, k_i=ini_frame, q_o=ena_aux)

    @always_comb
    def gen_ena_ini_frame():
        ena_ini_frame.next = ena_x and ena_aux

    @always_comb
    def gen_rst_ini_frame():
        rst_ini_frame.next = rst_y or ini_frame

    cont_ini_frame = CB_RE(clk_i=clk27_i,
                           rst_i=rst_ini_frame,
                           ce_i=ena_ini_frame,
                           q_o=cuenta_ini_frame)

    @always(cuenta_ini_frame)
    def gen_ini_frame():
        if cuenta_ini_frame == 15:  # pixels despues del ultimo activo cae el sincronismo
            ini_frame.next = Hi
        else:
            ini_frame.next = Lo

    @always_comb
    def conex_ini_frame():
        ini_frame_o.next = ini_frame

    return instances()
Exemple #8
0
def UART_TX(clk_i, rst_i, ini_tx_i, dato_i, tx_o, fin_tx_o, CLK_FREC_Hz,
            BAUDIOS):
    """Modulo transmisor de : 8 bits de datos, sin paridad y 1 bit de stop

    Unidad de control

    .. graphviz::
        digraph { node [ color=lightblue2, style=filled ];
                  ESPERA_INI -> ESPERA_INI ;
                  ESPERA_INI -> TRANSM [ label = "ini" ];
                  TRANSM -> FIN;
                  FIN -> ESPERA_INI; }

    """

    TICKS_BIT = int(round(CLK_FREC_Hz /
                          BAUDIOS))  # Duracion de un bit en ciclos de reloj

    TICKS_BIT_CMP = TICKS_BIT - 1  # Para que la comparacion n la convierta a "resize(signed.."

    SIZE_PAQ = len(dato_i) + 2  # Tamano del paquete a enviar

    SIZE_PAQ_CMP = SIZE_PAQ - 1  # Para que la comparacion n la convierta a "resize(signed.."

    dato_paq = Signal(intbv(0)[SIZE_PAQ:])  # El dato empaquetado

    bits_enviados = Signal(intbv(0, 0,
                                 SIZE_PAQ + 1))  # Cantidad de bits enviados

    ticks = Signal(intbv(0, 0, TICKS_BIT + 1))

    tx = Signal(Lo)

    e = enum("ESPERA_INI", "TRANSIMITIR", "FIN")
    estado = Signal(e.ESPERA_INI)

    # Senales de control
    rst = Signal(Hi)
    carga_dato = Signal(Lo)
    envia_bit = Signal(Lo)
    fin_envio = Signal(Lo)
    idle = Signal(Hi)
    contar_bits = Signal(Lo)
    rst_ticks = Signal(Lo)
    fin_ticks = Signal(Lo)

    # Datapath

    @always_comb
    def paquete(
    ):  # Arma el paquete con los bits de start, los datos y el stop
        dato_paq.next = concat(Hi, dato_i, Lo)

    tx_reg = SR_LE_PiSo_Der(clk_i=clk_i,
                            load_i=carga_dato,
                            d_i=dato_paq,
                            ce_i=envia_bit,
                            q_o=tx)  # Shift register para enviar el paquete

    @always_comb
    def conex_salida():
        tx_o.next = tx | idle  # Cuando no se envia nada, la linea permanece en alto (estado idle)

    contador_bits = CB_RE(clk_i=clk_i,
                          rst_i=rst,
                          ce_i=contar_bits,
                          q_o=bits_enviados)  # Cuenta los bits enviados

    @always(bits_enviados)
    def comp_fin_envio(
    ):  # Comparador que determina cuando se enviaron todos los bits
        if bits_enviados == SIZE_PAQ_CMP:
            fin_envio.next = Hi
        else:
            fin_envio.next = Lo

    contador_ticks = CB_R(
        clk_i=clk_i, rst_i=rst_ticks,
        q_o=ticks)  # Cuenta ciclos de reloj para saber la duracion de un bit

    @always(ticks)
    def comp_ticks():
        if ticks == TICKS_BIT_CMP:
            fin_ticks.next = Hi
        else:
            fin_ticks.next = Lo

    # Unidad de control
    @always(clk_i.posedge)
    def FSM_estados():
        """Logica del estado siguiente"""
        if rst_i:
            estado.next = e.ESPERA_INI

        else:
            ###########################
            if estado == e.ESPERA_INI:
                if ini_tx_i:
                    estado.next = e.TRANSIMITIR
            ###########################
            elif estado == e.TRANSIMITIR:
                if fin_envio and fin_ticks:
                    estado.next = e.FIN
            ###########################
            elif estado == e.FIN:
                estado.next = e.ESPERA_INI

            else:
                estado.next = e.ESPERA_INI

    @always(estado, ini_tx_i, fin_envio, fin_ticks)
    def FSM_salidas():
        """Logica combinacional de salida"""
        ###########################
        if estado == e.ESPERA_INI:
            fin_tx_o.next = Lo
            idle.next = Hi
            contar_bits.next = Lo
            rst.next = Hi
            rst_ticks.next = Hi
            envia_bit.next = Lo
            if ini_tx_i:
                carga_dato.next = Hi
            else:
                carga_dato.next = Lo
        ###########################
        elif estado == e.TRANSIMITIR:
            fin_tx_o.next = Lo
            carga_dato.next = Lo
            idle.next = Lo
            rst.next = Lo
            if fin_ticks:
                envia_bit.next = Hi
                contar_bits.next = Hi
                rst_ticks.next = Hi
            else:
                envia_bit.next = Lo
                contar_bits.next = Lo
                rst_ticks.next = Lo
        ###########################
        elif estado == e.FIN:
            fin_tx_o.next = Hi
            carga_dato.next = Lo
            idle.next = Hi
            contar_bits.next = Lo
            rst.next = Lo
            rst_ticks.next = Lo
            envia_bit.next = Lo

        else:
            fin_tx_o.next = Lo
            carga_dato.next = Lo
            idle.next = Hi
            contar_bits.next = Lo
            rst.next = Hi
            rst_ticks.next = Lo
            envia_bit.next = Lo

    return instances()
Exemple #9
0
def UART_RX(clk_i, rst_i, rx_i, dato_o, fin_rx_o, CLK_FREC_Hz, BAUDIOS):
    """Modulo receptor de : 8 bits de datos, sin paridad y 1 bit de stop

    Unidad de control

    .. graphviz::
        digraph { node [ color=lightblue2, style=filled ];
                  ESPERA_START -> ESPERA_START ;
                  ESPERA_START -> VERIF_START [ label = "RX == 0" ];
                  VERIF_START -> RECIBIR [ label = "medio_bit == 0" ];
                  VERIF_START -> ESPERA_START
                  RECIBIR -> VERIF_STOP [ label = "leyo 8bits" ];
                  VERIF_STOP -> FIN [label = "medio_bit == 1" ];
                  FIN -> ESPERA_START; }


    """

    TICKS_BIT = int(round(CLK_FREC_Hz /
                          BAUDIOS))  # Duracion de un bit en ciclos de reloj
    TICKS_MEDIO_BIT = int(round(CLK_FREC_Hz / BAUDIOS /
                                2))  # Duracion de medio bit en ciclos de reloj

    TICKS_BIT_CMP = TICKS_BIT - 1
    TICKS_MEDIO_BIT_CMP = TICKS_MEDIO_BIT - 1

    n = len(dato_o)

    SIZE_DATO_CMP = n - 1

    rx = Signal(Lo)

    dato_leido = Signal(intbv(0)[n:])
    bits_leidos = Signal(intbv(0, 0, n + 1))  # Cantidad de bits leidos

    ticks = Signal(intbv(0, 0, TICKS_BIT + 1))

    e = enum("ESPERA_START", "VERIF_START", "RECIBIR", "VERIF_STOP", "FIN")
    estado = Signal(e.ESPERA_START)

    # Senales de control
    rst = Signal(Lo)
    rst_ticks = Signal(Lo)
    lee_bit = Signal(Lo)
    contar_bits = Signal(Lo)
    fin_ticks = Signal(Lo)
    ticks_medio_bit = Signal(Lo)
    rst_ticks = Signal(Lo)
    fin_recepcion = Signal(Lo)
    dato_ok = Signal(Lo)

    reg_in = FD(clk_i=clk_i, d_i=rx_i,
                q_o=rx)  # Para tener la entrada sincronizada

    rx_reg = SR_RE_SiPo_Der(clk_i=clk_i,
                            rst_i=rst,
                            ce_i=lee_bit,
                            sr_i=rx,
                            q_o=dato_leido)

    reg_out = FD_E(clk_i=clk_i, ce_i=dato_ok, d_i=dato_leido, q_o=dato_o)

    contador_bits = CB_RE(clk_i=clk_i,
                          rst_i=rst,
                          ce_i=contar_bits,
                          q_o=bits_leidos)  # Cuenta los bits leidos

    @always(bits_leidos)
    def comp_fin_recepcion():
        if bits_leidos == SIZE_DATO_CMP:
            fin_recepcion.next = Hi
        else:
            fin_recepcion.next = Lo

    contador_ticks = CB_R(
        clk_i=clk_i, rst_i=rst_ticks,
        q_o=ticks)  # Cuenta ciclos de reloj para saber la duracion de un bit

    @always(ticks)
    def comp_ticks():
        if ticks == TICKS_BIT_CMP:
            fin_ticks.next = Hi
        else:
            fin_ticks.next = Lo

        if ticks == TICKS_MEDIO_BIT_CMP:
            ticks_medio_bit.next = Hi
        else:
            ticks_medio_bit.next = Lo

    # Unidad de control del modulo RX

    @always(clk_i.posedge)
    def FSM_estados():
        """Logica de cambio de estados"""
        if rst_i:
            estado.next = e.ESPERA_START
        else:
            #############################
            if estado == e.ESPERA_START:
                if not rx:  # Cuando la linea de Rx baja empieza el proceso
                    estado.next = e.VERIF_START
            #############################
            elif estado == e.VERIF_START:
                if ticks_medio_bit:  # Me paro en la mitad del bit de start para chequear que no haya sido un falso start
                    if not rx:
                        estado.next = e.RECIBIR  # Start Bit OK
                    else:
                        estado.next = e.ESPERA_START  # Falso Start Bit
            #############################
            elif estado == e.RECIBIR:
                if fin_recepcion and fin_ticks:
                    estado.next = e.VERIF_STOP
            #############################
            elif estado == e.VERIF_STOP:
                if fin_ticks:
                    if rx:  # Bit de stop OK
                        estado.next = e.FIN
                    else:
                        estado.next = e.ESPERA_START  # Error en el bit de stop, vuelve e empezar
            #############################
            elif estado == e.FIN:
                estado.next = e.ESPERA_START

            else:
                estado.next = e.ESPERA_START

    @always(estado, ticks_medio_bit, fin_ticks, rx)
    def FSM_salidas():
        """Logica combinacional de salida"""
        #############################
        if estado == e.ESPERA_START:
            contar_bits.next = Lo
            rst.next = Hi
            rst_ticks.next = Hi
            lee_bit.next = Lo
            fin_rx_o.next = Lo
            dato_ok.next = Lo
        #############################
        elif estado == e.VERIF_START:
            dato_ok.next = Lo
            fin_rx_o.next = Lo
            contar_bits.next = Lo
            rst.next = Lo
            lee_bit.next = Lo
            if ticks_medio_bit:
                rst_ticks.next = Hi
            else:
                rst_ticks.next = Lo
        #############################
        elif estado == e.RECIBIR:
            dato_ok.next = Lo
            fin_rx_o.next = Lo
            rst.next = Lo
            if fin_ticks:
                lee_bit.next = Hi
                contar_bits.next = Hi
                rst_ticks.next = Hi
            else:
                rst_ticks.next = Lo
                lee_bit.next = Lo
                contar_bits.next = Lo
        #############################
        elif estado == e.VERIF_STOP:
            dato_ok.next = Lo
            fin_rx_o.next = Lo
            contar_bits.next = Lo
            rst.next = Lo
            lee_bit.next = Lo
            if fin_ticks:
                rst_ticks.next = Hi
                if rx:
                    dato_ok.next = Hi
                else:
                    dato_ok.next = Lo
            else:
                rst_ticks.next = Lo
                dato_ok.next = Lo
        #############################
        elif estado == e.FIN:
            dato_ok.next = Lo
            contar_bits.next = Lo
            rst.next = Hi
            rst_ticks.next = Hi
            lee_bit.next = Lo
            fin_rx_o.next = Hi

        else:
            dato_ok.next = Lo
            contar_bits.next = Lo
            rst.next = Hi
            rst_ticks.next = Hi
            lee_bit.next = Lo
            fin_rx_o.next = Lo

    return instances()