Skip to content

Instantly share code, notes, and snippets.

@cibomahto
Created December 2, 2018 07:36
Show Gist options
  • Save cibomahto/c18c04f9f182d4549eba780d6829a972 to your computer and use it in GitHub Desktop.
Save cibomahto/c18c04f9f182d4549eba780d6829a972 to your computer and use it in GitHub Desktop.
module chip (
output LED_R,
output LED_G,
output LED_B,
output SPI_C_0,
output SPI_D_0,
output SPI_C_1,
output SPI_D_1,
output SPI_C_2,
output SPI_D_2,
output SPI_C_3,
output SPI_D_3,
output START_FLAG
);
wire clk;
wire led_r;
wire led_g;
wire led_b;
wire start_flag;
reg [1:0] halfclock;
always @(posedge clk)
halfclock <= halfclock + 1;
SB_HFOSC u_hfosc (
.CLKHFPU(1'b1),
.CLKHFEN(1'b1),
.CLKHF(clk)
);
blink my_blink (
.clk(clk),
.rst(0),
.led_r(led_r),
.led_g(led_g),
.led_b(led_b)
);
assign LED_R = led_r;
assign LED_G = led_g;
assign LED_B = led_b;
icnd2110 my_icnd_0(
.clk(halfclock[0]),
.rst(0),
.chipcount(200),
.cfg_pwm_wider(0),
.cfg_up(1),
.spi_c(SPI_C_0),
.spi_d(SPI_D_0),
.start_flag(START_FLAG)
);
icnd2110 my_icnd_1(
.clk(halfclock[0]),
.rst(0),
.chipcount(200),
.cfg_pwm_wider(0),
.cfg_up(1),
.spi_c(SPI_C_1),
.spi_d(SPI_D_1),
.start_flag()
);
icnd2110 my_icnd_2(
.clk(halfclock[0]),
.rst(0),
.chipcount(200),
.cfg_pwm_wider(0),
.cfg_up(1),
.spi_c(SPI_C_2),
.spi_d(SPI_D_2),
.start_flag()
);
icnd2110 my_icnd_3(
.clk(halfclock[0]),
.rst(0),
.chipcount(200),
.cfg_pwm_wider(0),
.cfg_up(1),
.spi_c(SPI_C_3),
.spi_d(SPI_D_3),
.start_flag()
);
endmodule
module icnd2110(
input clk,
input rst,
input [7:0] chipcount,
input cfg_pwm_wider, // Enhancement for low gray (1=enable)
input cfg_up, // Ghosting reduction (1=enable)
output spi_c,
output spi_d,
output start_flag
);
reg [3:0] state; // Current state machine mode
reg [10:0] counter; // 8-bit step counter
reg [7:0] chips; // Number of ICND2110 chips present
reg [9:0] val; // PWM value (top 8 bits are significant)
reg [5:0] outp; // current output
reg [7:0] pwm_val;
wire [15:0] correction;
reg data;
reg start_flag_r;
assign spi_c = !clk; // Off by 1/2 phase?
assign spi_d = data;
assign start_flag = start_flag_r;
// The LUT takes the majority of our space, can we move it to a ram?
correction_lut_16 corrector (
.value(pwm_val),
.corrected(correction)
);
/*
assign correction[15:8] = val;
assign correction[7:0] = 0;
*/
always @(posedge clk)
if(rst) begin
state <= 0;
data <= 0;
val <= 0;
outp <= 0;
end
else begin
start_flag_r <= 0;
data <= 0;
if(val[9] == 0)
pwm_val <= val[8:1];
else
pwm_val <= (255 - val[8:1]);
case(state)
// Many states here:
// 0. wait for start
0:
// TODO: implement start signal
begin
start_flag_r <= 1;
state <= 1;
counter <= 0;
chips <= chipcount;
val <= val + 1; // output value counter
if(val == 0)
outp <= outp+1;
if(outp > 11)
outp <= 0;
end
// 1. start (128 bits of 1)
1:
begin
data <= 1;
counter <= counter +1;
if(counter == 127) begin
state <= state + 1;
counter <= 0;
end
end
// 2. blank (16 bits of 0)
2,4,6,8:
begin
counter <= counter +1;
if(counter == 15) begin
state <= state + 1;
counter <= 0;
end
end
// 3. reg (16 bit register value)
3:
begin
counter <= counter + 1;
case(counter[3:0])
11:
data <= cfg_pwm_wider;
12:
data <= cfg_up;
13,14,15:
data <= 1;
default:
data <= 0;
endcase
if(counter == 15) begin
state <= state + 1;
counter <= 0;
end
end
// 4. blank (16 bits of 0)
// for n chips:
// 5. chip x, out5-out0 (16 x 6 bits)
5, 7:
begin
counter <= counter + 1;
if(((state == 5) && (counter[6:4] == outp))
|| ((state == 7) && (counter[6:4] == (outp - 6)))) begin
case(counter[3:0])
0: data <= correction[15];
1: data <= correction[14];
2: data <= correction[13];
3: data <= correction[12];
4: data <= correction[11];
5: data <= correction[10];
6: data <= correction[9];
7: data <= correction[8];
8: data <= correction[7];
9: data <= correction[6];
10: data <= correction[5];
11: data <= correction[4];
12: data <= correction[3];
13: data <= correction[2];
14: data <= correction[1];
15: data <= correction[0];
endcase
end
if(counter == (16*6-1)) begin
counter <= 0;
if(state == 5) begin
state <= state + 1;
end
else begin
chips <= chips - 1;
if(chips > 0)
state <= 4;
else
state <= state + 1;
end
end
end
// 6. blank
// 7. chip x, out11-out6 (16 x 6 bits)
// 8. blank
// 9. frame end (145 bits of 1)
9:
begin
data <= 1;
counter <= counter +1;
if(counter == 144) begin
// state <= state + 1;
state <= 0;
counter <= 0;
end
end
default:
state <= 0;
endcase
end
endmodule
'''
module lut(count_out, angle);
input [2:0] count_out;
output [11:0] angle;
reg [11:0] angle;
always @(count_out)
case (count_out)
3'b000: angle=12'b001000000000; //0 45 45
3'b001: angle=12'b000100101110; //1 26.54 26.57
3'b010: angle=12'b000010100000; //2 14.06 14.036
3'b011: angle=12'b000001010001; //3 7.12 7.13
3'b100: angle=12'b000000101001; //4 3.604 3.576
3'b101: angle=12'b000000010100; //5 1.76 1.79
3'b110: angle=12'b000000001010; //6 0.88 0.9
3'b111: angle=12'b000000000101; //7 0.44 0.45
default: angle=12'b001000000000; //default 0
endcase
endmodule
'''
header = '''
module correction_lut_16(value, corrected);
input [7:0] value;
output [15:0] corrected;
reg [15:0] corrected;
always @(value)
case (value)
'''
footer = '''
endcase
endmodule
'''
out = open('correction_lut_16.v','w')
out.write(header)
for val in range(0,256):
out.write("%i: corrected=%i;\n" % (val,int(65535*pow(val/255.0,1.8))))
out.write(footer)
'''
module lut(count_out, angle);
input [2:0] count_out;
output [11:0] angle;
reg [11:0] angle;
always @(count_out)
case (count_out)
3'b000: angle=12'b001000000000; //0 45 45
3'b001: angle=12'b000100101110; //1 26.54 26.57
3'b010: angle=12'b000010100000; //2 14.06 14.036
3'b011: angle=12'b000001010001; //3 7.12 7.13
3'b100: angle=12'b000000101001; //4 3.604 3.576
3'b101: angle=12'b000000010100; //5 1.76 1.79
3'b110: angle=12'b000000001010; //6 0.88 0.9
3'b111: angle=12'b000000000101; //7 0.44 0.45
default: angle=12'b001000000000; //default 0
endcase
endmodule
'''
header = '''
module correction_lut_8(value, corrected);
input [7:0] value;
output [7:0] corrected;
reg [7:0] corrected;
always @(value)
case (value)
'''
footer = '''
endcase
endmodule
'''
out = open('correction_lut_8.v','w')
out.write(header)
for val in range(0,256):
out.write("%i: corrected=%i;\n" % (val,int(255*pow(val/255.0,1.8))))
out.write(footer)
chip.bin: chip.v blink.v upduino_v2.pcf
yosys -q -p "synth_ice40 -blif chip.blif" chip.v blink.v correction_lut_8.v correction_lut_16.v icnd2110.v
arachne-pnr -d 5k -P sg48 -p upduino_v2.pcf chip.blif -o chip.txt
icepack chip.txt chip.bin
.PHONY: flash
flash:
iceprog chip.bin
.PHONY: clean
clean:
$(RM) -f chip.blif chip.txt chip.ex chip.bin
set_io LED_R 41
set_io LED_G 39
set_io LED_B 40
set_io START_FLAG 28
set_io SPI_C_0 2
set_io SPI_D_0 46
set_io SPI_C_1 47
set_io SPI_D_1 45
set_io SPI_C_2 48
set_io SPI_D_2 3
set_io SPI_C_3 4
set_io SPI_D_3 44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment