Блог страдающего Лиса
Lorem ipsum hello dolor sit world amet

23 окт 2024 Ср Нарисовать шахматную доску в перспективе

У меня есть одна демка, это "шахматка", она основана на принципе:
t.x = x / y
t.y = H / y
Вот тут t.x и t.y это точки текстуры, а H — высота над шахматной доской, x меняется от -160 до 160 (для экрана 320 пикселей по ширине), y меняется от 1 до 100, где y=1 самая дальняя точка перспективы, а y=100 ближняя.
kxrjyv-shahmat.png
Вот так эта программа пока что выглядит на Quick Basic 4.5. Моя же задача в том, чтобы использовать только одно деление, причем, это деление будет выполнено как серия вычитаний (и еще одно сложение), и выдать тоже самое на экране со скоростью 25 мгц. Я думаю, что у меня это может получиться.
Как я и говорил ранее, при ширине линии 800 пикселей я могу даже увеличить размеры поля, использовать не только 320, но и 800, но делать так, конечно, пока не буду. Сначала, вывод на экран без использования памяти и любых блоков DSP. Чистый хардкор, как в детстве.
У меня есть идеи на небольшие демки и мне хочется их показывать и рассказывать и я буду это делать в этом великолепном блоге.
Программа
У меня получилось сделать программу для верилятора, которая выдает точно такую же картинку, какую я изобразил ранее. Я весь код приводить тут не буду, только ядро алгоритма.
always @(posedge clock) begin

    // Вычисление текстуры XOR
    if (rx >= ry) begin rx <= rx + 1 - ry; tx <= tx + 1; end
    else          begin rx <= rx + 1; end

    // ----------------
    // Инициализация [на первой точки вывода]
    if (X == hzb) begin

        A <= 320;
        B <= Y - (199 + vtb);
        C <= 0;

    end
    // Запись результата [перед тем как начать выводить на экран]
    else if (X == hzb-1) begin

        tx <= C[0];
        ty <= C[0];
        rx <= (B - 1) - A;
        ry <= B;

    end
    // Деление числа A : B => C (остаток A)
    else begin if (A >= B) begin A <= A - B; C <= C + 1; end end
    // ----------------

    // Вывод окна видеоадаптера
    if (X >= hzb && X < hzb+hzv && Y >= vtb && Y < vtb+vtv)
    {r, g, b} <= Y > (200 + vtb) && (tx ^ ty) ? 3'b111 : 3'b000;

end
Объяснить тут как она работает, я не могу, потому что сложно. Вся фишка в делении, которое представляет собой тут просто серию вычитаний: if (A >= B) begin A <= A - B; C <= C + 1; end. Здесь A-делимое, B-делитель, C-результат, а в конце деления получается остаток. Деление это происходить может с разной скоростью. Например, разделить 320 на 200 займет всего 1 такт, а 320 на 8 уже 40 тактов. Но, поскольку ширина строки все равно 800, а результат всегда меньше 320, то поделить всегда получится подобным макаром.
Для процессора EPM570 это заняло только 150 LE, то есть, этот код влазит даже в EPM240.
Теги: Демо