Skip to content

Commit

Permalink
initial reset support. set pin 48 to 1 to reset
Browse files Browse the repository at this point in the history
  • Loading branch information
nand2mario committed Sep 24, 2023
1 parent 758b867 commit ed3fede
Show file tree
Hide file tree
Showing 5 changed files with 166 additions and 101 deletions.
58 changes: 47 additions & 11 deletions src/nes2hdmi.sv
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,11 @@ module nes2hdmi (

wire [15:0] mem_portB_addr;
logic [5:0] mem_portB_rdata;


logic initializing = 1;
logic [7:0] init_y = 0;
logic [7:0] init_x = 0;

// BRAM port A read/write
always_ff @(posedge clk) begin
if (mem_portA_we) begin
Expand All @@ -66,27 +70,59 @@ module nes2hdmi (
// BRAM port B read
always_ff @(posedge clk_pixel) begin
mem_portB_rdata <= mem[mem_portB_addr];
// mem_portB_rdata <= mem_portB_addr[13:8];
end

initial begin
$readmemb("background.txt", mem);
// $readmemb("nes_fb_testpattern_palette.txt", mem);
end

localparam [0:65] LOGO [0:12] = '{
'b11110000110011111111001111001111111110000000000000000000000000000,
'b11110000110011111111011111101111111110000000000000000000000000000,
'b11111000110011100000011100100001110000000000000000000000000000000,
'b11111000110011100000011100000001110000011111000111111100001111110,
'b11011100110011111110001110000001110000110011100111001110011100111,
'b11001110110011111110000111000001110000000011100110001110011000111,
'b11001111110011000000000011100001110000111111100110001110111000111,
'b11000111110011000000110011100001110001111111100110001110111000111,
'b11000011110011111110111111100001100001110011100110001110011001111,
'b11000011110011111110011111000001100000111111100110001110001111111,
'b00000000000000000000000000000000000000000000000000000000000000111,
'b00000000000000000000000000000000000000000000000000000000011001110,
'b00000000000000000000000000000000000000000000000000000000011111100
};

//
// Data input
// Data input and initial background loading
//
logic [8:0] r_scanline;
logic [8:0] r_cycle;
always @(posedge clk) begin
r_scanline <= scanline;
r_cycle <= cycle;
mem_portA_we <= 1'b0;
if ((r_scanline != scanline || r_cycle != cycle) && scanline < 9'd240 && ~cycle[8]) begin
mem_portA_addr <= {scanline[7:0], cycle[7:0]};
mem_portA_wdata <= color;
mem_portA_we <= 1'b1;
if (~resetn) begin
initializing <= 1;
init_y <= 0;
init_x <= 0;
mem_portA_we <= 0;
end else if (initializing) begin // setup background at initialization
init_x <= init_x + 1;
init_y <= init_x == 255 ? init_y + 1 : init_y;
if (init_y == 240)
initializing <= 0;
mem_portA_we <= 1;
mem_portA_addr <= {init_y, init_x};
if (init_x >= 96 && init_x <= 160 && init_y >= 212 && init_y <= 224 && LOGO[init_y - 212][init_x - 96])
mem_portA_wdata <= 4; // blue logo
else
mem_portA_wdata <= 13; // black
end else begin
r_scanline <= scanline;
r_cycle <= cycle;
mem_portA_we <= 1'b0;
if ((r_scanline != scanline || r_cycle != cycle) && scanline < 9'd240 && ~cycle[8]) begin
mem_portA_addr <= {scanline[7:0], cycle[7:0]};
mem_portA_wdata <= color;
mem_portA_we <= 1'b1;
end
end
end

Expand Down
8 changes: 4 additions & 4 deletions src/nes_tang20k.v
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@

module NES_Tang20k(
input sys_clk,
// input sys_resetn,
// input d7,
// Button S1

// Button S1 and pin 48 are both resets
input s1,
input reset2,

// UART
input UART_RXD,
Expand Down Expand Up @@ -70,7 +70,7 @@ reg [7:0] reset_cnt = 255; // reset for 255 cycles before start everything
always @(posedge clk) begin
reset_cnt <= reset_cnt == 0 ? 0 : reset_cnt - 1;
if (reset_cnt == 0)
sys_resetn <= ~s1;
sys_resetn <= ~s1 & ~reset2;
end

`ifndef VERILATOR
Expand Down
3 changes: 3 additions & 0 deletions src/nestang.cst
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,11 @@ IO_PORT "sys_clk" IO_TYPE=LVCMOS33 PULL_MODE=NONE;
// IO_LOC "sys_resetn" T2;
// IO_PORT "sys_resetn" PULL_MODE=NONE;

// S1 and pin 48 are both resets
IO_LOC "s1" 88;
IO_PORT "s1" PULL_MODE=NONE;
IO_LOC "reset2" 48;
IO_PORT "reset2" PULL_MODE=DOWN;

// HDMI
IO_LOC "tmds_clk_p" 33;
Expand Down
183 changes: 97 additions & 86 deletions src/usb_hid_host.v
Original file line number Diff line number Diff line change
Expand Up @@ -67,102 +67,112 @@ assign dbg_hid_report = {dat[7], dat[6], dat[5], dat[4], dat[3], dat[2], dat[1],
reg valid = 0; // whether current gamepad report is valid

always @(posedge usbclk) begin : process_in_data
data_rdy_r <= data_rdy; data_strobe_r <= data_strobe;
report <= 0; // ensure pulse
if (report == 1) begin
// clear mouse movement for later
mouse_dx <= 0; mouse_dy <= 0;
end
if(~data_rdy) rcvct <= 0;
else begin
if(data_strobe && ~data_strobe_r) begin // rising edge of ukp data strobe
dat[rcvct] <= ukpdat;
if (~usbrst_n) begin
valid <= 0;
report <= 0;
{game_l, game_r, game_u, game_d, game_a, game_b, game_x, game_y, game_sel, game_sta} <= 0;
end else begin
data_rdy_r <= data_rdy; data_strobe_r <= data_strobe;
report <= 0; // ensure pulse
if (report == 1) begin
// clear mouse movement for later
mouse_dx <= 0; mouse_dy <= 0;
end
if(~data_rdy) rcvct <= 0;
else begin
if(data_strobe && ~data_strobe_r) begin // rising edge of ukp data strobe
dat[rcvct] <= ukpdat;

if (typ == 1) begin // keyboard
case (rcvct)
0: key_modifiers <= ukpdat;
2: key1 <= ukpdat;
3: key2 <= ukpdat;
4: key3 <= ukpdat;
5: key4 <= ukpdat;
endcase
end else if (typ == 2) begin // mouse
case (rcvct)
0: mouse_btn <= ukpdat;
1: mouse_dx <= ukpdat;
2: mouse_dy <= ukpdat;
endcase
end else if (typ == 3) begin // gamepad
// A typical report layout:
// - d[3] is X axis (0: left, 255: right)
// - d[4] is Y axis
// - d[5][7:4] is buttons YBAX
// - d[6][5:4] is buttons START,SELECT
// Variations:
// - Some gamepads uses d[0] and d[1] for X and Y axis.
// - Some transmits a different set when d[0][1:0] is 2 (a dualshock adapater)
case (rcvct)
0: begin
if (ukpdat[1:0] != 2'b10) begin
// for DualShock2 adapter, 2'b10 marks an irrelevant record
valid <= 1;
game_l <= 0; game_r <= 0; game_u <= 0; game_d <= 0;
end else
valid <= 0;
if (ukpdat==8'h00) {game_l, game_r} <= 2'b10;
if (ukpdat==8'hff) {game_l, game_r} <= 2'b01;
end
1: begin
if (ukpdat==8'h00) {game_u, game_d} <= 2'b10;
if (ukpdat==8'hff) {game_u, game_d} <= 2'b01;
end
3: if (valid) begin
if (ukpdat[7:6]==2'b00) {game_l, game_r} <= 2'b10;
if (ukpdat[7:6]==2'b11) {game_l, game_r} <= 2'b01;
end
4: if (valid) begin
if (ukpdat[7:6]==2'b00) {game_u, game_d} <= 2'b10;
if (ukpdat[7:6]==2'b11) {game_u, game_d} <= 2'b01;
end
5: if (valid) begin
game_x <= ukpdat[4];
game_a <= ukpdat[5];
game_b <= ukpdat[6];
game_y <= ukpdat[7];
end
6: if (valid) begin
game_sel <= ukpdat[4];
game_sta <= ukpdat[5];
if (typ == 1) begin // keyboard
case (rcvct)
0: key_modifiers <= ukpdat;
2: key1 <= ukpdat;
3: key2 <= ukpdat;
4: key3 <= ukpdat;
5: key4 <= ukpdat;
endcase
end else if (typ == 2) begin // mouse
case (rcvct)
0: mouse_btn <= ukpdat;
1: mouse_dx <= ukpdat;
2: mouse_dy <= ukpdat;
endcase
end else if (typ == 3) begin // gamepad
// A typical report layout:
// - d[3] is X axis (0: left, 255: right)
// - d[4] is Y axis
// - d[5][7:4] is buttons YBAX
// - d[6][5:4] is buttons START,SELECT
// Variations:
// - Some gamepads uses d[0] and d[1] for X and Y axis.
// - Some transmits a different set when d[0][1:0] is 2 (a dualshock adapater)
case (rcvct)
0: begin
if (ukpdat[1:0] != 2'b10) begin
// for DualShock2 adapter, 2'b10 marks an irrelevant record
valid <= 1;
game_l <= 0; game_r <= 0; game_u <= 0; game_d <= 0;
end else
valid <= 0;
if (ukpdat==8'h00) {game_l, game_r} <= 2'b10;
if (ukpdat==8'hff) {game_l, game_r} <= 2'b01;
end
1: begin
if (ukpdat==8'h00) {game_u, game_d} <= 2'b10;
if (ukpdat==8'hff) {game_u, game_d} <= 2'b01;
end
3: if (valid) begin
if (ukpdat[7:6]==2'b00) {game_l, game_r} <= 2'b10;
if (ukpdat[7:6]==2'b11) {game_l, game_r} <= 2'b01;
end
4: if (valid) begin
if (ukpdat[7:6]==2'b00) {game_u, game_d} <= 2'b10;
if (ukpdat[7:6]==2'b11) {game_u, game_d} <= 2'b01;
end
5: if (valid) begin
game_x <= ukpdat[4];
game_a <= ukpdat[5];
game_b <= ukpdat[6];
game_y <= ukpdat[7];
end
6: if (valid) begin
game_sel <= ukpdat[4];
game_sta <= ukpdat[5];
end
endcase
// TODO: add any special handling if needed
// (using the detected controller type in 'dev')
end
endcase
// TODO: add any special handling if needed
// (using the detected controller type in 'dev')
rcvct <= rcvct + 1;
end
rcvct <= rcvct + 1;
end
if(~data_rdy && data_rdy_r && typ != 0) // falling edge of ukp data ready
report <= 1;
end
if(~data_rdy && data_rdy_r && typ != 0) // falling edge of ukp data ready
report <= 1;
end

reg save_delayed;
reg connected_r;
always @(posedge usbclk) begin : response_recognition
save_delayed <= save;
if (save) begin
regs[save_r] <= dat[save_b];
end else if (save_delayed && ~save && save_r == 6) begin
// falling edge of save for bInterfaceProtocol
if (regs[4] == 3) begin // bInterfaceClass. 3: HID, other: non-HID
if (regs[5] == 1) // bInterfaceSubClass. 1: Boot device
typ <= regs[6] == 1 ? 1 : 2; // bInterfaceProtocol. 1: keyboard, 2: mouse
else
typ <= 3; // gamepad
end else
typ <= 0;
if (~usbrst_n) begin
typ <= 0;
end else begin
save_delayed <= save;
if (save) begin
regs[save_r] <= dat[save_b];
end else if (save_delayed && ~save && save_r == 6) begin
// falling edge of save for bInterfaceProtocol
if (regs[4] == 3) begin // bInterfaceClass. 3: HID, other: non-HID
if (regs[5] == 1) // bInterfaceSubClass. 1: Boot device
typ <= regs[6] == 1 ? 1 : 2; // bInterfaceProtocol. 1: keyboard, 2: mouse
else
typ <= 3; // gamepad
end else
typ <= 0;
end
connected_r <= connected;
if (~connected & connected_r) typ <= 0; // clear device type on disconnect
end
connected_r <= connected;
if (~connected & connected_r) typ <= 0; // clear device type on disconnect
end

endmodule
Expand Down Expand Up @@ -226,14 +236,15 @@ module ukp(
wire record;
reg dmid;
reg [23:0] conct;
assign conerr = conct[23] || ~usbrst_n;
assign conerr = conct[23]; // || ~usbrst_n;

usb_hid_host_rom ukprom(.clk(usbclk), .adr(pc), .data(inst));

always @(posedge usbclk) begin
if(~usbrst_n) begin
pc <= 0; connected <= 0; cond <= 0; inst_ready <= 0; state <= S_OPCODE; timing <= 0;
mbit <= 0; bitadr <= 0; nak <= 1; ug <= 0;
dpi <= usb_dp; dmi <= usb_dm;
end else begin
dpi <= usb_dp; dmi <= usb_dm;
save <= 0; // ensure pulse
Expand Down
15 changes: 15 additions & 0 deletions tools/nes2img.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,25 @@ def writeBackBinary():
png = os.path.join(os.path.dirname(__file__), 'back.png')
with Image.open(png) as im:
img = image2nes(im)
# find bounding box of logo
l=256
r=0
t=240
b=0
with open(BIN, 'w') as bin_file:
for i in range(240): # print image for debug
for j in range(256):
bin_file.write('{:06b}\n'.format(img[i][j]))
if img[i][j] != 13:
l = min(j, l)
r = max(j, r)
t = min(i, t)
b = max(i, b)
print('left={}, right={}, top={}, bottom={}'.format(l, r, t, b))
for y in range(t, b+1):
for x in range(l, r+1):
print('{}'.format('1' if img[y][x] == 4 else '0'), end='')
print('')

if BIN != '': # Just write background as binary file
writeBackBinary()
Expand Down

0 comments on commit ed3fede

Please sign in to comment.