§ Описание пинов
Вообще, я хочу создать процессор, который бы что-то умел делать в самом базовом варианте. Ранее я уже писал процессор в виде статей и даже вел стримы по этому поводу, но мне хочется попробовать сделать еще раз что-нибудь похожее на простой 8080. Устройство этого процессора крайне простое, так что мне хотелось бы его сделать.
Начну вообще с того, что попробую описать пины, контакты и даже группы контактов совершенно стандартными способом.
module T8080
(
input clk,
input rstn,
input ce,
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;
}
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);
}