2018-12-08 12:35:48 +00:00
|
|
|
|
2018-02-15 18:31:32 +00:00
|
|
|
`include "hvsync_generator.v"
|
2018-02-19 00:19:20 +00:00
|
|
|
`include "cpu16.v"
|
2018-02-15 18:31:32 +00:00
|
|
|
|
|
|
|
module frame_buffer_top(clk, reset, hsync, vsync, hpaddle, vpaddle,
|
2018-11-12 19:13:17 +00:00
|
|
|
address_bus, to_cpu, from_cpu, write_enable,
|
|
|
|
rgb
|
2018-02-15 18:31:32 +00:00
|
|
|
);
|
|
|
|
|
|
|
|
input clk, reset;
|
|
|
|
input hpaddle, vpaddle;
|
|
|
|
output hsync, vsync;
|
|
|
|
wire display_on;
|
|
|
|
wire [8:0] hpos;
|
|
|
|
wire [8:0] vpos;
|
2021-06-28 20:36:47 +00:00
|
|
|
output reg [3:0] rgb;
|
2018-02-15 18:31:32 +00:00
|
|
|
|
2018-11-12 19:13:17 +00:00
|
|
|
reg [15:0] ram[0:32767]; // RAM (32768 x 16 bits)
|
|
|
|
reg [15:0] rom[0:1023]; // ROM (1024 x 16 bits)
|
2018-02-15 18:31:32 +00:00
|
|
|
|
2018-11-12 19:13:17 +00:00
|
|
|
// 16-bit CPU
|
2018-02-19 00:19:20 +00:00
|
|
|
output wire [15:0] address_bus;
|
|
|
|
output reg [15:0] to_cpu;
|
|
|
|
output wire [15:0] from_cpu;
|
2018-02-15 18:31:32 +00:00
|
|
|
output wire write_enable;
|
|
|
|
|
2018-02-19 00:19:20 +00:00
|
|
|
CPU16 cpu(.clk(clk),
|
2018-02-15 18:31:32 +00:00
|
|
|
.reset(reset),
|
2018-02-19 00:19:20 +00:00
|
|
|
.hold(hold),
|
|
|
|
.busy(busy),
|
2018-02-15 18:31:32 +00:00
|
|
|
.address(address_bus),
|
|
|
|
.data_in(to_cpu),
|
|
|
|
.data_out(from_cpu),
|
|
|
|
.write(write_enable));
|
|
|
|
|
2018-11-12 19:13:17 +00:00
|
|
|
// CPU -> RAM write bus (synchronous)
|
2018-02-15 18:31:32 +00:00
|
|
|
always @(posedge clk)
|
|
|
|
if (write_enable) begin
|
2018-02-19 00:19:20 +00:00
|
|
|
ram[address_bus[14:0]] <= from_cpu;
|
2018-02-15 18:31:32 +00:00
|
|
|
end
|
|
|
|
|
2018-11-12 19:13:17 +00:00
|
|
|
// RAM -> CPU read bus (asynchronous)
|
2018-02-15 18:31:32 +00:00
|
|
|
always @(*)
|
2018-02-19 00:19:20 +00:00
|
|
|
if (address_bus[15])
|
|
|
|
to_cpu = rom[address_bus[9:0]];
|
2018-11-12 19:13:17 +00:00
|
|
|
else
|
2018-02-19 00:19:20 +00:00
|
|
|
to_cpu = ram[address_bus[14:0]];
|
2018-02-15 18:31:32 +00:00
|
|
|
|
2018-11-12 19:13:17 +00:00
|
|
|
// video sync generator
|
2018-02-15 18:31:32 +00:00
|
|
|
hvsync_generator hvsync_gen(
|
|
|
|
.clk(clk),
|
|
|
|
.reset(0),
|
|
|
|
.hsync(hsync),
|
|
|
|
.vsync(vsync),
|
|
|
|
.display_on(display_on),
|
|
|
|
.hpos(hpos),
|
|
|
|
.vpos(vpos)
|
|
|
|
);
|
2018-02-19 00:19:20 +00:00
|
|
|
|
2018-11-12 19:13:17 +00:00
|
|
|
// CPU busy flags (not used here)
|
|
|
|
reg hold = 0;
|
2018-02-19 00:19:20 +00:00
|
|
|
wire busy;
|
2018-11-12 19:13:17 +00:00
|
|
|
|
|
|
|
reg [12:0] vindex; // index into line array
|
2018-07-15 04:29:27 +00:00
|
|
|
reg [15:0] vshift; // shift register with current word to output
|
2018-11-12 19:13:17 +00:00
|
|
|
reg [3:0] palette[0:3] = '{0,1,4,7}; // simple palette array
|
2018-02-15 18:31:32 +00:00
|
|
|
|
|
|
|
always @(posedge clk) begin
|
2018-11-12 19:13:17 +00:00
|
|
|
if (display_on) begin
|
|
|
|
// load next word from RAM every 8 pixels
|
2018-02-19 00:19:20 +00:00
|
|
|
if (0 == hpos[2:0]) begin
|
2018-11-12 19:13:17 +00:00
|
|
|
vshift <= ram[{2'b10,vindex}];
|
2018-02-19 00:19:20 +00:00
|
|
|
vindex <= vindex + 1;
|
|
|
|
end else
|
2018-11-12 19:13:17 +00:00
|
|
|
vshift <= vshift << 2; // shift next pixel in 16-bit word
|
2018-02-19 00:19:20 +00:00
|
|
|
// decode scanline RAM to RGB output
|
2018-11-12 19:13:17 +00:00
|
|
|
rgb <= palette[vshift[15:14]];
|
|
|
|
end else begin
|
|
|
|
rgb <= 0; // set color to black
|
|
|
|
if (vsync) vindex <= 0; // reset vindex every frame
|
|
|
|
end;
|
2018-02-15 18:31:32 +00:00
|
|
|
end
|
|
|
|
|
2018-11-12 19:13:17 +00:00
|
|
|
// test program
|
|
|
|
|
2018-02-15 18:31:32 +00:00
|
|
|
`ifdef EXT_INLINE_ASM
|
|
|
|
initial begin
|
|
|
|
rom = '{
|
|
|
|
__asm
|
2018-02-19 00:19:20 +00:00
|
|
|
.arch femto16
|
|
|
|
.org 32768
|
|
|
|
.len 1024
|
2018-02-15 18:31:32 +00:00
|
|
|
|
|
|
|
Start:
|
2018-11-12 19:13:17 +00:00
|
|
|
mov ax,cx ; ax = cx
|
|
|
|
mov bx,#0 ; bx = #0
|
2018-02-19 00:19:20 +00:00
|
|
|
Loop:
|
2018-11-12 19:13:17 +00:00
|
|
|
mov [bx],ax ; ram[bx] = ax
|
|
|
|
inc ax ; ax = ax + 1
|
|
|
|
inc bx ; bx = bx + 1
|
|
|
|
bnz Loop ; loop until bx is 0
|
|
|
|
inc cx
|
|
|
|
reset ; reset CPU
|
2018-02-15 18:31:32 +00:00
|
|
|
__endasm
|
|
|
|
};
|
|
|
|
end
|
|
|
|
`endif
|
|
|
|
|
|
|
|
endmodule
|