§ Описание пинов
Вообще, я хочу создать процессор, который бы что-то умел делать в самом базовом варианте. Ранее я уже писал процессор в виде статей и даже вел стримы по этому поводу, но мне хочется попробовать сделать еще раз что-нибудь похожее на простой 8080. Устройство этого процессора крайне простое, так что мне хотелось бы его сделать.Начну вообще с того, что попробую описать пины, контакты и даже группы контактов совершенно стандартными способом.
module T8080 ( input clk, // Тактовая частота input rstn, // RST=0 сброс input ce, // CE=1 активация output [15:0] a, // Адрес input [ 7:0] i, // Прочитанные данные output reg [ 7:0] o, // Для записи output reg w // Сигнал записи ); endmoduleПредставленная выше схема является минимальной обвязкой для процессора, ну разве что что можно обойтись без
rstn, ce
. Тут особо и не нужно объяснений. Адресная шина 16 бит, шина данных 8 бит, причем, не мультиплексированная, как обычно бывает, а разделенная — имеется вход и выход. Так как система на чипе, то имеются внутренние блоки памяти, которые позволяют даже использовать двухпортовый доступ к данным, читая сразу одновременно с двух источников.§ Шаблон приложения для верилятора
Также я заготовил некоторый код, который везде делаю, для того чтобы проверить, как будет работать цифровая схема, используя вериляцию, то есть, перевод из VERILOG в код на C/C++.#include <SDL2/SDL.h> #include <verilated.h> // ---------------------------------------------------- SDL_Surface* screen_surface; SDL_Window* sdl_window; SDL_Renderer* sdl_renderer; SDL_PixelFormat* sdl_pixel_format; SDL_Texture* sdl_screen_texture; SDL_Event evt; Uint32* screen_buffer; SDL_Rect dstRect; // ---------------------------------------------------- int scale = 2; int width = 640; int height = 400; int length = 16; int _hs = 0, _vs = 0; int x = 0, y = 0; // ---------------------------------------------------- void pset(int, int, Uint32); void vga(int, int, int); int main(int argc, char** argv) { int pticks = 0; if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO)) { exit(1); } SDL_ClearError(); sdl_window = SDL_CreateWindow("T8080 VEMULATOR", \ SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, \ scale*width, scale*height, SDL_WINDOW_SHOWN); sdl_renderer = SDL_CreateRenderer(sdl_window, -1, SDL_RENDERER_PRESENTVSYNC); screen_buffer = (Uint32*) malloc(width*height*sizeof(Uint32)); sdl_screen_texture = SDL_CreateTexture(sdl_renderer, \ SDL_PIXELFORMAT_BGRA32, \ SDL_TEXTUREACCESS_STREAMING, \ width, height); SDL_SetTextureBlendMode(sdl_screen_texture, SDL_BLENDMODE_NONE); dstRect.x = 0; dstRect.y = 0; dstRect.w = scale * width; dstRect.h = scale * height; for (;;) { // Прием событий while (SDL_PollEvent(& evt)) { switch (evt.type) { // Выход из приложения case SDL_QUIT: free(screen_buffer); SDL_DestroyTexture(sdl_screen_texture); SDL_FreeFormat(sdl_pixel_format); SDL_DestroyRenderer(sdl_renderer); SDL_DestroyWindow(sdl_window); SDL_Quit(); return 0; } } int nticks = SDL_GetTicks(); // Обновление экрана if (nticks - pticks >= length) { pticks = nticks; SDL_UpdateTexture(sdl_screen_texture,NULL,screen_buffer,width*sizeof(Uint32)); SDL_SetRenderDrawColor (sdl_renderer, 0, 0, 0, 0); SDL_RenderClear (sdl_renderer); SDL_RenderCopy (sdl_renderer, sdl_screen_texture, NULL, & dstRect); SDL_RenderPresent (sdl_renderer); } SDL_Delay(1); } } // Установка точки void pset(int x, int y, Uint32 cl) { if (x < 0 || y < 0 || x >= width || y >= height) { return; } screen_buffer[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); }