`default_nettype none module hex_print(input wire [3:0] halfbyte, input wire [7:0] x, input wire [15:0] y, output wire pixel ); wire [0:7] number_0 [15:0]; wire [0:7] number_1 [15:0]; wire [0:7] number_2 [15:0]; wire [0:7] number_3 [15:0]; wire [0:7] number_4 [15:0]; wire [0:7] number_5 [15:0]; wire [0:7] number_6 [15:0]; wire [0:7] number_7 [15:0]; wire [0:7] number_8 [15:0]; wire [0:7] number_9 [15:0]; wire [0:7] letter_A [15:0]; wire [0:7] letter_B [15:0]; wire [0:7] letter_C [15:0]; wire [0:7] letter_D [15:0]; wire [0:7] letter_E [15:0]; wire [0:7] letter_F [15:0]; assign number_0[0] = 8'b00000000; assign number_0[1] = 8'b00011000; assign number_0[2] = 8'b00100100; assign number_0[3] = 8'b00100100; assign number_0[4] = 8'b01000110; assign number_0[5] = 8'b01001010; assign number_0[6] = 8'b01001010; assign number_0[7] = 8'b01001010; assign number_0[8] = 8'b01010010; assign number_0[9] = 8'b01010010; assign number_0[10] = 8'b01010010; assign number_0[11] = 8'b01100010; assign number_0[12] = 8'b00100100; assign number_0[13] = 8'b00100100; assign number_0[14] = 8'b00011000; assign number_0[15] = 8'b00000000; assign number_1[0] = 8'b00000000; assign number_1[1] = 8'b00001000; assign number_1[2] = 8'b00011000; assign number_1[3] = 8'b00111000; assign number_1[4] = 8'b00001000; assign number_1[5] = 8'b00001000; assign number_1[6] = 8'b00001000; assign number_1[7] = 8'b00001000; assign number_1[8] = 8'b00001000; assign number_1[9] = 8'b00001000; assign number_1[10] = 8'b00001000; assign number_1[11] = 8'b00001000; assign number_1[12] = 8'b00001000; assign number_1[13] = 8'b00001000; assign number_1[14] = 8'b00001000; assign number_1[15] = 8'b00000000; assign number_2[0] = 8'b00000000; assign number_2[1] = 8'b00111000; assign number_2[2] = 8'b01000100; assign number_2[3] = 8'b00000010; assign number_2[4] = 8'b00000010; assign number_2[5] = 8'b00000010; assign number_2[6] = 8'b00000010; assign number_2[7] = 8'b00000100; assign number_2[8] = 8'b00001000; assign number_2[9] = 8'b00010000; assign number_2[10] = 8'b00100000; assign number_2[11] = 8'b00100000; assign number_2[12] = 8'b01000000; assign number_2[13] = 8'b01000000; assign number_2[14] = 8'b01111110; assign number_2[15] = 8'b00000000; assign number_3[0] = 8'b00000000; assign number_3[1] = 8'b00111000; assign number_3[2] = 8'b01000100; assign number_3[3] = 8'b00000010; assign number_3[4] = 8'b00000010; assign number_3[5] = 8'b00000010; assign number_3[6] = 8'b00000100; assign number_3[7] = 8'b00011000; assign number_3[8] = 8'b00000100; assign number_3[9] = 8'b00000010; assign number_3[10] = 8'b00000010; assign number_3[11] = 8'b00000010; assign number_3[12] = 8'b00000010; assign number_3[13] = 8'b01000100; assign number_3[14] = 8'b00111000; assign number_3[15] = 8'b00000000; assign number_4[0] = 8'b00000000; assign number_4[1] = 8'b00001000; assign number_4[2] = 8'b00001000; assign number_4[3] = 8'b00010000; assign number_4[4] = 8'b00010000; assign number_4[5] = 8'b00100000; assign number_4[6] = 8'b00100000; assign number_4[7] = 8'b01000100; assign number_4[8] = 8'b01111110; assign number_4[9] = 8'b00000100; assign number_4[10] = 8'b00000100; assign number_4[11] = 8'b00000100; assign number_4[12] = 8'b00000100; assign number_4[13] = 8'b00000100; assign number_4[14] = 8'b00000100; assign number_4[15] = 8'b00000000; assign number_5[0] = 8'b00000000; assign number_5[1] = 8'b01111100; assign number_5[2] = 8'b01000000; assign number_5[3] = 8'b01000000; assign number_5[4] = 8'b01000000; assign number_5[5] = 8'b01000000; assign number_5[6] = 8'b01111000; assign number_5[7] = 8'b00000100; assign number_5[8] = 8'b00000010; assign number_5[9] = 8'b00000010; assign number_5[10] = 8'b00000010; assign number_5[11] = 8'b00000010; assign number_5[12] = 8'b00000010; assign number_5[13] = 8'b01000100; assign number_5[14] = 8'b00111000; assign number_5[15] = 8'b00000000; assign number_6[0] = 8'b00000000; assign number_6[1] = 8'b00001100; assign number_6[2] = 8'b00010000; assign number_6[3] = 8'b00100000; assign number_6[4] = 8'b00100000; assign number_6[5] = 8'b01000000; assign number_6[6] = 8'b01000000; assign number_6[7] = 8'b01011000; assign number_6[8] = 8'b01100100; assign number_6[9] = 8'b01000010; assign number_6[10] = 8'b01000010; assign number_6[11] = 8'b01000010; assign number_6[12] = 8'b01000010; assign number_6[13] = 8'b00100100; assign number_6[14] = 8'b00011000; assign number_6[15] = 8'b00000000; assign number_7[0] = 8'b00000000; assign number_7[1] = 8'b01111110; assign number_7[2] = 8'b00000010; assign number_7[3] = 8'b00000100; assign number_7[4] = 8'b00000100; assign number_7[5] = 8'b00001000; assign number_7[6] = 8'b00001000; assign number_7[7] = 8'b00111100; assign number_7[8] = 8'b00010000; assign number_7[9] = 8'b00010000; assign number_7[10] = 8'b00010000; assign number_7[11] = 8'b00100000; assign number_7[12] = 8'b00100000; assign number_7[13] = 8'b00100000; assign number_7[14] = 8'b00100000; assign number_7[15] = 8'b00000000; assign number_8[0] = 8'b00000000; assign number_8[1] = 8'b00011000; assign number_8[2] = 8'b00100100; assign number_8[3] = 8'b01000010; assign number_8[4] = 8'b01000010; assign number_8[5] = 8'b01000010; assign number_8[6] = 8'b00100100; assign number_8[7] = 8'b00011000; assign number_8[8] = 8'b00100100; assign number_8[9] = 8'b01000010; assign number_8[10] = 8'b01000010; assign number_8[11] = 8'b01000010; assign number_8[12] = 8'b01000010; assign number_8[13] = 8'b00100100; assign number_8[14] = 8'b00011000; assign number_8[15] = 8'b00000000; assign number_9[0] = 8'b00000000; assign number_9[1] = 8'b00011000; assign number_9[2] = 8'b00100100; assign number_9[3] = 8'b01000010; assign number_9[4] = 8'b01000010; assign number_9[5] = 8'b01000010; assign number_9[6] = 8'b01000010; assign number_9[7] = 8'b00100110; assign number_9[8] = 8'b00011010; assign number_9[9] = 8'b00000010; assign number_9[10] = 8'b00000010; assign number_9[11] = 8'b00000100; assign number_9[12] = 8'b00000100; assign number_9[13] = 8'b00001000; assign number_9[14] = 8'b00110000; assign number_9[15] = 8'b00000000; assign letter_A[0] = 8'b00000000; assign letter_A[1] = 8'b00011000; assign letter_A[2] = 8'b00100100; assign letter_A[3] = 8'b00100100; assign letter_A[4] = 8'b00100100; assign letter_A[5] = 8'b01000010; assign letter_A[6] = 8'b01000010; assign letter_A[7] = 8'b01000010; assign letter_A[8] = 8'b01111110; assign letter_A[9] = 8'b01000010; assign letter_A[10] = 8'b01000010; assign letter_A[11] = 8'b01000010; assign letter_A[12] = 8'b01000010; assign letter_A[13] = 8'b01000010; assign letter_A[14] = 8'b01000010; assign letter_A[15] = 8'b00000000; assign letter_B[0] = 8'b00000000; assign letter_B[1] = 8'b01111000; assign letter_B[2] = 8'b01000100; assign letter_B[3] = 8'b01000010; assign letter_B[4] = 8'b01000010; assign letter_B[5] = 8'b01000010; assign letter_B[6] = 8'b01000100; assign letter_B[7] = 8'b01111000; assign letter_B[8] = 8'b01000100; assign letter_B[9] = 8'b01000010; assign letter_B[10] = 8'b01000010; assign letter_B[11] = 8'b01000010; assign letter_B[12] = 8'b01000010; assign letter_B[13] = 8'b01000100; assign letter_B[14] = 8'b01111000; assign letter_B[15] = 8'b00000000; assign letter_C[0] = 8'b00000000; assign letter_C[1] = 8'b00011100; assign letter_C[2] = 8'b00100010; assign letter_C[3] = 8'b00100000; assign letter_C[4] = 8'b01000000; assign letter_C[5] = 8'b01000000; assign letter_C[6] = 8'b01000000; assign letter_C[7] = 8'b01000000; assign letter_C[8] = 8'b01000000; assign letter_C[9] = 8'b01000000; assign letter_C[10] = 8'b01000000; assign letter_C[11] = 8'b01000000; assign letter_C[12] = 8'b00100000; assign letter_C[13] = 8'b00100010; assign letter_C[14] = 8'b00011100; assign letter_C[15] = 8'b00000000; assign letter_D[0] = 8'b00000000; assign letter_D[1] = 8'b01110000; assign letter_D[2] = 8'b01001000; assign letter_D[3] = 8'b01000100; assign letter_D[4] = 8'b01000100; assign letter_D[5] = 8'b01000010; assign letter_D[6] = 8'b01000010; assign letter_D[7] = 8'b01000010; assign letter_D[8] = 8'b01000010; assign letter_D[9] = 8'b01000010; assign letter_D[10] = 8'b01000010; assign letter_D[11] = 8'b01000100; assign letter_D[12] = 8'b01000100; assign letter_D[13] = 8'b01001000; assign letter_D[14] = 8'b01110000; assign letter_D[15] = 8'b00000000; assign letter_E[0] = 8'b00000000; assign letter_E[1] = 8'b01111110; assign letter_E[2] = 8'b01000000; assign letter_E[3] = 8'b01000000; assign letter_E[4] = 8'b01000000; assign letter_E[5] = 8'b01000000; assign letter_E[6] = 8'b01000000; assign letter_E[7] = 8'b01111000; assign letter_E[8] = 8'b01000000; assign letter_E[9] = 8'b01000000; assign letter_E[10] = 8'b01000000; assign letter_E[11] = 8'b01000000; assign letter_E[12] = 8'b01000000; assign letter_E[13] = 8'b01000000; assign letter_E[14] = 8'b01111110; assign letter_E[15] = 8'b00000000; assign letter_F[0] = 8'b00000000; assign letter_F[1] = 8'b01111110; assign letter_F[2] = 8'b01000000; assign letter_F[3] = 8'b01000000; assign letter_F[4] = 8'b01000000; assign letter_F[5] = 8'b01000000; assign letter_F[6] = 8'b01000000; assign letter_F[7] = 8'b01111000; assign letter_F[8] = 8'b01000000; assign letter_F[9] = 8'b01000000; assign letter_F[10] = 8'b01000000; assign letter_F[11] = 8'b01000000; assign letter_F[12] = 8'b01000000; assign letter_F[13] = 8'b01000000; assign letter_F[14] = 8'b01000000; assign letter_F[15] = 8'b00000000; assign pixel = halfbyte == 0 ? number_0[y][x] : halfbyte == 1 ? number_1[y][x] : halfbyte == 2 ? number_2[y][x] : halfbyte == 3 ? number_3[y][x] : halfbyte == 4 ? number_4[y][x] : halfbyte == 5 ? number_5[y][x] : halfbyte == 6 ? number_6[y][x] : halfbyte == 7 ? number_7[y][x] : halfbyte == 8 ? number_8[y][x] : halfbyte == 9 ? number_9[y][x] : halfbyte == 10 ? letter_A[y][x] : halfbyte == 11 ? letter_B[y][x] : halfbyte == 12 ? letter_C[y][x] : halfbyte == 13 ? letter_D[y][x] : halfbyte == 14 ? letter_E[y][x] : letter_F[y][x]; endmodule module vga_timing(input wire clock_50mhz, input wire reset, output reg h_sync, output reg v_sync, output reg [9:0] col, output reg [8:0] row, output reg display_on, output wire pixel_starting, output wire row_starting); parameter h_pixels = 640; parameter v_pixels = 480; parameter h_front_porch = 16; parameter v_front_porch = 10; parameter h_pulse = 96; parameter v_pulse = 2; parameter h_back_porch = 48; parameter v_back_porch = 33; parameter h_pol = 1'b0; parameter v_pol = 1'b1; parameter h_pulse_start = h_front_porch; parameter v_pulse_start = v_front_porch; parameter h_pulse_end = h_front_porch + h_pulse; parameter v_pulse_end = v_front_porch + v_pulse; parameter h_active_video_start = h_front_porch + h_pulse + h_back_porch; parameter v_active_video_start = v_front_porch + v_pulse + v_back_porch; parameter h_frame_end = h_active_video_start + h_pixels; parameter v_frame_end = v_active_video_start + v_pixels; reg [9:0] h_counter; reg [9:0] v_counter; reg divider; // 25MHz wire display_on_next_tick; assign display_on_next_tick = (h_counter < h_frame_end - 1) && (h_counter >= h_active_video_start - 1) && (v_counter < v_frame_end) && (v_counter >= v_active_video_start); always @ (posedge clock_50mhz) begin if (reset) begin divider <= 1'b0; h_counter <= 0; v_counter <= 0; h_sync <= ~h_pol; v_sync <= ~v_pol; row <= 0; col <= 0; display_on <= 0; end // if (reset) else begin divider <= divider + 1; if (divider == 1'b1) begin display_on <= display_on_next_tick; if (h_counter < h_frame_end - 1) begin h_counter <= h_counter + 1; h_sync <= h_pol ^ (h_counter < h_pulse_start - 1 || h_counter >= h_pulse_end - 1); if (h_counter >= h_active_video_start) col <= col + 1; end else begin h_counter <= 0; col <= 0; if (v_counter < v_frame_end - 1) begin v_counter <= v_counter + 1; v_sync <= v_pol ^ (v_counter < v_pulse_start - 1 || v_counter >= v_pulse_end - 1); if (v_counter >= v_active_video_start) row <= row + 1; end else begin v_counter <= 0; row <= 0; end // else: !if(v_counter < v_frame_end - 1) end // else: !if(h_counter < h_frame_end - 1) end // if (divider == 1'b1) end // else: !if(reset) end // always @ (posedge clock_50mhz) assign pixel_starting = display_on && divider == 1'b0; assign row_starting = pixel_starting && col == 0; endmodule // vga_timing module vga_pass_colors(input wire clock_50mhz, input wire reset, input wire h_sync_next_tick, input wire v_sync_next_tick, input wire display_on_next_tick, input wire pixel_on_next_tick, output reg h_sync, output reg v_sync, output reg [2:0] vga_red, output reg [2:0] vga_green, output reg [2:0] vga_blue ); wire [8:0] color_next_tick; assign color_next_tick = !display_on_next_tick ? 0 : pixel_on_next_tick ? color1 : color2; parameter color1 = {3'b010, 3'b111, 3'b101}; parameter color2 = {3'b000, 3'b000, 3'b111}; always @ (posedge clock_50mhz) begin if (reset) begin h_sync <= 0; v_sync <= 0; vga_red <= 0; vga_green <= 0; vga_blue <= 0; end else begin h_sync <= h_sync_next_tick; v_sync <= v_sync_next_tick; vga_red <= color_next_tick[8:6]; vga_green <= color_next_tick[5:3]; vga_blue <= color_next_tick[2:0]; end // else: !if(reset) end // always @ (posedge clock_50mhz) endmodule // vga_pass_colors module vga_hexmode(input wire clock_50mhz, input wire reset, input wire can_read, input wire [15:0] read_data, output wire want_to_read, output wire [17:0] read_addr, input wire [17:0] displayed_memory_base, output wire h_sync, output wire v_sync, output wire [2:0] vga_red, output wire [2:0] vga_green, output wire [2:0] vga_blue ); wire [9:0] col_next_tick; wire [8:0] row_next_tick; wire h_sync_next_tick; wire v_sync_next_tick; wire display_on_next_tick; wire pixel_starting_next_tick; wire row_starting_next_tick; vga_timing timing(clock_50mhz, reset, h_sync_next_tick, v_sync_next_tick, col_next_tick, row_next_tick, display_on_next_tick, pixel_starting_next_tick, row_starting_next_tick); parameter queue_size = 4; /* will store 4 consecutive hex digits copied from read_data[15:0] */ reg [15:0] digits_queue; reg [1:0] digits_in_queue; parameter words_per_line = 20; parameter lines = 30; parameter words_per_screen = words_per_line * lines; parameter digit_h_pixels = 8; parameter digit_v_pixels = 16; parameter word_digits = 4; reg [2:0] digit_x; wire [2:0] subsequent_digit_x; assign subsequent_digit_x = digit_x == digit_h_pixels - 1 ? 0 : digit_x + 1; reg [3:0] digit_y; wire [3:0] subsequent_digit_y; assign subsequent_digit_y = digit_y == digit_v_pixels - 1 ? 0 : digit_y + 1; wire digit_starting_next_tick; assign digit_starting_next_tick = pixel_starting_next_tick && digit_x == digit_h_pixels - 1; wire line_starting_next_tick; assign line_starting_next_tick = row_starting_next_tick && digit_y == digit_v_pixels - 1; reg [4:0] word_in_line; reg [11:0] word_idx; wire [11:0] subsequent_word_idx; assign subsequent_word_idx = word_idx == words_per_screen - 1 ? 0 : word_idx + 1; assign read_addr = displayed_memory_base + word_idx; reg [3:0] current_digit; wire [3:0] digit_next_tick; assign digit_next_tick = digit_starting_next_tick ? digits_queue[15:12] : current_digit; wire pixel_on_next_tick; hex_print hex_print(digit_next_tick, pixel_starting_next_tick ? subsequent_digit_x : digit_x, row_starting_next_tick ? subsequent_digit_y : digit_y, pixel_on_next_tick); vga_pass_colors color_pass(clock_50mhz, reset, h_sync_next_tick, v_sync_next_tick, display_on_next_tick, pixel_on_next_tick, h_sync, v_sync, vga_red, vga_green, vga_blue); /* 0 - waiting for read; 1 - reading; 2 - reading done */ reg [1:0] reading_state; assign want_to_read = reading_state == 0 || (digit_starting_next_tick && digits_in_queue - 1 == 0); wire reading; /* If new read can start, the previous one is ignored */ assign reading = reading_state == 1 && !(want_to_read); reg [11:0] word_idx_at_some_point; reg [1:0] digits_in_queue_at_some_point; reg [1:0] reading_state_at_some_point; always @ (posedge clock_50mhz) begin if (reset) begin digits_queue <= 16'bxxxxxxxxxxxxxxxx; digits_in_queue <= 0; reading_state <= 0; digit_x <= digit_h_pixels - 1; digit_y <= digit_v_pixels - 1; word_in_line <= 0; word_idx <= 0; word_idx_at_some_point <= 0; digits_in_queue_at_some_point <= 0; reading_state_at_some_point <= 0; end else begin if (pixel_starting_next_tick && col_next_tick == 3 && row_next_tick == 1) begin word_idx_at_some_point <= word_idx; digits_in_queue_at_some_point <= digits_in_queue; reading_state_at_some_point <= reading_state; end if (pixel_starting_next_tick) digit_x <= subsequent_digit_x; if (digit_starting_next_tick) begin current_digit <= digit_next_tick; /* * Once there's only 1 digit in the queue, word_idx shall * already be pointing at the next address. */ if (digits_in_queue - 3 == 0) begin if (word_in_line == words_per_line - 1) begin word_in_line <= 0; if (digit_y == digit_v_pixels - 1) word_idx <= subsequent_word_idx; else word_idx <= word_idx - (words_per_line - 1); end else begin word_in_line <= word_in_line + 1; word_idx <= subsequent_word_idx; end end /* * Hopefully read will always finish before we pop the next digit * from the queue. But we still need to avoid multiple drivers. */ if (!reading) digits_queue <= {digits_queue[11:0], 4'bxxxx}; end if (row_starting_next_tick) digit_y <= subsequent_digit_y; digits_in_queue <= digits_in_queue + (reading ? queue_size : 0) - (digit_starting_next_tick ? 1 : 0); if (want_to_read) begin if (can_read) reading_state <= 1; else reading_state <= 0; end else if (reading_state == 1) begin reading_state <= 2; digits_queue <= read_data; end end // else: !if(reset) end // always @ (posedge clock_50mhz) endmodule module on_button_write(input wire clock_50mhz, input wire reset, input wire can_write, output reg [15:0] write_data, output wire want_to_write, output wire [17:0] write_addr, input wire [17:0] written_memory_base, input wire but ); reg button_pressed; /* 0 - waiting for write, 1 - writing, 2 - write complete */ reg [1:0] write_state; parameter cooldown_start = 25'b111111111111111111111111; reg [23:0] but_cooldown; reg [4:0] write_idx; assign write_addr = written_memory_base + write_idx; wire perform_action; assign perform_action = button_pressed && !but_cooldown; assign want_to_write = perform_action || write_state == 0; always @ (posedge clock_50mhz) begin if (reset) begin but_cooldown <= cooldown_start; write_data <= 16'b000100000000000; write_state <= 2; write_idx <= 0; button_pressed <= 0; end else begin button_pressed <= !but; if (perform_action) but_cooldown <= cooldown_start; else if (but_cooldown) but_cooldown <= but_cooldown - 1; if (want_to_write) begin if (can_write) write_state <= 1; else write_state <= 0; end else if (write_state == 1) begin write_state <= 2; write_data <= write_data + 1; write_idx <= write_idx >= 30 ? 0 : write_idx + 1; end end end // always @ (posedge clock_50mhz) endmodule module dumb_write(input wire clock_50mhz, input wire reset, input wire can_write, output wire [15:0] write_data, output wire want_to_write, output wire [17:0] write_addr, input wire [17:0] written_memory_base, input wire start_operating ); reg [9:0] write_idx; /* To each word we'll be writing its offset from written_memory_base */ assign write_data = write_idx; assign write_addr = written_memory_base + write_idx; parameter max_idx = 599; reg operating; assign want_to_write = operating; reg [1:0] write_state; always @ (posedge clock_50mhz) begin if (reset) begin write_idx <= 10'bxxxxxxxxxx; operating <= 0; end else begin if (start_operating && !operating) begin operating <= 1; write_state <= 0; write_idx <= 0; end else if (operating) begin if (can_write) begin write_idx <= write_idx + 1; if (write_idx == max_idx) operating <= 0; end end end // else: !if(reset) end // always @ (posedge clock_50mhz) endmodule // dumb_write module top(input wire clock_100mhz, input wire but1, input wire but2, output reg [17:0] sram_addr, inout wire [15:0] sram_io, output reg sram_cs_n, output reg sram_oe_n, output reg sram_we_n, output wire h_sync, output wire v_sync, output wire [2:0] vga_red, output wire [2:0] vga_green, output wire [2:0] vga_blue, output wire sdo, input wire sdi, output wire sck, output wire ss_n ); reg reset; reg err_disabled; reg clock_50mhz; always @ (posedge clock_100mhz) clock_50mhz <= clock_50mhz + 1; parameter memory_base = 18'b010101010101010101; wire vga_io_available; assign vga_io_available = 1; wire vga_wants_io; wire [17:0] vga_io_addr; vga_hexmode vga(clock_50mhz, reset, vga_io_available, sram_io, vga_wants_io, vga_io_addr, memory_base, h_sync, v_sync, vga_red, vga_green, vga_blue); reg last_reset; always @ (posedge clock_50mhz) last_reset <= reset; wire dumbwrite_io_available; assign dumbwrite_io_available = vga_io_available && !vga_wants_io; wire dumbwrite_wants_io; wire [17:0] dumbwrite_io_addr; wire [15:0] dumbwrite_write_data; dumb_write dumbwrite(clock_50mhz, reset, dumbwrite_io_available, dumbwrite_write_data, dumbwrite_wants_io, dumbwrite_io_addr, memory_base, !reset && last_reset); wire butwrite_io_available; assign butwrite_io_available = dumbwrite_io_available && !dumbwrite_wants_io; wire butwrite_wants_io; wire [17:0] butwrite_io_addr; wire [15:0] butwrite_write_data; on_button_write butwrite(clock_50mhz, reset, butwrite_io_available, butwrite_write_data, butwrite_wants_io, butwrite_io_addr, memory_base, but2); reg [15:0] write_data; reg write_in_progress; always @ (posedge clock_50mhz) begin reset <= !but1 || err_disabled; if (!but1) err_disabled <= 0; if (reset) begin err_disabled <= 0; write_in_progress <= 0; sram_oe_n <= 1'b1; sram_cs_n <= 1'b1; write_data <= 16'bxxxxxxxxxxxxxxxx; end else begin if (vga_wants_io) begin write_in_progress <= 0; sram_oe_n <= 1'b0; sram_cs_n <= 1'b0; sram_addr <= vga_io_addr; end else if (dumbwrite_wants_io) begin write_in_progress <= 1; sram_oe_n <= 1'b1; sram_cs_n <= 1'b0; sram_addr <= dumbwrite_io_addr; write_data <= dumbwrite_write_data; end else if (butwrite_wants_io) begin write_in_progress <= 1; sram_oe_n <= 1'b1; sram_cs_n <= 1'b0; sram_addr <= butwrite_io_addr; write_data <= butwrite_write_data; if (butwrite_io_addr > memory_base + 30) err_disabled <= 1; end else begin write_in_progress <= 0; sram_oe_n <= 1'b1; sram_cs_n <= 1'b1; end end end // always @ (posedge clock_50mhz) always @ (negedge clock_100mhz) begin if (reset) begin sram_we_n <= 1'b1; end else begin if (write_in_progress) sram_we_n <= !sram_we_n; else sram_we_n <= 1'b1; end end assign sram_io = sram_we_n ? 16'bzzzzzzzzzzzzzzzz : write_data; assign sdo = sdi; assign sck = 1; assign ss_n = 1; endmodule // top