/* * This wb slave controls a button, a LED and timer. * * | *WISHBONE DATASHEET* | * |---------------------------------------------------------------------------| * | *Description* | *Specification* | * |---------------------------------+-----------------------------------------| * | General description | miscellaneous peripherals core | * |---------------------------------+-----------------------------------------| * | Supported cycles | SLAVE, pipelined READ/WRITE | * |---------------------------------+-----------------------------------------| * | Data port, size | 16-bit | * | Data port, granularity | 16-bit | * | Data port, maximum operand size | 16-bit | * | Data transfer ordering | Big endian and/or little endian | * | Data transfer ordering | Undefined | * | Address port, size | 3 | * |---------------------------------+-----------------------------------------| * | Clock frequency constraints | NONE | * |---------------------------------+-----------------------------------------| * | | *Signal name* | *WISHBONE Equiv.* | * | |------------------+----------------------| * | | ACK_O | ACK_O | * | | ADR_I | ADR_I() | * | Supported signal list and cross | CLK_I | CLK_I | * | reference to equivalent | DAT_I | DAT_I() | * | WISHBONE signals | DAT_O | DAT_O() | * | | STB_I | STB_I | * | | WE_I | WE_I | * | | RST_I | RST_I | * | | STALL_O | STALL_O | * |---------------------------------+-----------------------------------------| * | Special requirements | NONE | * * 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