Sylvain Munaut | bd83e53 | 2020-09-15 22:11:29 +0200 | [diff] [blame^] | 1 | /* |
| 2 | * led_blinker.v |
| 3 | * |
| 4 | * vim: ts=4 sw=4 |
| 5 | * |
| 6 | * Controls E1 led blinking |
| 7 | * |
| 8 | * Copyright (C) 2019-2020 Sylvain Munaut <tnt@246tNt.com> |
| 9 | * SPDX-License-Identifier: CERN-OHL-S-2.0 |
| 10 | */ |
| 11 | |
| 12 | `default_nettype none |
| 13 | |
| 14 | `define SMALL |
| 15 | |
| 16 | module led_blinker ( |
| 17 | // Requested LED state |
| 18 | input wire [7:0] led_state, |
| 19 | |
| 20 | // Shift Register interface |
| 21 | output wire [7:0] sr_val, |
| 22 | output reg sr_go, |
| 23 | input wire sr_rdy, |
| 24 | |
| 25 | // Clock / Reset |
| 26 | input wire clk, |
| 27 | input wire rst |
| 28 | ); |
| 29 | |
| 30 | // ff00 f0f0 cccc aaaa |
| 31 | localparam integer BLINK_SLOW_SPEED = 0; |
| 32 | localparam [15:0] BLINK_SLOW_PATTERN = 16'hf0f0; |
| 33 | localparam integer BLINK_FAST_SPEED = 0; |
| 34 | localparam [15:0] BLINK_FAST_PATTERN = 16'haaaa; |
| 35 | |
| 36 | |
| 37 | // Signals |
| 38 | // ------- |
| 39 | |
| 40 | reg [15:0] tick_cnt; |
| 41 | wire tick; |
| 42 | |
| 43 | reg [ 9:0] cycle; |
| 44 | |
| 45 | wire blink_slow; |
| 46 | wire blink_fast; |
| 47 | |
| 48 | reg [ 3:0] led; |
| 49 | |
| 50 | |
| 51 | // Counter |
| 52 | // ------- |
| 53 | |
| 54 | // Tick |
| 55 | always @(posedge clk) |
| 56 | `ifdef SMALL |
| 57 | tick_cnt <= (tick_cnt + 1) & (tick ? 16'h0000 : 16'hffff); |
| 58 | `else |
| 59 | tick_cnt <= tick ? 16'h00000 : (tick_cnt+ 1); |
| 60 | `endif |
| 61 | |
| 62 | assign tick = tick_cnt[15]; |
| 63 | |
| 64 | // Cycles |
| 65 | always @(posedge clk) |
| 66 | cycle <= cycle + tick; |
| 67 | |
| 68 | |
| 69 | // Blink patterns |
| 70 | // -------------- |
| 71 | |
| 72 | // Base |
| 73 | assign blink_slow = BLINK_SLOW_PATTERN[cycle[9-BLINK_SLOW_SPEED:6-BLINK_SLOW_SPEED]]; |
| 74 | assign blink_fast = BLINK_FAST_PATTERN[cycle[9-BLINK_FAST_SPEED:6-BLINK_FAST_SPEED]]; |
| 75 | |
| 76 | // Per-led |
| 77 | always @(*) |
| 78 | begin : led_state |
| 79 | integer i; |
| 80 | for (i=0; i<4; i=i+1) |
| 81 | led[i] = led_state[2*i+1] ? (led_state[2*i] ? blink_fast : blink_slow) : led_state[2*i]; |
| 82 | end |
| 83 | |
| 84 | |
| 85 | // Request |
| 86 | // ------- |
| 87 | |
| 88 | // Keep update requests 'pending' for half a cycle |
| 89 | always @(posedge clk or posedge rst) |
| 90 | if (rst) |
| 91 | sr_go <= 1'b0; |
| 92 | else |
| 93 | sr_go <= (sr_go & ~(sr_rdy | tick_cnt[14])) | tick; |
| 94 | |
| 95 | assign sr_val = { |
| 96 | led[1], |
| 97 | 1'b0, |
| 98 | led[0], |
| 99 | 1'b0, |
| 100 | 1'b0, |
| 101 | led[2], |
| 102 | 1'b0, |
| 103 | led[3] |
| 104 | }; |
| 105 | |
| 106 | endmodule // led_blinker |