1 |
50 |
dgisselq |
////////////////////////////////////////////////////////////////////////////////
|
2 |
|
|
//
|
3 |
|
|
// Filename: clrled.v
|
4 |
|
|
//
|
5 |
|
|
// Project: OpenArty, an entirely open SoC based upon the Arty platform
|
6 |
|
|
//
|
7 |
|
|
// Purpose: The ARTY contains 4 Color LEDs. Each color LED is composed of
|
8 |
|
|
// three LEDs: one red, one blue, and one green. These LEDs need
|
9 |
|
|
// to be toggled in a PWM manner in order to create varying amounts of
|
10 |
|
|
// reds, blues, greens, and other colors with varying components of red,
|
11 |
|
|
// green, and blue. This Verilog core creates a bus controlled core
|
12 |
|
|
// so that these LEDs can be controlled by any bus master. While the core
|
13 |
|
|
// is ostensibly controlled via a wishbone bus, none of the control wires
|
14 |
|
|
// are wishbone wires, save the i_stb wire. Address wires are not needed,
|
15 |
|
|
// as this core only implements a single address. Stall is permanently
|
16 |
|
|
// set to zero. Ack is always on the clock after STB is true (but not set
|
17 |
|
|
// here), and the output data is given by o_data. See fastio.v for how to
|
18 |
|
|
// connect this to a wishbone bus.
|
19 |
|
|
//
|
20 |
|
|
// The core also accepts 9-bits from a counter created elsewhere. This
|
21 |
|
|
// counter is created quite simply, and phase is irrelevant for our
|
22 |
|
|
// purposes here. Thy reason why we don't create the counter within this
|
23 |
|
|
// core is because the same counter can also be shared with the other
|
24 |
|
|
// clrled cores. The code to generate this counter is quite simple:
|
25 |
|
|
//
|
26 |
|
|
// reg [8:0] counter;
|
27 |
|
|
// always @(posedge i_clk)
|
28 |
|
|
// counter <= counter + 9'h1;
|
29 |
|
|
//
|
30 |
|
|
//
|
31 |
|
|
// The core creates and maintains one 32-bit register on the bus. This
|
32 |
|
|
// register contains four bytes:
|
33 |
|
|
//
|
34 |
|
|
// Byte 0 (MSB)
|
35 |
|
|
// Contains the most significant bits of the red, green, and blue
|
36 |
|
|
// color. Since using these bits sets the CLRLED to be *very*
|
37 |
|
|
// bright, the design is set to assume they will rarely be used.
|
38 |
|
|
//
|
39 |
|
|
// Byte 1
|
40 |
|
|
// The red control. The higher the value, the brighter the red
|
41 |
|
|
// component will be.
|
42 |
|
|
//
|
43 |
|
|
// Byte 2 Blue control.
|
44 |
|
|
// Byte 3 Green control.
|
45 |
|
|
//
|
46 |
|
|
// As examples, setting this register to 0x0ffffff will produce a bright
|
47 |
|
|
// white light from the color LED. Setting it to 0x070000 will produce
|
48 |
|
|
// a dimmer red light.
|
49 |
|
|
//
|
50 |
|
|
// Creator: Dan Gisselquist, Ph.D.
|
51 |
|
|
// Gisselquist Technology, LLC
|
52 |
|
|
//
|
53 |
|
|
////////////////////////////////////////////////////////////////////////////////
|
54 |
|
|
//
|
55 |
|
|
// Copyright (C) 2015-2016, Gisselquist Technology, LLC
|
56 |
|
|
//
|
57 |
|
|
// This program is free software (firmware): you can redistribute it and/or
|
58 |
|
|
// modify it under the terms of the GNU General Public License as published
|
59 |
|
|
// by the Free Software Foundation, either version 3 of the License, or (at
|
60 |
|
|
// your option) any later version.
|
61 |
|
|
//
|
62 |
|
|
// This program is distributed in the hope that it will be useful, but WITHOUT
|
63 |
|
|
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
|
64 |
|
|
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
65 |
|
|
// for more details.
|
66 |
|
|
//
|
67 |
|
|
// You should have received a copy of the GNU General Public License along
|
68 |
|
|
// with this program. (It's in the $(ROOT)/doc directory, run make with no
|
69 |
|
|
// target there if the PDF file isn't present.) If not, see
|
70 |
|
|
// <http://www.gnu.org/licenses/> for a copy.
|
71 |
|
|
//
|
72 |
|
|
// License: GPL, v3, as defined and found on www.gnu.org,
|
73 |
|
|
// http://www.gnu.org/licenses/gpl.html
|
74 |
|
|
//
|
75 |
|
|
//
|
76 |
|
|
////////////////////////////////////////////////////////////////////////////////
|
77 |
|
|
//
|
78 |
|
|
//
|
79 |
|
|
module clrled(i_clk, i_stb, i_data, i_counter, o_data, o_led);
|
80 |
|
|
input i_clk, i_stb;
|
81 |
|
|
input [31:0] i_data;
|
82 |
|
|
input [8:0] i_counter;
|
83 |
|
|
output wire [31:0] o_data;
|
84 |
|
|
output reg [2:0] o_led;
|
85 |
|
|
|
86 |
|
|
//
|
87 |
|
|
//
|
88 |
|
|
// If i_counter isn't available, just build one as in:
|
89 |
|
|
//
|
90 |
|
|
// reg [8:0] counter;
|
91 |
|
|
// always @(posedge i_clk) counter <= counter + 1'b1;
|
92 |
|
|
//
|
93 |
|
|
|
94 |
|
|
wire [31:0] w_clr_led;
|
95 |
|
|
reg [8:0] r_clr_led_r, r_clr_led_g, r_clr_led_b;
|
96 |
|
|
|
97 |
|
|
initial r_clr_led_r = 9'h003; // Color LED on the far right
|
98 |
|
|
initial r_clr_led_g = 9'h000;
|
99 |
|
|
initial r_clr_led_b = 9'h000;
|
100 |
|
|
|
101 |
|
|
always @(posedge i_clk)
|
102 |
|
|
if (i_stb)
|
103 |
|
|
begin
|
104 |
|
|
r_clr_led_r <= { i_data[26], i_data[23:16] };
|
105 |
|
|
r_clr_led_g <= { i_data[25], i_data[15: 8] };
|
106 |
|
|
r_clr_led_b <= { i_data[24], i_data[ 7: 0] };
|
107 |
|
|
end
|
108 |
|
|
|
109 |
|
|
assign o_data = { 5'h0,
|
110 |
|
|
r_clr_led_r[8], r_clr_led_g[8], r_clr_led_b[8],
|
111 |
|
|
r_clr_led_r[7:0], r_clr_led_g[7:0], r_clr_led_b[7:0]
|
112 |
|
|
};
|
113 |
|
|
|
114 |
|
|
wire [8:0] rev_counter;
|
115 |
|
|
assign rev_counter[8] = i_counter[0];
|
116 |
|
|
assign rev_counter[7] = i_counter[1];
|
117 |
|
|
assign rev_counter[6] = i_counter[2];
|
118 |
|
|
assign rev_counter[5] = i_counter[3];
|
119 |
|
|
assign rev_counter[4] = i_counter[4];
|
120 |
|
|
assign rev_counter[3] = i_counter[5];
|
121 |
|
|
assign rev_counter[2] = i_counter[6];
|
122 |
|
|
assign rev_counter[1] = i_counter[7];
|
123 |
|
|
assign rev_counter[0] = i_counter[8];
|
124 |
|
|
|
125 |
|
|
always @(posedge i_clk)
|
126 |
|
|
o_led <= { (rev_counter[8:0] < r_clr_led_r),
|
127 |
|
|
(rev_counter[8:0] < r_clr_led_g),
|
128 |
|
|
(rev_counter[8:0] < r_clr_led_b) };
|
129 |
|
|
|
130 |
|
|
endmodule
|