Initial commit
This commit is contained in:
239
source/hsl2rgb.sv
Normal file
239
source/hsl2rgb.sv
Normal file
@@ -0,0 +1,239 @@
|
||||
`timescale 1ns/100ps
|
||||
`default_nettype none
|
||||
|
||||
/**
|
||||
* HSL to RGB translation.
|
||||
*
|
||||
* H, S, L = [0..1)
|
||||
*
|
||||
* Q = | L < 0.5 ? L + L*S
|
||||
* | L >= 0.5 ? L + S - L*S
|
||||
*
|
||||
* P = 2 * L - Q
|
||||
*
|
||||
* TR = H < 2/3 ? H + 1/3 : 1/3 - (1 - H)
|
||||
* TG = H
|
||||
* TB = H >= 1/3 ? H - 1/3 : 1 - H
|
||||
*
|
||||
* COLORX = | TX < 1/6 ? P + ((Q - P) * 6 * TX)
|
||||
* | 1/6 <= TX < 1/2 ? Q
|
||||
* | 1/2 <= TX < 2/3 ? P + ((Q - P) * (2/3 - TX) * 6)
|
||||
* | else : P
|
||||
*/
|
||||
|
||||
/*
|
||||
* Datapath:
|
||||
*
|
||||
* if l < [1/2]
|
||||
* then: lls = l + (l * s)
|
||||
* else: lls = l - (l * s)
|
||||
*
|
||||
* m1h = ~(h - 1)
|
||||
*
|
||||
* tr =
|
||||
* if h < [2/3]
|
||||
* then: h + [1/3]
|
||||
* else: [1/3] - m1h
|
||||
*
|
||||
* tg = h
|
||||
*
|
||||
* tb =
|
||||
* if h >= [1/3]
|
||||
* then: h - [1/3]
|
||||
* else: m1h
|
||||
*
|
||||
* q =
|
||||
* if l < [1/2]
|
||||
* then: lls
|
||||
* else: lls + s
|
||||
*
|
||||
* p = l * 2 - q
|
||||
* qp = (q - l) * 2
|
||||
*
|
||||
* r =
|
||||
* p + 6 * qp * tr
|
||||
* p + 6 * qp * ([2/3] - tr)
|
||||
*
|
||||
* g =
|
||||
* p + 6 * qp * tg
|
||||
* p + 6 * qp * ([2/3] - tg)
|
||||
*
|
||||
* b =
|
||||
* p + 6 * qp * tb
|
||||
* p + 6 * qp * ([2/3] - tb)
|
||||
*/
|
||||
|
||||
module hsl2rgb
|
||||
(input wire clock,
|
||||
input wire reset,
|
||||
|
||||
input wire [7:0] h,
|
||||
input wire [7:0] s,
|
||||
input wire [7:0] l,
|
||||
input wire ready_i,
|
||||
|
||||
output reg [7:0] r,
|
||||
output reg [7:0] g,
|
||||
output reg [7:0] b,
|
||||
output wire valid_o);
|
||||
|
||||
`define C1_6 43
|
||||
`define C1_3 85
|
||||
`define C1_2 128
|
||||
`define C2_3 171
|
||||
`define C1_1 256
|
||||
|
||||
localparam STAGES = 5;
|
||||
logic [STAGES-1:0] valid;
|
||||
|
||||
assign valid_o = valid[STAGES-1];
|
||||
|
||||
always_ff @ (posedge clock, posedge reset)
|
||||
if (reset)
|
||||
valid <= '0;
|
||||
else
|
||||
valid <= { valid[STAGES-2:0], ready_i };
|
||||
|
||||
/* ---------------- Stage 1 ---------------- */
|
||||
logic [8:0] lls; // lls = l0 ± (l0 * s0)
|
||||
logic ls_sub;
|
||||
|
||||
/* verilator lint_off UNUSED */
|
||||
logic [31:0] mac_lls_o;
|
||||
/* verilator lint_on UNUSED */
|
||||
|
||||
assign lls = {mac_lls_o[16:8]};
|
||||
assign ls_sub = l < `C1_2 ? 1'b0 : 1'b1;
|
||||
|
||||
ice40_mac16x16 mac_lls
|
||||
(.clock, .reset,
|
||||
.a({8'b0, l}),
|
||||
.b({8'b0, s}),
|
||||
.s({16'b0, l, 8'b0}),
|
||||
.sub(ls_sub),
|
||||
.y(mac_lls_o));
|
||||
|
||||
/* propagate to next stage */
|
||||
logic [7:0] h1, s1, l1;
|
||||
always_ff @ (posedge clock) begin
|
||||
h1 <= h;
|
||||
s1 <= s;
|
||||
l1 <= l;
|
||||
end
|
||||
|
||||
/* ---------------- stage 2 ---------------- */
|
||||
logic [8:0] q_pre;
|
||||
logic [7:0] q;
|
||||
logic [7:0] minus1h; // minus1h = 256 - h = ~(h - 1)
|
||||
|
||||
always_ff @ (posedge clock) begin
|
||||
q_pre <= l1 < `C1_2 ? lls : lls + s1;
|
||||
minus1h <= ~(h1 - 1);
|
||||
end
|
||||
|
||||
assign q = q_pre[8] ? 8'hff : q_pre[7:0];
|
||||
|
||||
/* propagate to next stage */
|
||||
logic [7:0] h2, l2;
|
||||
always_ff @ (posedge clock) begin
|
||||
h2 <= h1;
|
||||
l2 <= l1;
|
||||
end
|
||||
|
||||
/* ---------------- stage 3 ---------------- */
|
||||
logic [7:0] tr, tg, tb;
|
||||
logic [8:0] p_pre;
|
||||
logic [7:0] p; // p = l * 2 - q
|
||||
logic [7:0] qp; // qp = q - p
|
||||
|
||||
always_ff @ (posedge clock) begin
|
||||
tr <= h2 < 8'(`C2_3) ? h2 + 8'(`C1_3) : 8'(`C1_3) - minus1h;
|
||||
tg <= h2;
|
||||
tb <= h2 >= 8'(`C1_3) ? h2 - 8'(`C1_3) : minus1h;
|
||||
|
||||
p_pre <= (9'(l2) << 1) - q;
|
||||
qp <= 8'((q - l2) << 1);
|
||||
end
|
||||
|
||||
assign p = p_pre[8] ? 8'hff : p_pre[7:0];
|
||||
|
||||
/* propagate to next stage */
|
||||
logic [7:0] q3;
|
||||
always_ff @ (posedge clock)
|
||||
q3 <= q;
|
||||
|
||||
/* ---------------- stage 4 ---------------- */
|
||||
logic [7:0] trx, tgx, tbx;
|
||||
logic [10:0] qp6;
|
||||
|
||||
/* verilator lint_off UNUSED */
|
||||
logic [31:0] mac_r_o;
|
||||
logic [31:0] mac_g_o;
|
||||
logic [31:0] mac_b_o;
|
||||
/* verilator lint_on UNUSED */
|
||||
|
||||
assign qp6 = (11'(qp) << 1) + (11'(qp) << 2);
|
||||
assign trx = (tr < `C1_6) ? tr : `C2_3 - tr;
|
||||
assign tgx = (tg < `C1_6) ? tg : `C2_3 - tg;
|
||||
assign tbx = (tb < `C1_6) ? tb : `C2_3 - tb;
|
||||
|
||||
ice40_mac16x16 mac_r
|
||||
(.clock, .reset,
|
||||
.a({5'b0, qp6}),
|
||||
.b({8'b0, trx}),
|
||||
.s({16'b0, p, 8'b0}),
|
||||
.sub(1'b0),
|
||||
.y(mac_r_o));
|
||||
|
||||
ice40_mac16x16 mac_g
|
||||
(.clock, .reset,
|
||||
.a({5'b0, qp6}),
|
||||
.b({8'b0, tgx}),
|
||||
.s({16'b0, p, 8'b0}),
|
||||
.sub(1'b0),
|
||||
.y(mac_g_o));
|
||||
|
||||
ice40_mac16x16 mac_b
|
||||
(.clock, .reset,
|
||||
.a({5'b0, qp6}),
|
||||
.b({8'b0, tbx}),
|
||||
.s({16'b0, p, 8'b0}),
|
||||
.sub(1'b0),
|
||||
.y(mac_b_o));
|
||||
|
||||
/* propagate to next stage */
|
||||
logic [7:0] tr4, tg4, tb4;
|
||||
logic [7:0] p4;
|
||||
logic [7:0] q4;
|
||||
|
||||
always_ff @ (posedge clock) begin
|
||||
tr4 <= tr;
|
||||
tg4 <= tg;
|
||||
tb4 <= tb;
|
||||
p4 <= p;
|
||||
q4 <= q3;
|
||||
end
|
||||
|
||||
/* ---------------- stage 5 ---------------- */
|
||||
always_ff @ (posedge clock) begin
|
||||
if (tr4 < `C1_6) r <= mac_r_o[16] ? 8'hff : mac_r_o[15:8];
|
||||
else if (tr4 < `C1_2) r <= q4;
|
||||
else if (tr4 < `C2_3) r <= mac_r_o[16] ? 8'hff : mac_r_o[15:8];
|
||||
else r <= p4;
|
||||
end
|
||||
|
||||
always_ff @ (posedge clock) begin
|
||||
if (tg4 < `C1_6) g <= mac_g_o[16] ? 8'hff : mac_g_o[15:8];
|
||||
else if (tg4 < `C1_2) g <= q4;
|
||||
else if (tg4 < `C2_3) g <= mac_g_o[16] ? 8'hff : mac_g_o[15:8];
|
||||
else g <= p4;
|
||||
end
|
||||
|
||||
always_ff @ (posedge clock) begin
|
||||
if (tb4 < `C1_6) b <= mac_b_o[16] ? 8'hff : mac_b_o[15:8];
|
||||
else if (tb4 < `C1_2) b <= q4;
|
||||
else if (tb4 < `C2_3) b <= mac_b_o[16] ? 8'hff : mac_b_o[15:8];
|
||||
else b <= p4;
|
||||
end
|
||||
|
||||
endmodule // hsl2rgb
|
||||
Reference in New Issue
Block a user