§ Шаблон для верилятора

Стандартный код.
Скачать шаблон в формате ZIP
#include <SDL2/SDL.h>
#include <verilated.h>
#include "obj_dir/Vvideo.h"
// КОНСТАНТЫ -------------------------------------------------------------------
#define WIDTH  640
#define HEIGHT 480
// КЛАССЫ ----------------------------------------------------------------------
SDL_Surface*        surface;
SDL_Window*         window;
SDL_Renderer*       renderer;
SDL_Texture*        texture;
SDL_Event           evt;
SDL_Rect            dstRect;
Uint32*             screen;
// МОДУЛИ ----------------------------------------------------------------------
Vvideo*             video;
// ПЕРЕМЕННЫЕ ------------------------------------------------------------------
int length = 20, x = 0, y = 0, _hs = 1, _vs = 0;
// ПРОТОТИПЫ -------------------------------------------------------------------
void pset(int x, int y, Uint32 cl);
void vga(int hs, int vs, int cl);
// -----------------------------------------------------------------------------
void tick()
{
    video->clock = 0; video->eval();
    video->clock = 1; video->eval();

    vga(video->hs, video->vs, video->r*16*65536 + video->g*16*256 + video->b*16);
}
// -----------------------------------------------------------------------------
int main(int argc, char** argv)
{
    SDL_ClearError();
    Verilated::commandArgs(argc, argv);

    // Создание модулей
    video = new Vvideo;

    // Инициализация
    int pticks = 0, nticks;
    int wincen = SDL_WINDOWPOS_CENTERED;
    int pixfmt = SDL_PIXELFORMAT_BGRA32;
    int pixstm = SDL_TEXTUREACCESS_STREAMING;
    int presyn = SDL_RENDERER_PRESENTVSYNC;
    int wshown = SDL_WINDOW_SHOWN;

    dstRect.x = 0;
    dstRect.y = 0;
    dstRect.w = 2*WIDTH;
    dstRect.h = 2*HEIGHT;

    if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO)) {
        exit(1);
    }

    // Открыть окно SDL
    window   = SDL_CreateWindow("Vemulator",wincen,wincen,dstRect.w,dstRect.h,wshown);
    renderer = SDL_CreateRenderer(window,-1,presyn);
    screen   = (Uint32*) malloc(WIDTH*HEIGHT*sizeof(Uint32));
    texture  = SDL_CreateTexture(renderer,pixfmt,pixstm,WIDTH,HEIGHT);
    SDL_SetTextureBlendMode(texture,SDL_BLENDMODE_NONE);

    for (;;) {

        int count = 0;

        // Прием событий
        while (SDL_PollEvent(& evt)) {

            switch (evt.type) {

                // Событие выхода
                case SDL_QUIT:

                    free(screen);
                    SDL_DestroyTexture  (texture);
                    SDL_DestroyRenderer (renderer);
                    SDL_DestroyWindow   (window);
                    SDL_Quit();
                    return 0;
            }
        }

        // Выполнение фрейма длиной <frame_length>: ms.
        do {
            for (int i = 0; i < 8192; i++) tick();
            nticks = SDL_GetTicks();
        }
        while ((nticks - pticks) <= length);

        pticks = nticks;
        SDL_UpdateTexture       (texture, NULL, screen, WIDTH*sizeof(Uint32));
        SDL_SetRenderDrawColor  (renderer, 0, 0, 0, 0);
        SDL_RenderClear         (renderer);
        SDL_RenderCopy          (renderer, texture, NULL, & dstRect);
        SDL_RenderPresent       (renderer);
        SDL_Delay(1);
    }
}

// Установка точки
void pset(int x, int y, Uint32 cl)
{
    if (x < 0 || y < 0 || x >= WIDTH || y >= HEIGHT) {
        return;
    }

    screen[WIDTH*y + x] = cl;
}

// Отслеживание сигнала RGB по HS/VS
void vga(int hs, int vs, int cl)
{
    if (hs) x++;
    if (_hs == 1 && hs == 0) { x = 0; y++; }
    if (_vs == 0 && vs == 1) { y = 0; }
    _hs = hs;
    _vs = vs;
    pset(x-(48+2), y-33, cl);
}

§ makefile

Подключение видеоадаптера video 640 на 480 для тестирования.
VLIB="/usr/share/verilator/include"
COMM=$(VLIB)/verilated_threads.cpp $(VLIB)/verilated.cpp
MODS=obj_dir/Vvideo__ALL.a

all: app
	./main
app: syn
	g++ -o main -I$(VLIB) main.cc -lSDL2 $(COMM) $(MODS)
syn: video.v
	verilator --threads 1 -cc video.v > /dev/null
	cd obj_dir && make -f Vvideo.mk > /dev/null
clean:
	rm -r obj_dir tb

§ video.v

Тестовый модуль.
/* verilator lint_off WIDTH */

module video
(
    input   wire        clock,
    output  reg [3:0]   r,
    output  reg [3:0]   g,
    output  reg [3:0]   b,
    output  wire        hs,
    output  wire        vs
);
// Тайминги для горизонтальной и вертикальной развертки
// ---------------------------------------------------------------------
parameter
//  Visible     Front       Sync        Back        Whole
    hzv =  640, hzf =   16, hzs =   96, hzb =   48, hzw =  800,
    vtv =  480, vtf =   10, vts =    2, vtb =   33, vtw =  525;
// ---------------------------------------------------------------------
assign hs = x < (hzb + hzv + hzf);
assign vs = y < (vtb + vtv + vtf);
// ---------------------------------------------------------------------
wire        xmax = (x == hzw - 1);
wire        ymax = (y == vtw - 1);
reg  [10:0] x    = 0;
reg  [10:0] y    = 0;
// ---------------------------------------------------------------------
always @(posedge clock) begin

    // Кадровая развертка
    x <= xmax ?         0 : x + 1;
    y <= xmax ? (ymax ? 0 : y + 1) : y;
    {r, g, b} <= 12'h000;

    // Вывод окна видеоадаптера
    if (x >= hzb && x < hzb+hzv && y >= vtb && y < vtb+vtv)
    begin
         {r, g, b} <= 12'h008;
    end

end

endmodule