/* * This wb slave controls buttons, LEDs (only one LED, actually) and timer. * * Registers and their addresses: * button2 clicks - address 1 * led2 state - address 3 * timer (low bits) - address 4 * timer (high bits) - address 5 * Addresses 0, 2, 6 and 7 are not used (undefined contents). * * The button register resets to 0. Its content increases by 1 * every time button is clicked. Button register can also be set to an arbitrary * value by writing to it. * * Writing any non-0 value to led register causes led to be turned on. * Writing 0 to led register causes led to be turned off. Reading * led register gives hFFFF if led is on or h0000 otherwire. Led is * switched off on reset. * * Timer has 32 bits and increases by one every clock tick. It starts * with value 0 on reset. Low 16 bits of timer and high 16 bits of timer are * available at addresses 4 and 5, respectively. Those addresses can also be * written to, if one desires to set the clock to a certain value. Care must * be taken when reading the timer, because between the read of first * and second half, the bottom part might overlap to 0, causing the high part * to increase by 1. Because of that, the correct procedure is to read one of * timer registers twice and compare the values. Of course, when measuring * very short or very long times, it might be justifiable to only read one half * of the timer. */ `default_nettype none module miscellaneous_slave #( /* * Assuming CLK_I is 12.5 MHz, we'd need around 22 and half a bit * to achieve half-second cooldown. Passig a lower value here makes * it easier to create a simulation that uses buttons and also manages * to finish running b4 trumpets for the last judgement sound... */ parameter BUTTON_COOLDOWN_BITS = 17 ) ( output wire ACK_O, input wire CLK_I, input wire [2:0] ADR_I, input wire [15:0] DAT_I, output wire [15:0] DAT_O, input wire RST_I, input wire STB_I, input wire WE_I, output wire STALL_O, /* Non-wishbone */ /* no button1, since it is reserved to be used as reset button */ input wire button2, /* no led2, since it is reserved for signalling when cpu stops operating */ output wire led2 ); reg [15:0] button2_clicks; reg [1:0] button2_latched; /* * After button is released we measure a cooldown time b4 recording another * click. Without this, a single button click could be recorded as many * clicks (I know from my own experience with the board). */ reg [BUTTON_COOLDOWN_BITS-1:0] button2_cooldown; reg led2_state; assign led2 = ~led2_state; reg [31:0] timer_count; reg [15:0] output_data; reg ack; assign DAT_O = output_data; assign ACK_O = ack; assign STALL_O = 0; always @ (posedge CLK_I) begin /* Latch and also invert button signals (the inputs are active low) */ button2_latched <= {button2_latched[0], ~button2}; if (!button2_cooldown && button2_latched == 2'b01) button2_clicks <= button2_clicks + 1; /* might get overwritten below */ if (button2_latched[0]) button2_cooldown <= -1; else if (button2_cooldown) button2_cooldown <= button2_cooldown - 1; /* might get overwritten below */ output_data <= 16'hXXXX; /* might get overwritten below */ if (RST_I) begin ack <= 0; button2_clicks <= 0; button2_cooldown <= -1; led2_state <= 0; timer_count <= 0; end else begin ack <= STB_I; timer_count <= timer_count + 1; if (STB_I) begin case (ADR_I) 1 : begin output_data <= button2_clicks; if (WE_I) button2_clicks <= DAT_I; end 3 : begin output_data <= {16{led2_state}}; if (WE_I) led2_state <= DAT_I != 0; end 4 : begin output_data <= timer_count[15:0]; if (WE_I) timer_count[15:0] <= DAT_I; end 5 : begin output_data <= timer_count[31:16]; if (WE_I) timer_count[31:16] <= DAT_I; end endcase // case (ADR_I) end // if (STB_I) end // else: !if(RST_I) end // always @ (posedge CLK_I) endmodule // miscellaneous