mirror of
https://github.com/sehugg/8bitworkshop.git
synced 2024-11-25 03:34:05 +00:00
more verilog presets
This commit is contained in:
parent
a456f3d9cf
commit
f0f6783f6b
80
presets/verilog/7segment.v
Normal file
80
presets/verilog/7segment.v
Normal file
@ -0,0 +1,80 @@
|
||||
`include "hvsync_generator.v"
|
||||
|
||||
module seven_segment_decoder(digit, segments);
|
||||
input [3:0] digit;
|
||||
output [6:0] segments;
|
||||
|
||||
always @(*)
|
||||
case(digit)
|
||||
0: segments = 7'b1111110;
|
||||
1: segments = 7'b0110000;
|
||||
2: segments = 7'b1101101;
|
||||
3: segments = 7'b1111001;
|
||||
4: segments = 7'b0110011;
|
||||
5: segments = 7'b1011011;
|
||||
6: segments = 7'b1011111;
|
||||
7: segments = 7'b1110000;
|
||||
8: segments = 7'b1111111;
|
||||
9: segments = 7'b1111011;
|
||||
default: segments = 7'b0000000;
|
||||
endcase
|
||||
endmodule
|
||||
|
||||
module segments_to_bitmap(segments, line, bits);
|
||||
input [6:0] segments;
|
||||
input [2:0] line;
|
||||
output [4:0] bits;
|
||||
|
||||
always @(*)
|
||||
case (line)
|
||||
0:bits = (segments[6]?5'b11111:0) ^ (segments[5]?5'b00001:0) ^ (segments[1]?5'b10000:0);
|
||||
1:bits = (segments[1]?5'b10000:0) ^ (segments[5]?5'b00001:0);
|
||||
2:bits = (segments[0]?5'b11111:0) ^ (|segments[5:4]?5'b00001:0) ^ (|segments[2:1]?5'b10000:0);
|
||||
3:bits = (segments[2]?5'b10000:0) ^ (segments[4]?5'b00001:0);
|
||||
4:bits = (segments[3]?5'b11111:0) ^ (segments[4]?5'b00001:0) ^ (segments[2]?5'b10000:0);
|
||||
default:bits = 0;
|
||||
endcase
|
||||
endmodule
|
||||
|
||||
module test_numbers_top(
|
||||
input clk, reset,
|
||||
output hsync, vsync,
|
||||
output [2:0] rgb
|
||||
);
|
||||
wire display_on;
|
||||
wire [8:0] hpos;
|
||||
wire [8:0] vpos;
|
||||
|
||||
hvsync_generator hvsync_gen(
|
||||
.clk(clk),
|
||||
.reset(reset),
|
||||
.hsync(hsync),
|
||||
.vsync(vsync),
|
||||
.display_on(display_on),
|
||||
.hpos(hpos),
|
||||
.vpos(vpos)
|
||||
);
|
||||
|
||||
wire [3:0] digit = hpos[7:4];
|
||||
wire [2:0] xofs = hpos[3:1];
|
||||
wire [2:0] yofs = vpos[3:1];
|
||||
wire [4:0] bits;
|
||||
wire [6:0] segments;
|
||||
|
||||
seven_segment_decoder decoder(
|
||||
.digit(digit),
|
||||
.segments(segments)
|
||||
);
|
||||
|
||||
segments_to_bitmap numbers(
|
||||
.segments(segments),
|
||||
.line(yofs),
|
||||
.bits(bits)
|
||||
);
|
||||
|
||||
wire r = display_on && 0;
|
||||
wire g = display_on && bits[~xofs];
|
||||
wire b = display_on && 0;
|
||||
assign rgb = {b,g,r};
|
||||
|
||||
endmodule
|
@ -13,11 +13,12 @@ module ball_paddle_top(clk, reset, hsync, vsync, rgb);
|
||||
reg [8:0] ball_htimer;
|
||||
reg [8:0] ball_vtimer;
|
||||
|
||||
reg [8:0] ball_horiz_stop = 204;
|
||||
reg [8:0] ball_horiz_move = -2;
|
||||
reg [8:0] ball_vert_stop = 251;
|
||||
reg [8:0] ball_vert_move = 2;
|
||||
|
||||
localparam ball_horiz_stop = 204;
|
||||
localparam ball_vert_stop = 251;
|
||||
|
||||
hvsync_generator hvsync_gen(
|
||||
.clk(clk),
|
||||
.reset(reset),
|
||||
@ -40,7 +41,7 @@ module ball_paddle_top(clk, reset, hsync, vsync, rgb);
|
||||
ball_htimer <= ball_horiz_stop;
|
||||
end else
|
||||
ball_htimer <= ball_htimer + 1;
|
||||
end;
|
||||
end
|
||||
|
||||
// update vertical timer
|
||||
always @(posedge hsync or posedge reset)
|
||||
@ -51,30 +52,33 @@ module ball_paddle_top(clk, reset, hsync, vsync, rgb);
|
||||
ball_vtimer <= ball_vert_stop + ball_vert_move;
|
||||
else
|
||||
ball_vtimer <= ball_vtimer + 1;
|
||||
end;
|
||||
end
|
||||
|
||||
// collide with vertical and horizontal boundaries
|
||||
wire ball_vert_collide = ball_vgfx && vpos >= 240;
|
||||
wire ball_horiz_collide = ball_hgfx && hpos >= 256 && vpos == 255;
|
||||
|
||||
// vertical bounce
|
||||
always @(posedge ball_vert_collide)
|
||||
begin
|
||||
ball_vert_move <= -ball_vert_move;
|
||||
end;
|
||||
end
|
||||
|
||||
// horizontal bounce
|
||||
always @(posedge ball_horiz_collide)
|
||||
begin
|
||||
ball_horiz_move <= -ball_horiz_move;
|
||||
end;
|
||||
end
|
||||
|
||||
// compute ball display
|
||||
wire ball_hgfx = ball_htimer >= 508;
|
||||
wire ball_vgfx = ball_vtimer >= 508;
|
||||
wire ball_gfx = ball_hgfx && ball_vgfx;
|
||||
|
||||
// collide with vertical and horizontal boundaries
|
||||
wire ball_vert_collide = ball_vgfx && vpos >= 240;
|
||||
wire ball_horiz_collide = ball_hgfx && hpos >= 256 && vpos == 255;
|
||||
|
||||
// compute grid display
|
||||
wire grid_gfx = (((hpos&7)==0) && ((vpos&7)==0));
|
||||
|
||||
// combine into RGB signals
|
||||
wire r = display_on && (ball_hgfx | ball_gfx);
|
||||
wire g = display_on && (grid_gfx | ball_gfx);
|
||||
wire b = display_on && (ball_vgfx | ball_gfx);
|
||||
|
198
presets/verilog/cpu8.v
Normal file
198
presets/verilog/cpu8.v
Normal file
@ -0,0 +1,198 @@
|
||||
|
||||
`define OP_LOAD_A 4'h0
|
||||
`define OP_LOAD_B 4'h1
|
||||
`define OP_ADD 4'h2
|
||||
`define OP_SUB 4'h3
|
||||
`define OP_INC 4'h4
|
||||
`define OP_DEC 4'h5
|
||||
`define OP_ASL 4'h6
|
||||
`define OP_LSR 4'h7
|
||||
`define OP_OR 4'h8
|
||||
`define OP_AND 4'h9
|
||||
`define OP_XOR 4'ha
|
||||
|
||||
module ALU(
|
||||
input [7:0] A,
|
||||
input [7:0] B,
|
||||
output [8:0] Y,
|
||||
input [3:0] aluop
|
||||
);
|
||||
|
||||
always @(*)
|
||||
case (aluop)
|
||||
`OP_LOAD_A: Y = {1'b0, A};
|
||||
`OP_LOAD_B: Y = {1'b0, B};
|
||||
`OP_ADD: Y = A + B;
|
||||
`OP_SUB: Y = A - B;
|
||||
`OP_INC: Y = A + 1;
|
||||
`OP_DEC: Y = A - 1;
|
||||
`OP_ASL: Y = {A[7], A + A};
|
||||
`OP_LSR: Y = {A[0], A >> 1};
|
||||
`OP_OR: Y = {1'b0, A | B};
|
||||
`OP_AND: Y = {1'b0, A & B};
|
||||
`OP_XOR: Y = {1'b0, A ^ B};
|
||||
default: Y = 9'bx;
|
||||
endcase
|
||||
|
||||
endmodule
|
||||
|
||||
`define REG_A 1'b0
|
||||
`define REG_B 1'b1
|
||||
`define I_CONST(r,x) { 2'b00, r, x }
|
||||
`define I_LOAD_ADDR(r,addr) { 3'b010, r, addr }
|
||||
`define I_STORE_ADDR(r,addr) { 3'b011, r, addr }
|
||||
`define I_COMPUTE(r,op) { 3'b100, r, op }
|
||||
`define I_RESET 8'hff
|
||||
|
||||
module CPU(
|
||||
input clk,
|
||||
input reset,
|
||||
output [7:0] address,
|
||||
input [7:0] data_in,
|
||||
output [7:0] data_out,
|
||||
output write
|
||||
);
|
||||
|
||||
reg [7:0] ip;
|
||||
reg [7:0] opcode;
|
||||
reg [3:0] aluop;
|
||||
reg [7:0] A, B;
|
||||
reg [8:0] Y;
|
||||
reg [2:0] state;
|
||||
|
||||
reg carry;
|
||||
reg zero;
|
||||
wire [1:0] flags = { zero, carry };
|
||||
|
||||
localparam S_RESET = 0;
|
||||
localparam S_SELECT = 1;
|
||||
localparam S_DECODE = 2;
|
||||
localparam S_LOAD_ADDR = 3;
|
||||
localparam S_STORE_ADDR = 4;
|
||||
localparam S_COMPUTE = 5;
|
||||
|
||||
wire load_const = opcode[3:1] == 3'b111;
|
||||
|
||||
ALU alu(.A(A), .B(B), .Y(Y), .aluop(aluop));
|
||||
|
||||
always @(posedge clk)
|
||||
if (reset) begin
|
||||
state <= 0;
|
||||
write <= 0;
|
||||
end else begin
|
||||
case (state)
|
||||
// state 0: reset
|
||||
S_RESET: begin
|
||||
ip <= 8'h80;
|
||||
write <= 0;
|
||||
state <= S_SELECT;
|
||||
end
|
||||
// state 1: select opcode address
|
||||
S_SELECT: begin
|
||||
address <= ip;
|
||||
ip <= ip + 1;
|
||||
write <= 0;
|
||||
state <= S_DECODE;
|
||||
end
|
||||
// state 2: read/decode opcode
|
||||
S_DECODE: begin
|
||||
casez (data_in)
|
||||
8'b00??????: begin
|
||||
if (data_in[5])
|
||||
B <= {3'b0, data_in[4:0]};
|
||||
else
|
||||
A <= {3'b0, data_in[4:0]};
|
||||
state <= S_SELECT;
|
||||
end
|
||||
8'b010?????: begin
|
||||
address <= {4'b0, data_in[3:0]};
|
||||
state <= S_LOAD_ADDR;
|
||||
end
|
||||
8'b011?????: begin
|
||||
address <= {4'b0, data_in[3:0]};
|
||||
state <= S_STORE_ADDR;
|
||||
end
|
||||
8'b100?????: begin
|
||||
aluop <= data_in[3:0];
|
||||
state <= S_COMPUTE;
|
||||
end
|
||||
default: begin
|
||||
state <= S_RESET; // reset
|
||||
end
|
||||
endcase
|
||||
opcode <= data_in;
|
||||
end
|
||||
// state 3: load address
|
||||
S_LOAD_ADDR: begin
|
||||
if (opcode[4])
|
||||
B <= data_in;
|
||||
else
|
||||
A <= data_in;
|
||||
state <= S_SELECT;
|
||||
end
|
||||
// state 4: store address
|
||||
S_STORE_ADDR: begin
|
||||
if (opcode[4])
|
||||
data_out <= B;
|
||||
else
|
||||
data_out <= A;
|
||||
write <= 1;
|
||||
state <= S_SELECT;
|
||||
end
|
||||
// state 5: compute ALU op and flags
|
||||
S_COMPUTE: begin
|
||||
if (opcode[4])
|
||||
B <= Y[7:0];
|
||||
else
|
||||
A <= Y[7:0];
|
||||
carry <= Y[8];
|
||||
zero <= ~|Y;
|
||||
state <= S_SELECT;
|
||||
end
|
||||
endcase
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
||||
module test_CPU_top(
|
||||
input clk,
|
||||
input reset,
|
||||
output [7:0] address_bus,
|
||||
output reg [7:0] to_cpu,
|
||||
output [7:0] from_cpu,
|
||||
output write_enable
|
||||
);
|
||||
|
||||
reg [7:0] ram[127:0];
|
||||
reg [7:0] rom[127:0];
|
||||
|
||||
CPU cpu(.clk(clk),
|
||||
.reset(reset),
|
||||
.address(address_bus),
|
||||
.data_in(to_cpu),
|
||||
.data_out(from_cpu),
|
||||
.write(write_enable));
|
||||
|
||||
// does not work as (posedge clk)
|
||||
always @(*)
|
||||
if (write_enable)
|
||||
ram[address_bus[6:0]] = from_cpu;
|
||||
else if (address_bus[7] == 0)
|
||||
to_cpu = ram[address_bus[6:0]];
|
||||
else
|
||||
to_cpu = rom[address_bus[6:0]];
|
||||
|
||||
initial begin
|
||||
// address 0x80
|
||||
rom['h00] = `I_CONST(`REG_A, 5'h1f);
|
||||
rom['h01] = `I_COMPUTE(`REG_A, `OP_ASL);
|
||||
rom['h02] = `I_COMPUTE(`REG_A, `OP_ASL);
|
||||
rom['h03] = `I_COMPUTE(`REG_A, `OP_ASL);
|
||||
rom['h04] = `I_COMPUTE(`REG_A, `OP_ASL);
|
||||
rom['h05] = `I_COMPUTE(`REG_B, `OP_LOAD_A);
|
||||
rom['h06] = `I_STORE_ADDR(`REG_B, 4'd1);
|
||||
rom['h07] = `I_LOAD_ADDR(`REG_B, 4'd1);
|
||||
rom['h08] = `I_RESET;
|
||||
end
|
||||
|
||||
endmodule
|
@ -1,11 +1,10 @@
|
||||
`include "hvsync_generator.v"
|
||||
|
||||
module digits10_case(digit, yofs, bits);
|
||||
|
||||
input [3:0] digit;
|
||||
input [2:0] yofs;
|
||||
output [4:0] bits;
|
||||
|
||||
module digits10_case(
|
||||
input [3:0] digit,
|
||||
input [2:0] yofs,
|
||||
output [4:0] bits
|
||||
);
|
||||
wire [6:0] caseexpr = {digit,yofs};
|
||||
always @(*)
|
||||
case (caseexpr)/*{w:5,h:5,count:10}*/
|
||||
@ -73,13 +72,12 @@ module digits10_case(digit, yofs, bits);
|
||||
endcase
|
||||
endmodule
|
||||
|
||||
module digits10_array(digit, yofs, bits);
|
||||
|
||||
input [3:0] digit;
|
||||
input [2:0] yofs;
|
||||
output [4:0] bits;
|
||||
|
||||
reg [4:0] bitarray[10][5];
|
||||
module digits10_array(
|
||||
input [3:0] digit,
|
||||
input [2:0] yofs,
|
||||
output [4:0] bits
|
||||
);
|
||||
reg [4:0] bitarray[16][5];
|
||||
|
||||
assign bits = bitarray[digit][yofs];
|
||||
|
||||
@ -143,21 +141,25 @@ module digits10_array(digit, yofs, bits);
|
||||
bitarray[9][2] = 5'b11111;
|
||||
bitarray[9][3] = 5'b00001;
|
||||
bitarray[9][4] = 5'b11111;
|
||||
|
||||
for (int i = 10; i <= 15; i++)
|
||||
for (int j = 0; j <= 4; j++)
|
||||
bitarray[i][j] = 0;
|
||||
end
|
||||
endmodule
|
||||
|
||||
module test_numbers_top(clk, hsync, vsync, rgb);
|
||||
|
||||
input clk;
|
||||
output hsync, vsync;
|
||||
output [2:0] rgb;
|
||||
module test_numbers_top(
|
||||
input clk, reset,
|
||||
output hsync, vsync,
|
||||
output [2:0] rgb
|
||||
);
|
||||
wire display_on;
|
||||
wire [8:0] hpos;
|
||||
wire [8:0] vpos;
|
||||
|
||||
hvsync_generator hvsync_gen(
|
||||
.clk(clk),
|
||||
.reset(0),
|
||||
.reset(reset),
|
||||
.hsync(hsync),
|
||||
.vsync(vsync),
|
||||
.display_on(display_on),
|
||||
|
16
presets/verilog/gates.v
Normal file
16
presets/verilog/gates.v
Normal file
@ -0,0 +1,16 @@
|
||||
module gates(clk, out_not, out_and, out_or, out_xor, in);
|
||||
|
||||
input clk;
|
||||
output out_not, out_and, out_or, out_xor;
|
||||
output reg [3:0] in;
|
||||
|
||||
not U1(out_not,in[0]);
|
||||
and U2(out_and,in[0],in[1],in[2],in[3]);
|
||||
or U3(out_or,in[0],in[1],in[2],in[3]);
|
||||
xor U4(out_xor,in[0],in[1],in[2]);
|
||||
|
||||
always @(posedge clk) begin
|
||||
in <= in + 1;
|
||||
end
|
||||
|
||||
endmodule;
|
@ -1,6 +1,23 @@
|
||||
`ifndef HVSYNC_GENERATOR_H
|
||||
`define HVSYNC_GENERATOR_H
|
||||
|
||||
// constant declarations for TV-simulator sync parameters
|
||||
localparam H_DISPLAY = 256; // horizontal display width
|
||||
localparam H_BACK = 23; // horizontal left border (back porch)
|
||||
localparam H_FRONT = 7; // horizontal right border (front porch)
|
||||
localparam H_SYNC = 23; // horizontal sync width
|
||||
localparam H_SYNC_START = H_DISPLAY + H_FRONT;
|
||||
localparam H_SYNC_END = H_DISPLAY + H_FRONT + H_SYNC - 1;
|
||||
localparam H_MAX = H_DISPLAY + H_BACK + H_FRONT + H_SYNC - 1;
|
||||
|
||||
localparam V_DISPLAY = 240; // vertical display height
|
||||
localparam V_TOP = 5; // vertical top border
|
||||
localparam V_BOTTOM = 14; // vertical bottom border
|
||||
localparam V_SYNC = 3; // vertical sync # lines
|
||||
localparam V_SYNC_START = V_DISPLAY + V_BOTTOM;
|
||||
localparam V_SYNC_END = V_DISPLAY + V_BOTTOM + V_SYNC - 1;
|
||||
localparam V_MAX = V_DISPLAY + V_TOP + V_BOTTOM + V_SYNC - 1;
|
||||
|
||||
module hvsync_generator(
|
||||
input clk,
|
||||
input reset,
|
||||
@ -10,23 +27,6 @@ module hvsync_generator(
|
||||
output [8:0] vpos
|
||||
);
|
||||
|
||||
// constant declarations for TV-simulator sync parameters
|
||||
localparam H_DISPLAY = 256; // horizontal display width
|
||||
localparam H_BACK = 23; // horizontal left border (back porch)
|
||||
localparam H_FRONT = 7; // horizontal right border (front porch)
|
||||
localparam H_SYNC = 23; // horizontal sync width
|
||||
localparam H_SYNC_START = H_DISPLAY + H_FRONT;
|
||||
localparam H_SYNC_END = H_DISPLAY + H_FRONT + H_SYNC - 1;
|
||||
localparam H_MAX = H_DISPLAY + H_BACK + H_FRONT + H_SYNC - 1;
|
||||
|
||||
localparam V_DISPLAY = 240; // vertical display height
|
||||
localparam V_TOP = 5; // vertical top border
|
||||
localparam V_BOTTOM = 14; // vertical bottom border
|
||||
localparam V_SYNC = 3; // vertical sync # lines
|
||||
localparam V_SYNC_START = V_DISPLAY + V_BOTTOM;
|
||||
localparam V_SYNC_END = V_DISPLAY + V_BOTTOM + V_SYNC - 1;
|
||||
localparam V_MAX = V_DISPLAY + V_TOP + V_BOTTOM + V_SYNC - 1;
|
||||
|
||||
wire hmaxxed = (hpos == H_MAX) || reset;
|
||||
wire vmaxxed = (vpos == V_MAX) || reset;
|
||||
|
||||
@ -37,7 +37,7 @@ module hvsync_generator(
|
||||
hpos <= 0;
|
||||
else
|
||||
hpos <= hpos + 1;
|
||||
end;
|
||||
end
|
||||
|
||||
// increment vertical position counter
|
||||
always @(posedge clk)
|
||||
@ -47,7 +47,7 @@ module hvsync_generator(
|
||||
vpos <= vpos + 1;
|
||||
else
|
||||
vpos <= 0;
|
||||
end;
|
||||
end
|
||||
|
||||
// compute hsync + vsync + display_on signals
|
||||
always @(posedge clk)
|
||||
|
82
presets/verilog/ram1.v
Normal file
82
presets/verilog/ram1.v
Normal file
@ -0,0 +1,82 @@
|
||||
`include "hvsync_generator.v"
|
||||
`include "digits10.v"
|
||||
|
||||
module RAM_1KB(clk, addr, din, dout, we);
|
||||
input clk; // clock
|
||||
input [9:0] addr; // 10-bit address
|
||||
input [7:0] din; // 8-bit data input
|
||||
output [7:0] dout; // 8-bit data output
|
||||
input we; // write enable
|
||||
|
||||
reg [7:0] mem [1024]; // 1024x8 bit memory
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (we) // if write enabled
|
||||
mem[addr] <= din; // write memory from din
|
||||
dout <= mem[addr]; // read memory to dout
|
||||
end
|
||||
endmodule
|
||||
|
||||
module test_framebuf_top(
|
||||
input clk, reset,
|
||||
output hsync, vsync,
|
||||
output [2:0] rgb
|
||||
);
|
||||
wire display_on;
|
||||
wire [8:0] hpos;
|
||||
wire [8:0] vpos;
|
||||
|
||||
wire [9:0] ram_addr;
|
||||
wire [7:0] ram_read;
|
||||
reg [7:0] ram_write;
|
||||
reg ram_writeenable = 0;
|
||||
|
||||
RAM_1KB ram(
|
||||
.clk(clk),
|
||||
.dout(ram_read),
|
||||
.din(ram_write),
|
||||
.addr(ram_addr),
|
||||
.we(ram_writeenable)
|
||||
);
|
||||
|
||||
hvsync_generator hvsync_gen(
|
||||
.clk(clk),
|
||||
.reset(reset),
|
||||
.hsync(hsync),
|
||||
.vsync(vsync),
|
||||
.display_on(display_on),
|
||||
.hpos(hpos),
|
||||
.vpos(vpos)
|
||||
);
|
||||
|
||||
wire [4:0] row = vpos[7:3];
|
||||
wire [4:0] col = hpos[7:3];
|
||||
wire [3:0] digit = ram_read[3:0];
|
||||
wire [2:0] yofs = vpos[2:0];
|
||||
wire [2:0] xofs = hpos[2:0];
|
||||
wire [4:0] bits;
|
||||
|
||||
assign ram_addr = {row,col};
|
||||
|
||||
digits10_case numbers(
|
||||
.digit(digit),
|
||||
.yofs(yofs),
|
||||
.bits(bits)
|
||||
);
|
||||
|
||||
wire r = display_on && 0;
|
||||
wire g = display_on && bits[~xofs];
|
||||
wire b = display_on && 0;
|
||||
assign rgb = {b,g,r};
|
||||
|
||||
always @(posedge clk)
|
||||
if (display_on && vpos[2:0] == 7)
|
||||
case (hpos[2:0])
|
||||
6: begin
|
||||
ram_write <= (ram_read + 1);
|
||||
ram_writeenable <= 1;
|
||||
end
|
||||
7: ram_writeenable <= 0;
|
||||
endcase
|
||||
|
||||
endmodule
|
77
presets/verilog/ram2.v
Normal file
77
presets/verilog/ram2.v
Normal file
@ -0,0 +1,77 @@
|
||||
`include "hvsync_generator.v"
|
||||
`include "digits10.v"
|
||||
|
||||
module RAM_1KB_tri(clk, addr, data, we);
|
||||
input clk;
|
||||
input [9:0] addr;
|
||||
inout [7:0] data;
|
||||
input we;
|
||||
|
||||
reg [7:0] mem [1023:0];
|
||||
assign data = !we ? mem[addr] : 8'bz;
|
||||
always @(posedge clk) begin
|
||||
if (we)
|
||||
mem[addr] <= data;
|
||||
end
|
||||
endmodule
|
||||
|
||||
module test_framebuf_top(
|
||||
input clk, reset,
|
||||
output hsync, vsync,
|
||||
output [2:0] rgb
|
||||
);
|
||||
wire display_on;
|
||||
wire [8:0] hpos;
|
||||
wire [8:0] vpos;
|
||||
|
||||
reg ram_writeenable = 0;
|
||||
wire [9:0] ram_addr = {row,col};
|
||||
wire [7:0] ram_data = ram_writeenable ? ram_write : 8'bz;
|
||||
wire [7:0] ram_read = ram_writeenable ? 8'bz : ram_data;
|
||||
reg [7:0] ram_write;
|
||||
|
||||
RAM_1KB_tri ram(
|
||||
.clk(clk),
|
||||
.data(ram_data),
|
||||
.addr(ram_addr),
|
||||
.we(ram_writeenable)
|
||||
);
|
||||
|
||||
hvsync_generator hvsync_gen(
|
||||
.clk(clk),
|
||||
.reset(reset),
|
||||
.hsync(hsync),
|
||||
.vsync(vsync),
|
||||
.display_on(display_on),
|
||||
.hpos(hpos),
|
||||
.vpos(vpos)
|
||||
);
|
||||
|
||||
wire [4:0] row = vpos[7:3];
|
||||
wire [4:0] col = hpos[7:3];
|
||||
wire [3:0] digit = ram_read[3:0];
|
||||
wire [2:0] yofs = vpos[2:0];
|
||||
wire [4:0] bits;
|
||||
|
||||
digits10_array numbers(
|
||||
.digit(digit),
|
||||
.yofs(yofs),
|
||||
.bits(bits)
|
||||
);
|
||||
|
||||
wire r = display_on && 0;
|
||||
wire g = display_on && bits[hpos[2:0] ^ 3'b111];
|
||||
wire b = display_on && 0;
|
||||
assign rgb = {b,g,r};
|
||||
|
||||
always @(posedge clk)
|
||||
if (display_on && vpos[2:0] == 7)
|
||||
case (hpos[2:0])
|
||||
6: begin
|
||||
ram_write <= ram_read + 1;
|
||||
ram_writeenable <= 1;
|
||||
end
|
||||
7: ram_writeenable <= 0;
|
||||
endcase
|
||||
|
||||
endmodule
|
@ -1,14 +1,11 @@
|
||||
`include "hvsync_generator.v"
|
||||
|
||||
module car_bitmap(yofs, bits);
|
||||
|
||||
input [3:0] yofs;
|
||||
output [7:0] bits;
|
||||
|
||||
module car_bitmap(
|
||||
input [3:0] yofs,
|
||||
output [7:0] bits
|
||||
);
|
||||
reg [7:0] bitarray[16];
|
||||
|
||||
assign bits = bitarray[yofs];
|
||||
|
||||
initial begin/*{w:8,h:16}*/
|
||||
bitarray[0] = 8'b0;
|
||||
bitarray[1] = 8'b101110;
|
||||
@ -29,10 +26,9 @@ module car_bitmap(yofs, bits);
|
||||
end
|
||||
endmodule
|
||||
|
||||
module sprite_bitmap_top(clk, hsync, vsync, rgb, hpaddle, vpaddle);
|
||||
module sprite_bitmap_top(clk, reset, hsync, vsync, rgb);
|
||||
|
||||
input clk;
|
||||
input hpaddle, vpaddle;
|
||||
input clk, reset;
|
||||
output hsync, vsync;
|
||||
output [2:0] rgb;
|
||||
wire display_on;
|
||||
@ -44,12 +40,12 @@ module sprite_bitmap_top(clk, hsync, vsync, rgb, hpaddle, vpaddle);
|
||||
reg [3:0] car_sprite_yofs;
|
||||
wire [7:0] car_sprite_bits;
|
||||
|
||||
reg [7:0] player_x = 128;
|
||||
reg [7:0] player_y = 128;
|
||||
reg [8:0] player_x = 128;
|
||||
reg [8:0] player_y = 128;
|
||||
|
||||
hvsync_generator hvsync_gen(
|
||||
.clk(clk),
|
||||
.reset(0),
|
||||
.reset(reset),
|
||||
.hsync(hsync),
|
||||
.vsync(vsync),
|
||||
.display_on(display_on),
|
||||
@ -63,23 +59,22 @@ module sprite_bitmap_top(clk, hsync, vsync, rgb, hpaddle, vpaddle);
|
||||
|
||||
always @(posedge hsync)
|
||||
// start sprite?
|
||||
if (vpos == {1'0,player_y})
|
||||
if (vpos == player_y)
|
||||
car_sprite_yofs <= 15;
|
||||
else if (car_sprite_yofs != 0)
|
||||
car_sprite_yofs <= car_sprite_yofs - 1;
|
||||
|
||||
always @(posedge clk)
|
||||
if (display_on) begin
|
||||
if (hpos == {1'0,player_x})
|
||||
car_sprite_xofs <= 15;
|
||||
else if (car_sprite_xofs != 0)
|
||||
car_sprite_xofs <= car_sprite_xofs - 1;
|
||||
end
|
||||
if (hpos == player_x)
|
||||
car_sprite_xofs <= 15;
|
||||
else if (car_sprite_xofs != 0)
|
||||
car_sprite_xofs <= car_sprite_xofs - 1;
|
||||
|
||||
// mirror sprite in X direction
|
||||
wire car_gfx = car_sprite_bits[car_sprite_xofs>=8 ?
|
||||
wire [3:0] car_bit = car_sprite_xofs>=8 ?
|
||||
15-car_sprite_xofs:
|
||||
car_sprite_xofs];
|
||||
car_sprite_xofs;
|
||||
wire car_gfx = car_sprite_bits[3'(car_bit)];
|
||||
|
||||
wire r = display_on && car_gfx;
|
||||
wire g = display_on && car_gfx;
|
||||
|
305
presets/verilog/sprite_rotation.v
Normal file
305
presets/verilog/sprite_rotation.v
Normal file
@ -0,0 +1,305 @@
|
||||
`include "hvsync_generator.v"
|
||||
|
||||
module tank_bitmap(addr, bits);
|
||||
|
||||
input [7:0] addr;
|
||||
output [7:0] bits;
|
||||
|
||||
reg [15:0] bitarray[256];
|
||||
|
||||
assign bits = (addr[0]) ? bitarray[addr>>1][15:8] : bitarray[addr>>1][7:0];
|
||||
|
||||
initial begin/*{w:16,h:16,bpw:16,count:5}*/
|
||||
bitarray[0'h00] = 16'b11110000000;
|
||||
bitarray[0'h01] = 16'b11110000000;
|
||||
bitarray[0'h02] = 16'b1100000000;
|
||||
bitarray[0'h03] = 16'b1100000000;
|
||||
bitarray[0'h04] = 16'b111101101111000;
|
||||
bitarray[0'h05] = 16'b111101101111000;
|
||||
bitarray[0'h06] = 16'b111111111111000;
|
||||
bitarray[0'h07] = 16'b111111111111000;
|
||||
bitarray[0'h08] = 16'b111111111111000;
|
||||
bitarray[0'h09] = 16'b111111111111000;
|
||||
bitarray[0'h0a] = 16'b111111111111000;
|
||||
bitarray[0'h0b] = 16'b111100001111000;
|
||||
bitarray[0'h0c] = 16'b111100001111000;
|
||||
bitarray[0'h0d] = 16'b0;
|
||||
bitarray[0'h0e] = 16'b0;
|
||||
bitarray[0'h0f] = 16'b0;
|
||||
|
||||
bitarray[0'h10] = 16'b111000000000;
|
||||
bitarray[0'h11] = 16'b1111000000000;
|
||||
bitarray[0'h12] = 16'b1111000000000;
|
||||
bitarray[0'h13] = 16'b11000000000;
|
||||
bitarray[0'h14] = 16'b11101110000;
|
||||
bitarray[0'h15] = 16'b1101110000;
|
||||
bitarray[0'h16] = 16'b111101111110000;
|
||||
bitarray[0'h17] = 16'b111101111111000;
|
||||
bitarray[0'h18] = 16'b111111111111000;
|
||||
bitarray[0'h19] = 16'b11111111111000;
|
||||
bitarray[0'h1a] = 16'b11111111111100;
|
||||
bitarray[0'h1b] = 16'b11111111111100;
|
||||
bitarray[0'h1c] = 16'b11111001111100;
|
||||
bitarray[0'h1d] = 16'b1111001110000;
|
||||
bitarray[0'h1e] = 16'b1111000000000;
|
||||
bitarray[0'h1f] = 16'b1100000000000;
|
||||
|
||||
bitarray[0'h20] = 16'b0;
|
||||
bitarray[0'h21] = 16'b0;
|
||||
bitarray[0'h22] = 16'b11000011000000;
|
||||
bitarray[0'h23] = 16'b111000111100000;
|
||||
bitarray[0'h24] = 16'b111101111110000;
|
||||
bitarray[0'h25] = 16'b1110111111000;
|
||||
bitarray[0'h26] = 16'b111111111100;
|
||||
bitarray[0'h27] = 16'b11111111110;
|
||||
bitarray[0'h28] = 16'b11011111111110;
|
||||
bitarray[0'h29] = 16'b111111111111100;
|
||||
bitarray[0'h2a] = 16'b111111111001000;
|
||||
bitarray[0'h2b] = 16'b11111110000000;
|
||||
bitarray[0'h2c] = 16'b1111100000000;
|
||||
bitarray[0'h2d] = 16'b111110000000;
|
||||
bitarray[0'h2e] = 16'b11110000000;
|
||||
bitarray[0'h2f] = 16'b1100000000;
|
||||
|
||||
bitarray[0'h30] = 16'b0;
|
||||
bitarray[0'h31] = 16'b0;
|
||||
bitarray[0'h32] = 16'b110000000;
|
||||
bitarray[0'h33] = 16'b100001111000000;
|
||||
bitarray[0'h34] = 16'b1110001111110000;
|
||||
bitarray[0'h35] = 16'b1111010111111100;
|
||||
bitarray[0'h36] = 16'b1111111111111111;
|
||||
bitarray[0'h37] = 16'b1111111111111;
|
||||
bitarray[0'h38] = 16'b11111111110;
|
||||
bitarray[0'h39] = 16'b101111111110;
|
||||
bitarray[0'h3a] = 16'b1111111101100;
|
||||
bitarray[0'h3b] = 16'b11111111000000;
|
||||
bitarray[0'h3c] = 16'b1111111100000;
|
||||
bitarray[0'h3d] = 16'b11111110000;
|
||||
bitarray[0'h3e] = 16'b111100000;
|
||||
bitarray[0'h3f] = 16'b1100000;
|
||||
|
||||
bitarray[0'h40] = 16'b0;
|
||||
bitarray[0'h41] = 16'b0;
|
||||
bitarray[0'h42] = 16'b0;
|
||||
bitarray[0'h43] = 16'b111111111000;
|
||||
bitarray[0'h44] = 16'b111111111000;
|
||||
bitarray[0'h45] = 16'b111111111000;
|
||||
bitarray[0'h46] = 16'b111111111000;
|
||||
bitarray[0'h47] = 16'b1100001111100000;
|
||||
bitarray[0'h48] = 16'b1111111111100000;
|
||||
bitarray[0'h49] = 16'b1111111111100000;
|
||||
bitarray[0'h4a] = 16'b1100001111100000;
|
||||
bitarray[0'h4b] = 16'b111111111000;
|
||||
bitarray[0'h4c] = 16'b111111111000;
|
||||
bitarray[0'h4d] = 16'b111111111000;
|
||||
bitarray[0'h4e] = 16'b111111111000;
|
||||
bitarray[0'h4f] = 16'b0;
|
||||
end
|
||||
endmodule
|
||||
|
||||
module sprite_renderer(clk, vstart, load, hstart, rom_addr, rom_bits,
|
||||
hmirror, vmirror,
|
||||
gfx, busy);
|
||||
|
||||
input clk, vstart, load, hstart;
|
||||
input hmirror, vmirror;
|
||||
output [4:0] rom_addr;
|
||||
input [7:0] rom_bits;
|
||||
output gfx;
|
||||
output busy = state != WAIT_FOR_VSTART;
|
||||
|
||||
reg [2:0] state;
|
||||
reg [3:0] ycount;
|
||||
reg [3:0] xcount;
|
||||
|
||||
reg [15:0] outbits;
|
||||
|
||||
localparam WAIT_FOR_VSTART = 0;
|
||||
localparam WAIT_FOR_LOAD = 1;
|
||||
localparam LOAD1_SETUP = 2;
|
||||
localparam LOAD1_FETCH = 3;
|
||||
localparam LOAD2_SETUP = 4;
|
||||
localparam LOAD2_FETCH = 5;
|
||||
localparam WAIT_FOR_HSTART = 6;
|
||||
localparam DRAW = 7;
|
||||
|
||||
always @(posedge clk)
|
||||
begin
|
||||
case (state)
|
||||
WAIT_FOR_VSTART: begin
|
||||
ycount <= 0;
|
||||
// set a default value (blank) for pixel output
|
||||
// note: multiple non-blocking assignments are vendor-specific
|
||||
gfx <= 0;
|
||||
if (vstart) state <= WAIT_FOR_LOAD;
|
||||
end
|
||||
WAIT_FOR_LOAD: begin
|
||||
xcount <= 0;
|
||||
gfx <= 0;
|
||||
if (load) state <= LOAD1_SETUP;
|
||||
end
|
||||
LOAD1_SETUP: begin
|
||||
rom_addr <= {vmirror?~ycount:ycount, 1'b0};
|
||||
state <= LOAD1_FETCH;
|
||||
end
|
||||
LOAD1_FETCH: begin
|
||||
outbits[7:0] <= rom_bits;
|
||||
state <= LOAD2_SETUP;
|
||||
end
|
||||
LOAD2_SETUP: begin
|
||||
rom_addr <= {vmirror?~ycount:ycount, 1'b1};
|
||||
state <= LOAD2_FETCH;
|
||||
end
|
||||
LOAD2_FETCH: begin
|
||||
outbits[15:8] <= rom_bits;
|
||||
state <= WAIT_FOR_HSTART;
|
||||
end
|
||||
WAIT_FOR_HSTART: begin
|
||||
if (hstart) state <= DRAW;
|
||||
end
|
||||
DRAW: begin
|
||||
// mirror graphics left/right
|
||||
gfx <= outbits[hmirror ? ~xcount[3:0] : xcount[3:0]];
|
||||
xcount <= xcount + 1;
|
||||
if (xcount == 15) begin // pre-increment value
|
||||
ycount <= ycount + 1;
|
||||
if (ycount == 15) // pre-increment value
|
||||
state <= WAIT_FOR_VSTART; // done drawing sprite
|
||||
else
|
||||
state <= WAIT_FOR_LOAD; // done drawing this scanline
|
||||
end
|
||||
end
|
||||
endcase
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
||||
module rotation_selector(rotation, bitmap_num, hmirror, vmirror);
|
||||
input [4:0] rotation;
|
||||
output [2:0] bitmap_num;
|
||||
output hmirror, vmirror;
|
||||
|
||||
always @(*)
|
||||
case (rotation[3:2])
|
||||
0: begin
|
||||
bitmap_num = {1'b0, rotation[1:0]};
|
||||
hmirror = 0;
|
||||
vmirror = 0;
|
||||
end
|
||||
1: begin
|
||||
bitmap_num = -rotation[2:0];
|
||||
hmirror = 0;
|
||||
vmirror = 1;
|
||||
end
|
||||
2: begin
|
||||
bitmap_num = {1'b0, rotation[1:0]};
|
||||
hmirror = 1;
|
||||
vmirror = 1;
|
||||
end
|
||||
3: begin
|
||||
bitmap_num = -rotation[2:0];
|
||||
hmirror = 1;
|
||||
vmirror = 0;
|
||||
end
|
||||
endcase
|
||||
|
||||
endmodule
|
||||
|
||||
module tank_controller(clk, reset, hpos, vpos, hsync, vsync,
|
||||
sprite_addr, sprite_bits, gfx);
|
||||
|
||||
input clk;
|
||||
input reset;
|
||||
input hsync;
|
||||
input vsync;
|
||||
input [8:0] hpos;
|
||||
input [8:0] vpos;
|
||||
output [7:0] sprite_addr;
|
||||
input [7:0] sprite_bits;
|
||||
reg hmirror;
|
||||
reg vmirror;
|
||||
output gfx;
|
||||
wire busy;
|
||||
|
||||
reg [7:0] player_x = 64;
|
||||
reg [7:0] player_y = 64;
|
||||
reg [4:0] player_rot = 0;
|
||||
|
||||
wire vstart = {1'b0,player_y} == vpos;
|
||||
wire hstart = {1'b0,player_x} == hpos;
|
||||
|
||||
sprite_renderer renderer(
|
||||
.clk(clk),
|
||||
.vstart(vstart),
|
||||
.load(hsync),
|
||||
.hstart(hstart),
|
||||
.hmirror(hmirror),
|
||||
.vmirror(vmirror),
|
||||
.rom_addr(sprite_addr[4:0]),
|
||||
.rom_bits(sprite_bits),
|
||||
.gfx(gfx),
|
||||
.busy(busy));
|
||||
|
||||
rotation_selector rotsel(
|
||||
.rotation(player_rot),
|
||||
.bitmap_num(sprite_addr[7:5]),
|
||||
.hmirror(hmirror),
|
||||
.vmirror(vmirror));
|
||||
|
||||
always @(posedge vsync)
|
||||
player_rot <= player_rot + 1;
|
||||
|
||||
endmodule
|
||||
|
||||
module test_top(clk, reset, hsync, vsync, rgb);
|
||||
|
||||
input clk;
|
||||
input reset;
|
||||
output hsync;
|
||||
output vsync;
|
||||
output [2:0] rgb;
|
||||
wire display_on;
|
||||
wire [8:0] hpos;
|
||||
wire [8:0] vpos;
|
||||
|
||||
reg [7:0] paddle_x;
|
||||
reg [7:0] paddle_y;
|
||||
|
||||
hvsync_generator hvsync_gen(
|
||||
.clk(clk),
|
||||
.reset(reset),
|
||||
.hsync(hsync),
|
||||
.vsync(vsync),
|
||||
.display_on(display_on),
|
||||
.hpos(hpos),
|
||||
.vpos(vpos)
|
||||
);
|
||||
|
||||
wire [7:0] tank_sprite_addr;
|
||||
wire [7:0] tank_sprite_bits;
|
||||
|
||||
tank_bitmap tank_bmp(
|
||||
.addr(tank_sprite_addr),
|
||||
.bits(tank_sprite_bits));
|
||||
|
||||
tank_controller tank1(
|
||||
.clk(clk),
|
||||
.reset(reset),
|
||||
.hpos(hpos),
|
||||
.vpos(vpos),
|
||||
.hsync(hsync),
|
||||
.vsync(vsync),
|
||||
.sprite_addr(tank_sprite_addr),
|
||||
.sprite_bits(tank_sprite_bits),
|
||||
.gfx(tank1_gfx)
|
||||
);
|
||||
|
||||
wire tank1_gfx;
|
||||
wire unused;
|
||||
|
||||
wire r = display_on && tank1_gfx;
|
||||
wire g = display_on && tank1_gfx;
|
||||
wire b = display_on && tank1_gfx;
|
||||
assign rgb = {b,g,r};
|
||||
|
||||
endmodule
|
@ -1,10 +1,12 @@
|
||||
`include "hvsync_generator.v"
|
||||
|
||||
module test_hvsync_top(clk, hsync, vsync, rgb);
|
||||
|
||||
input clk;
|
||||
output hsync, vsync;
|
||||
output [2:0] rgb;
|
||||
module test_hvsync_top(
|
||||
input clk,
|
||||
output hsync,
|
||||
output vsync,
|
||||
output [2:0] rgb
|
||||
);
|
||||
|
||||
wire display_on;
|
||||
wire [8:0] hpos;
|
||||
wire [8:0] vpos;
|
||||
|
@ -5,12 +5,16 @@ var VERILOG_PRESETS = [
|
||||
{id:'hvsync_generator.v', name:'Video Sync Generator'},
|
||||
{id:'test_hvsync.v', name:'Test Pattern'},
|
||||
{id:'lfsr.v', name:'Linear Feedback Shift Register'},
|
||||
{id:'digits10.v', name:'Digits'},
|
||||
{id:'digits10.v', name:'Bitmapped Digits'},
|
||||
{id:'7segment.v', name:'7-Segment Decoder'},
|
||||
{id:'ball_slip_counter.v', name:'Ball Motion (slipping counter)'},
|
||||
{id:'ball_paddle.v', name:'Brick Smash Game'},
|
||||
{id:'sprite_bitmap.v', name:'Sprite Bitmaps'},
|
||||
{id:'sprite_renderer.v', name:'Sprite Rendering'},
|
||||
{id:'sprite_multiple.v', name:'Multiple Sprites'},
|
||||
{id:'sprite_rotation.v', name:'Sprite Rotation'},
|
||||
{id:'ram1.v', name:'RAM Text Display'},
|
||||
{id:'tank.v', name:'Tank Game'},
|
||||
{id:'cpu8.v', name:'Simple 8-Bit CPU'},
|
||||
];
|
||||
|
||||
@ -568,7 +572,7 @@ var VerilogPlatform = function(mainElement, options) {
|
||||
this.runToVsync = function() {
|
||||
var self = this;
|
||||
this.setDebugCondition(function() {
|
||||
if (gen.vsync && gen.ticks() > debugTargetClock+1000) {
|
||||
if (gen.vsync && gen.ticks() > debugTargetClock+2000) {
|
||||
self.breakpointHit(gen.ticks());
|
||||
return true;
|
||||
}
|
||||
|
@ -1114,6 +1114,7 @@ function compileYosys(code, platform, options) {
|
||||
return {errors:errors};
|
||||
}
|
||||
endtime("compile");
|
||||
//TODO: filename in errors
|
||||
if (errors.length) return {errors:errors};
|
||||
try {
|
||||
var json_file = FS.readFile(topmod+".json", {encoding:'utf8'});
|
||||
|
@ -60,10 +60,13 @@ def tohex(v):
|
||||
return '%02x'%v
|
||||
def tohex2(v):
|
||||
return '0x%02x'%v
|
||||
def tobin(v):
|
||||
return "bitarray[0][0]=3'b{0:3b};\n".format(v)
|
||||
|
||||
print '\thex ' + string.join(map(tohex,output),'')
|
||||
print string.join(map(tohex2,output),',')
|
||||
print '\thex ' + string.join(map(tohex,outputlo),'')
|
||||
print '\thex ' + string.join(map(tohex,outputhi),'')
|
||||
print string.join(map(tobin,output),'')
|
||||
|
||||
print len(output),len(outputlo),len(outputhi)
|
||||
|
@ -17,6 +17,7 @@ outfmtgroup.add_argument("-A", "--asmhex", action="store_true", help="DASM-compa
|
||||
outfmtgroup.add_argument("-B", "--asmdb", action="store_true", help="Z80ASM-compatible hex")
|
||||
outfmtgroup.add_argument("-C", "--carray", action="store_true", help="Nested C array")
|
||||
outfmtgroup.add_argument("-F", "--flatcarray", action="store_true", help="Flat C array")
|
||||
outfmtgroup.add_argument("-V", "--verilog", action="store_true", help="Verilog-compatible hex")
|
||||
parser.add_argument('bdffile', help="BDF bitmap file")
|
||||
args = parser.parse_args()
|
||||
|
||||
@ -98,5 +99,12 @@ for arr in [output]:
|
||||
print "static char FONT[%d] = {" % ((hichar-lochar+1) * height)
|
||||
print string.join(map(tohex2,arr),',')
|
||||
print "}";
|
||||
|
||||
|
||||
if args.verilog:
|
||||
j = 0
|
||||
for i in range(0,len(output),height):
|
||||
#print "rom["+str(j)+"] = 32'h" + string.join(map(tohex,arr[i:i+height/2]),'') + ";"
|
||||
#j += 1
|
||||
#print "rom["+str(j)+"] = 32'h" + string.join(map(tohex,arr[i+height/2:i+height]),'') + ";"
|
||||
#j += 1
|
||||
print "rom["+str(j)+"] = 64'h" + string.join(map(tohex,arr[i:i+height]),'') + ";"
|
||||
j += 1
|
||||
|
Loading…
Reference in New Issue
Block a user