1
0
mirror of https://github.com/sehugg/8bitworkshop.git synced 2024-06-20 08:29:30 +00:00

preset updates; shadow text for scope view

This commit is contained in:
Steven Hugg 2018-02-09 16:23:14 -06:00
parent 661bbb0ced
commit 9c25aed9fa
5 changed files with 333 additions and 188 deletions

View File

@ -6,7 +6,7 @@
`define OP_XOR 4'h4 `define OP_XOR 4'h4
`define OP_INC 4'h5 `define OP_INC 4'h5
`define OP_DEC 4'h6 `define OP_DEC 4'h6
`define OP_NOP 4'h7 `define OP_ZERO 4'h7
// operations that generate carry // operations that generate carry
`define OP_ADD 4'h8 `define OP_ADD 4'h8
`define OP_SUB 4'h9 `define OP_SUB 4'h9
@ -24,35 +24,57 @@ module ALU(
case (aluop) case (aluop)
`OP_LOAD_A: Y = {1'b0, A}; `OP_LOAD_A: Y = {1'b0, A};
`OP_LOAD_B: Y = {1'b0, B}; `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 + A;
`OP_LSR: Y = {A[0], A >> 1};
`OP_OR: Y = {1'b0, A | B}; `OP_OR: Y = {1'b0, A | B};
`OP_AND: Y = {1'b0, A & B}; `OP_AND: Y = {1'b0, A & B};
`OP_XOR: Y = {1'b0, A ^ B}; `OP_XOR: Y = {1'b0, A ^ B};
`OP_INC: Y = A + 1;
`OP_DEC: Y = A - 1;
`OP_ZERO: Y = 0;
`OP_ADD: Y = A + B;
`OP_SUB: Y = A - B;
`OP_ASL: Y = A + A;
`OP_LSR: Y = {A[0], A >> 1};
default: Y = 9'bx; default: Y = 9'bx;
endcase endcase
endmodule endmodule
/*
Bits Description
00ddaaaa A @ B -> dest
01ddaaaa A @ immediate -> dest
11ddaaaa A @ read [B] -> dest
10000001 swap A <-> B
1001nnnn A -> write [nnnn]
1010tttt conditional branch
dd = destination (00=A, 01=B, 10=IP, 11=none)
aaaa = ALU operation (@ operator)
nnnn = 4-bit constant
tttt = flags test for conditional branch
*/
// destinations for COMPUTE instructions
`define DEST_A 2'b00 `define DEST_A 2'b00
`define DEST_B 2'b01 `define DEST_B 2'b01
`define DEST_IP 2'b10 `define DEST_IP 2'b10
`define DEST_NOP 2'b11 `define DEST_NOP 2'b11
// instruction macros
`define I_COMPUTE(dest,op) { 2'b00, 2'(dest), 4'(op) } `define I_COMPUTE(dest,op) { 2'b00, 2'(dest), 4'(op) }
`define I_COMPUTE_IMM(dest,op) { 2'b01, 2'(dest), 4'(op) } `define I_COMPUTE_IMM(dest,op) { 2'b01, 2'(dest), 4'(op) }
`define I_COMPUTE_READB(dest,op) { 2'b11, 2'(dest), 4'(op) } `define I_COMPUTE_READB(dest,op) { 2'b11, 2'(dest), 4'(op) }
`define I_CONST_IMM_A { 2'b01, `DEST_A, `OP_LOAD_B } `define I_CONST_IMM_A { 2'b01, `DEST_A, `OP_LOAD_B }
`define I_CONST_IMM_B { 2'b01, `DEST_B, `OP_LOAD_B } `define I_CONST_IMM_B { 2'b01, `DEST_B, `OP_LOAD_B }
`define I_JUMP_IMM { 2'b01, `DEST_IP, `OP_LOAD_B } `define I_JUMP_IMM { 2'b01, `DEST_IP, `OP_LOAD_B }
`define I_STORE_A_TO_B { 8'b10000000 } `define I_STORE_A(addr) { 4'b1001, 4'(addr) }
`define I_CONST_SHORT_A(addr) { 4'b01010, 4'(addr) } `define I_BRANCH_IF_CARRY(carry) { 4'b1010, 2'b00, 1'(carry), 1'b1 }
`define I_CONST_SHORT_B(addr) { 4'b01011, 4'(addr) } `define I_SWAP_AB { 8'b10000001 }
`define I_BRANCH_IF_CARRY(carry) { 6'b100100, 1'(carry), 1'b1 } `define I_RESET { 8'b10111111 }
`define I_RESET { 8'b10000001 } // convenience macros
`define I_ZERO_A `I_COMPUTE(`DEST_A, `OP_ZERO)
`define I_ZERO_B `I_COMPUTE(`DEST_B, `OP_ZERO)
module CPU( module CPU(
input clk, input clk,
@ -75,7 +97,7 @@ module CPU(
reg [7:0] opcode; reg [7:0] opcode;
wire [3:0] aluop = opcode[3:0]; wire [3:0] aluop = opcode[3:0];
wire [1:0] opdest = opcode[5:4]; wire [1:0] opdest = opcode[5:4];
wire memalu = opcode[6]; wire B_or_data = opcode[6];
localparam S_RESET = 0; localparam S_RESET = 0;
localparam S_SELECT = 1; localparam S_SELECT = 1;
@ -83,7 +105,7 @@ module CPU(
localparam S_COMPUTE = 3; localparam S_COMPUTE = 3;
localparam S_READ_IP = 4; localparam S_READ_IP = 4;
ALU alu(.A(A), .B(memalu?data_in:B), .Y(Y), .aluop(aluop)); ALU alu(.A(A), .B(B_or_data?data_in:B), .Y(Y), .aluop(aluop));
always @(posedge clk) always @(posedge clk)
if (reset) begin if (reset) begin
@ -118,20 +140,26 @@ module CPU(
IP <= IP + 1; IP <= IP + 1;
state <= S_COMPUTE; state <= S_COMPUTE;
end end
// ALU A + [B] -> dest // ALU A + read [B] -> dest
8'b11??????: begin 8'b11??????: begin
address <= B; address <= B;
state <= S_COMPUTE; state <= S_COMPUTE;
end end
// A -> write [B] // A -> write [aluop]
8'b10000000: begin 8'b1001????: begin
address <= B; address <= {4'b0, aluop};
data_out <= A; data_out <= A;
write <= 1; write <= 1;
state <= S_SELECT; state <= S_SELECT;
end end
// swap A,B
8'b10000001: begin
A <= B;
B <= A;
state <= S_SELECT;
end
// conditional branch // conditional branch
8'b1001????: begin 8'b1010????: begin
if ( if (
(data_in[0] && (data_in[1] == carry)) || (data_in[0] && (data_in[1] == carry)) ||
(data_in[2] && (data_in[3] == zero))) (data_in[2] && (data_in[3] == zero)))
@ -143,16 +171,6 @@ module CPU(
end end
IP <= IP + 1; // skip immediate IP <= IP + 1; // skip immediate
end end
// aluop -> A
8'b1010????: begin
A <= {4'b0, data_in[3:0]};
state <= S_SELECT;
end
// aluop -> B
8'b1011????: begin
B <= {4'b0, data_in[3:0]};
state <= S_SELECT;
end
// fall-through RESET // fall-through RESET
default: begin default: begin
state <= S_RESET; // reset state <= S_RESET; // reset
@ -197,8 +215,8 @@ module test_CPU_top(
output [7:0] B output [7:0] B
); );
reg [7:0] ram[127:0]; reg [7:0] ram[0:127];
reg [7:0] rom[127:0]; reg [7:0] rom[0:127];
assign IP = cpu.IP; assign IP = cpu.IP;
assign A = cpu.A; assign A = cpu.A;
@ -221,17 +239,18 @@ module test_CPU_top(
to_cpu = rom[address_bus[6:0]]; to_cpu = rom[address_bus[6:0]];
initial begin initial begin
// ROM starts at address 0x80 rom = '{
rom['h00] = `I_CONST_IMM_A; `I_ZERO_A,
rom['h01] = 1; `I_CONST_IMM_B,
rom['h02] = `I_CONST_SHORT_B(0); 1,
rom['h03] = `I_COMPUTE(`DEST_A, `OP_ADD); `I_COMPUTE(`DEST_A, `OP_ADD), // addr 4
rom['h04] = `I_COMPUTE(`DEST_B, `OP_ADD); `I_SWAP_AB,
rom['h05] = `I_STORE_A_TO_B; `I_BRANCH_IF_CARRY(0),
//rom['h06] = `I_JUMP_IMM; 3 + 'h80, // correct for ROM offset
rom['h06] = `I_BRANCH_IF_CARRY(0); `I_RESET,
rom['h07] = 3 + 'h80; // correct for ROM offset // leftover elements
rom['h08] = `I_RESET; 120{0}
};
end end
endmodule endmodule

View File

@ -1,15 +1,17 @@
`define OP_LOAD_A 4'h0 `define OP_LOAD_A 4'h0
`define OP_LOAD_B 4'h1 `define OP_LOAD_B 4'h1
`define OP_ADD 4'h2 `define OP_OR 4'h2
`define OP_SUB 4'h3 `define OP_AND 4'h3
`define OP_INC 4'h4 `define OP_XOR 4'h4
`define OP_DEC 4'h5 `define OP_INC 4'h5
`define OP_ASL 4'h6 `define OP_DEC 4'h6
`define OP_LSR 4'h7 `define OP_NOP 4'h7
`define OP_OR 4'h8 // operations that generate carry
`define OP_AND 4'h9 `define OP_ADD 4'h8
`define OP_XOR 4'ha `define OP_SUB 4'h9
`define OP_ASL 4'ha
`define OP_LSR 4'hb
module ALU( module ALU(
input [7:0] A, input [7:0] A,
@ -22,27 +24,51 @@ module ALU(
case (aluop) case (aluop)
`OP_LOAD_A: Y = {1'b0, A}; `OP_LOAD_A: Y = {1'b0, A};
`OP_LOAD_B: Y = {1'b0, B}; `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_OR: Y = {1'b0, A | B};
`OP_AND: Y = {1'b0, A & B}; `OP_AND: Y = {1'b0, A & B};
`OP_XOR: Y = {1'b0, A ^ B}; `OP_XOR: Y = {1'b0, A ^ B};
`OP_INC: Y = A + 1;
`OP_DEC: Y = A - 1;
`OP_ADD: Y = A + B;
`OP_SUB: Y = A - B;
`OP_ASL: Y = A + A;
`OP_LSR: Y = {A[0], A >> 1};
default: Y = 9'bx; default: Y = 9'bx;
endcase endcase
endmodule endmodule
`define REG_A 1'b0 /*
`define REG_B 1'b1 Bits Description
`define I_CONST(r,x) { 2'b00, r, x }
`define I_LOAD_ADDR(r,addr) { 3'b010, r, addr } 00ddaaaa A + B -> dest
`define I_STORE_ADDR(r,addr) { 3'b011, r, addr } 01ddaaaa A + immediate -> dest
`define I_COMPUTE(r,op) { 3'b100, r, op } 11ddaaaa A + read [B] -> dest
`define I_RESET 8'hff 10000001 swap A <-> B
1001nnnn A -> write [nnnn]
1010tttt conditional branch
dd = destination (00=A, 01=B, 10=IP, 11=none)
aaaa = ALU operation (replaces + operator)
nnnn = 4-bit constant
tttt = flags test for conditional branch
*/
`define DEST_A 2'b00
`define DEST_B 2'b01
`define DEST_IP 2'b10
`define DEST_NOP 2'b11
`define I_COMPUTE(dest,op) { 2'b00, 2'(dest), 4'(op) }
`define I_COMPUTE_IMM(dest,op) { 2'b01, 2'(dest), 4'(op) }
`define I_COMPUTE_READB(dest,op) { 2'b11, 2'(dest), 4'(op) }
`define I_CONST_IMM_A { 2'b01, `DEST_A, `OP_LOAD_B }
`define I_CONST_IMM_B { 2'b01, `DEST_B, `OP_LOAD_B }
`define I_JUMP_IMM { 2'b01, `DEST_IP, `OP_LOAD_B }
`define I_STORE_A(addr) { 4'b1001, 4'(addr) }
`define I_BRANCH_IF_CARRY(carry) { 4'b1010, 2'b00, 1'(carry), 1'b1 }
`define I_SWAP_AB { 8'b10000001 }
`define I_RESET { 8'b10111111 }
module CPU( module CPU(
input clk, input clk,
@ -53,9 +79,7 @@ module CPU(
output write output write
); );
reg [7:0] ip; reg [7:0] IP;
reg [7:0] opcode;
reg [3:0] aluop;
reg [7:0] A, B; reg [7:0] A, B;
reg [8:0] Y; reg [8:0] Y;
reg [2:0] state; reg [2:0] state;
@ -63,17 +87,19 @@ module CPU(
reg carry; reg carry;
reg zero; reg zero;
wire [1:0] flags = { zero, carry }; wire [1:0] flags = { zero, carry };
reg [7:0] opcode;
wire [3:0] aluop = opcode[3:0];
wire [1:0] opdest = opcode[5:4];
wire memalu = opcode[6];
localparam S_RESET = 0; localparam S_RESET = 0;
localparam S_SELECT = 1; localparam S_SELECT = 1;
localparam S_DECODE = 2; localparam S_DECODE = 2;
localparam S_LOAD_ADDR = 3; localparam S_COMPUTE = 3;
localparam S_STORE_ADDR = 4; localparam S_READ_IP = 4;
localparam S_COMPUTE = 5;
wire load_const = opcode[3:1] == 3'b111; ALU alu(.A(A), .B(memalu?data_in:B), .Y(Y), .aluop(aluop));
ALU alu(.A(A), .B(B), .Y(Y), .aluop(aluop));
always @(posedge clk) always @(posedge clk)
if (reset) begin if (reset) begin
@ -83,75 +109,87 @@ module CPU(
case (state) case (state)
// state 0: reset // state 0: reset
S_RESET: begin S_RESET: begin
ip <= 8'h80; IP <= 8'h80;
write <= 0; write <= 0;
state <= S_SELECT; state <= S_SELECT;
end end
// state 1: select opcode address // state 1: select opcode address
S_SELECT: begin S_SELECT: begin
address <= ip; address <= IP;
ip <= ip + 1; IP <= IP + 1;
write <= 0; write <= 0;
state <= S_DECODE; state <= S_DECODE;
end end
// state 2: read/decode opcode // state 2: read/decode opcode
S_DECODE: begin S_DECODE: begin
opcode <= data_in;
casez (data_in) casez (data_in)
8'b00??????: begin // load constant // ALU A + B -> dest
if (data_in[5]) 8'b00??????: begin
B <= {3'b0, data_in[4:0]};
else
A <= {3'b0, data_in[4:0]};
state <= S_SELECT;
end
8'b010?????: begin // read memory
address <= {4'b0, data_in[3:0]};
state <= S_LOAD_ADDR;
end
8'b011?????: begin // write memory
address <= {4'b0, data_in[3:0]};
state <= S_STORE_ADDR;
end
8'b100?????: begin // compute w/ ALU
aluop <= data_in[3:0];
state <= S_COMPUTE; state <= S_COMPUTE;
end end
8'b101000??: begin // branch if flag set/clear // ALU A + immediate -> dest
if ((data_in[0] ? carry : zero) ^ data_in[1]) 8'b01??????: begin
ip <= A; address <= IP;
IP <= IP + 1;
state <= S_COMPUTE;
end
// ALU A + read [B] -> dest
8'b11??????: begin
address <= B;
state <= S_COMPUTE;
end
// A -> write [aluop]
8'b1001????: begin
address <= {4'b0, aluop};
data_out <= A;
write <= 1;
state <= S_SELECT; state <= S_SELECT;
end end
// swap A,B
8'b10000001: begin
A <= B;
B <= A;
state <= S_SELECT;
end
// conditional branch
8'b1010????: begin
if (
(data_in[0] && (data_in[1] == carry)) ||
(data_in[2] && (data_in[3] == zero)))
begin
address <= IP;
state <= S_READ_IP;
end else begin
state <= S_SELECT;
end
IP <= IP + 1; // skip immediate
end
// fall-through RESET
default: begin default: begin
state <= S_RESET; // reset state <= S_RESET; // reset
end end
endcase endcase
opcode <= data_in;
end end
// state 3: load address // state 3: compute ALU op and flags
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 S_COMPUTE: begin
if (opcode[4]) // transfer ALU output to destination
B <= Y[7:0]; case (opdest)
else `DEST_A: A <= Y[7:0];
A <= Y[7:0]; `DEST_B: B <= Y[7:0];
carry <= Y[8]; `DEST_IP: IP <= Y[7:0];
`DEST_NOP: ;
endcase
// set carry for certain operations (code >= 8)
if (aluop[3]) carry <= Y[8];
// set zero flag
zero <= ~|Y; zero <= ~|Y;
// repeat CPU loop
state <= S_SELECT;
end
// state 4: read new IP from memory (immediate mode)
S_READ_IP: begin
IP <= data_in;
state <= S_SELECT; state <= S_SELECT;
end end
endcase endcase
@ -165,11 +203,18 @@ module test_CPU_top(
output [7:0] address_bus, output [7:0] address_bus,
output reg [7:0] to_cpu, output reg [7:0] to_cpu,
output [7:0] from_cpu, output [7:0] from_cpu,
output write_enable output write_enable,
output [7:0] IP,
output [7:0] A,
output [7:0] B
); );
reg [7:0] ram[127:0]; reg [7:0] ram[0:127];
reg [7:0] rom[127:0]; reg [7:0] rom[0:127];
assign IP = cpu.IP;
assign A = cpu.A;
assign B = cpu.B;
CPU cpu(.clk(clk), CPU cpu(.clk(clk),
.reset(reset), .reset(reset),
@ -188,16 +233,19 @@ module test_CPU_top(
to_cpu = rom[address_bus[6:0]]; to_cpu = rom[address_bus[6:0]];
initial begin initial begin
// address 0x80 rom = '{
rom['h00] = `I_CONST(`REG_A, 5'h1f); `I_CONST_IMM_A,
rom['h01] = `I_COMPUTE(`REG_A, `OP_ASL); 0,
rom['h02] = `I_COMPUTE(`REG_A, `OP_ASL); `I_CONST_IMM_B,
rom['h03] = `I_COMPUTE(`REG_A, `OP_ASL); 1,
rom['h04] = `I_COMPUTE(`REG_A, `OP_ASL); `I_COMPUTE(`DEST_A, `OP_ADD), // addr 4
rom['h05] = `I_COMPUTE(`REG_B, `OP_LOAD_A); `I_SWAP_AB,
rom['h06] = `I_STORE_ADDR(`REG_B, 4'd1); `I_BRANCH_IF_CARRY(0),
rom['h07] = `I_LOAD_ADDR(`REG_B, 4'd1); 4 + 'h80, // correct for ROM offset
rom['h08] = `I_RESET; `I_RESET,
// leftover elements
119{0}
};
end end
endmodule endmodule

View File

@ -10,80 +10,99 @@ module car_bitmap(yofs, bits);
assign bits = bitarray[yofs]; assign bits = bitarray[yofs];
initial begin/*{w:8,h:16}*/ initial begin/*{w:8,h:16}*/
bitarray[0] = 8'b110000; bitarray[0] = 8'b1100;
bitarray[1] = 8'b1110111; bitarray[1] = 8'b11001100;
bitarray[2] = 8'b11100110; bitarray[2] = 8'b11111100;
bitarray[3] = 8'b11111111; bitarray[3] = 8'b11101100;
bitarray[4] = 8'b11100110; bitarray[4] = 8'b11100000;
bitarray[5] = 8'b1100111; bitarray[5] = 8'b1100000;
bitarray[6] = 8'b110000; bitarray[6] = 8'b1110000;
bitarray[7] = 8'b110000; bitarray[7] = 8'b110000;
bitarray[8] = 8'b110000; bitarray[8] = 8'b110000;
bitarray[9] = 8'b1110000; bitarray[9] = 8'b110000;
bitarray[10] = 8'b1100000; bitarray[10] = 8'b1100111;
bitarray[11] = 8'b11100000; bitarray[11] = 8'b11100110;
bitarray[12] = 8'b11101100; bitarray[12] = 8'b11111111;
bitarray[13] = 8'b11111100; bitarray[13] = 8'b11100110;
bitarray[14] = 8'b11001100; bitarray[14] = 8'b1110111;
bitarray[15] = 8'b1100; bitarray[15] = 8'b110000;
end end
endmodule endmodule
module sprite_renderer(clk, vstart, load, hstart, rom_yofs, rom_bits, module sprite_renderer(clk, vstart, load, hstart, rom_addr, rom_bits,
gfx, in_progress); gfx, in_progress);
input clk, vstart, load, hstart; input clk, vstart, load, hstart;
output [3:0] rom_yofs; output [3:0] rom_addr;
input [7:0] rom_bits; input [7:0] rom_bits;
output gfx; output gfx;
output in_progress = yactive; output in_progress = state != WAIT_FOR_VSTART;
reg [2:0] state;
reg [3:0] ycount; reg [3:0] ycount;
reg [3:0] xcount; reg [3:0] xcount;
reg yactive;
reg xactive;
reg loading;
reg [7:0] outbits; reg [7:0] outbits;
localparam WAIT_FOR_VSTART = 0;
localparam WAIT_FOR_LOAD = 1;
localparam LOAD1_SETUP = 2;
localparam LOAD1_FETCH = 3;
localparam WAIT_FOR_HSTART = 4;
localparam DRAW = 5;
always @(posedge clk) always @(posedge clk)
begin begin
// set a default value (blank) for pixel output case (state)
// note: multiple non-blocking assignments are vendor-specific WAIT_FOR_VSTART: begin
gfx <= 0; ycount <= 0;
// load next line? set ROM address // set a default value (blank) for pixel output
if (yactive && load) begin // note: multiple non-blocking assignments are vendor-specific
rom_yofs <= ~ycount; gfx <= 0;
loading <= 1; if (vstart) state <= WAIT_FOR_LOAD;
// ROM address was set, now latch bits from bus end
end else if (loading) begin WAIT_FOR_LOAD: begin
outbits <= rom_bits; xcount <= 0;
loading <= 0; gfx <= 0;
ycount <= ycount + 1; if (load) state <= LOAD1_SETUP;
// start sprite at this vertical scanline end
end else if (vstart) begin LOAD1_SETUP: begin
yactive <= 1; rom_addr <= ycount;
//ycount <= 0; gfx <= 0;
// start sprite at this horizontal clock state <= LOAD1_FETCH;
end else if (hstart && yactive) begin end
xactive <= 1; LOAD1_FETCH: begin
//xcount <= 0; outbits[7:0] <= rom_bits;
// both X & Y active, set pixel output gfx <= 0;
end else if (xactive && yactive) state <= WAIT_FOR_HSTART;
begin end
WAIT_FOR_HSTART: begin
if (hstart) state <= DRAW;
gfx <= 0;
end
DRAW: begin
// mirror graphics left/right // mirror graphics left/right
gfx <= outbits[xcount[3]?~xcount[2:0]:xcount[2:0]]; gfx <= outbits[xcount<8 ? xcount[2:0] : ~xcount[2:0]];
xcount <= xcount + 1; xcount <= xcount + 1;
if (xcount == 15) begin // pre-increment value if (xcount == 15) begin // pre-increment value
xactive <= 0; // done drawing this scanline ycount <= ycount + 1;
if (ycount == 0) // post-increment value if (ycount == 15) // pre-increment value
yactive <= 0; // done drawing sprite state <= WAIT_FOR_VSTART; // done drawing sprite
else
state <= WAIT_FOR_LOAD; // done drawing this scanline
end end
end end
default: begin
state <= 0; // TODO: reset
gfx <= 0;
end
endcase
end end
endmodule endmodule
module test_top(clk, hsync, vsync, rgb, hpaddle, vpaddle); module test_top(clk, hsync, vsync, rgb, hpaddle, vpaddle);
input clk; input clk;
@ -127,7 +146,7 @@ module test_top(clk, hsync, vsync, rgb, hpaddle, vpaddle);
.vstart(vstart), .vstart(vstart),
.load(hsync), .load(hsync),
.hstart(hstart), .hstart(hstart),
.rom_yofs(car_sprite_yofs), .rom_addr(car_sprite_yofs),
.rom_bits(car_sprite_bits), .rom_bits(car_sprite_bits),
.gfx(car_gfx), .gfx(car_gfx),
.in_progress(unused)); .in_progress(unused));

View File

@ -159,6 +159,15 @@ function PixelEditor(parentDiv, fmt, palette, initialData, thumbnails) {
}); });
} }
function setPixels(p) {
var i = 0;
for (var y=0; y<height; y++) {
for (var x=0; x<width; x++) {
setPixel(x, y, p[i++]);
}
}
}
this.rotate = function(deg) { this.rotate = function(deg) {
console.log("rotate " + deg); console.log("rotate " + deg);
var s1 = Math.sin(deg * Math.PI / 180); var s1 = Math.sin(deg * Math.PI / 180);
@ -175,12 +184,35 @@ function PixelEditor(parentDiv, fmt, palette, initialData, thumbnails) {
p[i++] = col; p[i++] = col;
} }
} }
i = 0; setPixels(p);
commit();
}
this.flipy = function() {
console.log("flipy");
var p = self.getImageColors();
var i = 0;
for (var y=0; y<height; y++) { for (var y=0; y<height; y++) {
for (var x=0; x<width; x++) { for (var x=0; x<width; x++) {
setPixel(x, y, p[i++]); var col = getPixel(x, height-1-y);
p[i++] = col;
} }
} }
setPixels(p);
commit();
}
this.flipx = function() {
console.log("flipx");
var p = self.getImageColors();
var i = 0;
for (var y=0; y<height; y++) {
for (var x=0; x<width; x++) {
var col = getPixel(width-1-x, y);
p[i++] = col;
}
}
setPixels(p);
commit(); commit();
} }
} }
@ -472,6 +504,14 @@ function pixelEditorKeypress(e) {
case 36: // End case 36: // End
currentPixelEditor.rotate(45); currentPixelEditor.rotate(45);
break; break;
}
switch (e.charCode) {
case 104:
currentPixelEditor.flipx();
break;
case 118:
currentPixelEditor.flipy();
break;
default: default:
console.log(e); console.log(e);
break; break;

View File

@ -297,6 +297,24 @@ var VerilogPlatform = function(mainElement, options) {
gen.__unreset(); gen.__unreset();
} }
function shadowText(ctx, txt, x, y) {
ctx.shadowColor = "black";
ctx.shadowBlur = 0;
ctx.shadowOffsetY = -1;
ctx.shadowOffsetX = 0;
ctx.fillText(txt, x, y);
ctx.shadowOffsetY = 1;
ctx.shadowOffsetX = 0;
ctx.fillText(txt, x, y);
ctx.shadowOffsetY = 0;
ctx.shadowOffsetX = -1;
ctx.fillText(txt, x, y);
ctx.shadowOffsetY = 0;
ctx.shadowOffsetX = 1;
ctx.fillText(txt, x, y);
ctx.shadowOffsetX = 0;
}
function updateScopeFrame() { function updateScopeFrame() {
var arr = ports_and_signals; var arr = ports_and_signals;
if (!arr) return; if (!arr) return;
@ -348,17 +366,18 @@ var VerilogPlatform = function(mainElement, options) {
ctx.fillStyle = name == inspect_sym ? "yellow" : "white"; ctx.fillStyle = name == inspect_sym ? "yellow" : "white";
name = name.replace(/__DOT__/g,'.'); name = name.replace(/__DOT__/g,'.');
ctx.textAlign = 'left'; ctx.textAlign = 'left';
ctx.fillText(name, 1, yposlist[i]); ctx.fillStyle = "white";
shadowText(ctx, name, 1, yposlist[i]);
if (scope_time_x > 0) { if (scope_time_x > 0) {
ctx.textAlign = 'right'; ctx.textAlign = 'right';
var value = arr.length * scope_time_x + i + jstart; var value = arr.length * scope_time_x + i + jstart;
ctx.fillText(""+trace_buffer[value], videoWidth-1, yposlist[i]); shadowText(ctx, ""+trace_buffer[value], videoWidth-1, yposlist[i]);
} }
} }
// draw scope line & label // draw scope line & label
if (scope_time_x > 0) { if (scope_time_x > 0) {
ctx.fillStyle = "cyan"; ctx.fillStyle = "cyan";
ctx.fillText(""+(scope_time_x+scope_x_offset), shadowText(ctx, ""+(scope_time_x+scope_x_offset),
(scope_time_x>10)?(scope_time_x-2):(scope_time_x+20), videoHeight-2); (scope_time_x>10)?(scope_time_x-2):(scope_time_x+20), videoHeight-2);
ctx.fillRect(scope_time_x, 0, 1, 4000); ctx.fillRect(scope_time_x, 0, 1, 4000);
} }