@@ -0,0 +1,3 @@ | |||
*.blif | |||
*.asc | |||
*.bin |
@@ -0,0 +1,24 @@ | |||
filename = top | |||
pcf_file = io.pcf | |||
RPI_USER=pi | |||
RPI_IP=192.168.10.90 | |||
RPI_DIR=/home/pi/ice40/build2 | |||
build: | |||
yosys -p "synth_ice40 -blif $(filename).blif" $(filename).v | |||
arachne-pnr -d 5k -P sg48 -p $(pcf_file) $(filename).blif -o $(filename).asc | |||
icepack $(filename).asc $(filename).bin | |||
prog: #for sram | |||
iceprog -S $(filename).bin | |||
prog_flash: | |||
iceprog $(filename).bin | |||
rpi_prog: build | |||
scp $(filename).bin $(RPI_USER)@$(RPI_IP):$(RPI_DIR) | |||
ssh $(RPI_USER)@$(RPI_IP) "cd $(RPI_DIR); iceprog $(filename).bin" | |||
clean: | |||
rm -rf $(filename).blif $(filename).asc $(filename).bin |
@@ -0,0 +1,9 @@ | |||
# 7-Segment-Display to show Counter Value | |||
The goal of this example is to display a counter output on a 7-segment connected to the fpga. | |||
For used IOs check out io.pcf. | |||
To Upload use Makefile, Project IceStorm is needed for this to work. | |||
I uploaded with RPI4, look at make rpi_prog |
@@ -0,0 +1,34 @@ | |||
//transforms 4bits numbers to a 7seg display | |||
// | |||
// --a-- | |||
// | | | |||
// f b | |||
// | | | |||
// --g-- | |||
// | | | |||
// e c | |||
// | | | |||
// --d-- DP | |||
// | |||
// 7'gfedcba (a = LSB) | |||
module bcd_to_7seg(input [3:0] bcd_in, output [6:0] seg_out); | |||
assign seg_out = (bcd_in==4'h0) ? 7'b0111111 : | |||
(bcd_in==4'h1) ? 7'b0000110 : | |||
(bcd_in==4'h2) ? 7'b1011011 : | |||
(bcd_in==4'h3) ? 7'b1001111 : | |||
(bcd_in==4'h4) ? 7'b1100110 : | |||
(bcd_in==4'h5) ? 7'b1101101 : | |||
(bcd_in==4'h6) ? 7'b1111101 : | |||
(bcd_in==4'h7) ? 7'b0000111 : | |||
(bcd_in==4'h8) ? 7'b1111111 : | |||
(bcd_in==4'h9) ? 7'b1101111 : | |||
(bcd_in==4'ha) ? 7'b1110111 : | |||
(bcd_in==4'hb) ? 7'b1111100 : | |||
(bcd_in==4'hc) ? 7'b0111001 : | |||
(bcd_in==4'hd) ? 7'b1011110 : | |||
(bcd_in==4'he) ? 7'b1111001 : | |||
(bcd_in==4'hf) ? 7'b1110001 : | |||
7'b0110110; //does a H, default shouldn't happen | |||
endmodule |
@@ -0,0 +1,43 @@ | |||
// generate clocks | |||
module clocks | |||
#( | |||
parameter PRE_PWM = 28'd12, | |||
parameter PRE_7SEG = 28'd12, | |||
parameter PRE_COUNTER = 28'd12 | |||
) | |||
( | |||
input clk, output clk_pwm, output clk_7seg, output clk_counter | |||
); | |||
reg [27:0] counter = 28'd0; | |||
reg [27:0] counter_7seg = 28'd0; | |||
reg [27:0] counter_counter = 28'd0; | |||
reg clk_pwm; | |||
reg clk_7seg; | |||
reg clk_counter; | |||
always @(posedge clk) | |||
begin | |||
counter <= counter + 28'd1; | |||
if(counter >= (PRE_PWM-1)) | |||
counter <= 28'd0; | |||
clk_pwm <= ( counter < PRE_PWM/2) ? 1'b1 : 1'b0; | |||
end | |||
always @(posedge clk) | |||
begin | |||
counter_7seg <= counter_7seg + 28'd1; | |||
if(counter_7seg >= (PRE_7SEG-1)) | |||
counter_7seg <= 28'd0; | |||
clk_7seg <= ( counter_7seg < PRE_7SEG/2) ? 1'b1 : 1'b0; | |||
end | |||
always @(posedge clk) | |||
begin | |||
counter_counter <= counter_counter + 28'd1; | |||
if(counter_counter >= (PRE_COUNTER-1)) | |||
counter_counter <= 28'd0; | |||
clk_counter <= ( counter_counter < PRE_COUNTER/2) ? 1'b1 : 1'b0; | |||
end | |||
endmodule |
@@ -0,0 +1,23 @@ | |||
////////////////////////////////////////////////////////////// | |||
// 20-bit loadable up-down counter ////// | |||
////////////////////////////////////////////////////////////// | |||
module counter(clk, rst, data, updown, load, data_out); | |||
input clk, rst, load; | |||
input updown; | |||
input [19:0] data; | |||
output reg [19:0] data_out; | |||
always @(posedge clk) | |||
begin | |||
if(rst) | |||
data_out <= 20'b0; | |||
else if(load) | |||
data_out <= data; | |||
else | |||
data_out <= ((updown)?(data_out + 1'b1):(data_out -1'b1)); | |||
end | |||
endmodule |
@@ -0,0 +1,48 @@ | |||
`include "bcd_to_7seg.v" | |||
module digit_driver | |||
#( | |||
parameter D = 28'd0 | |||
) | |||
( | |||
input clk, input [19:0] number, input dot, output [7:0] segs, output [4:0] digs | |||
); | |||
// io for 7seg | |||
reg [2:0] active_digit; | |||
wire [4:0] buf_digs; | |||
wire [19:0] number; | |||
wire [3:0] a_number; | |||
wire [6:0] seg_out; | |||
bcd_to_7seg bcd_to_7seg_inst( | |||
.bcd_in(a_number), | |||
.seg_out(seg_out) | |||
); | |||
// see bcd_to_7seg.v for segments placement | |||
// common anode ~seg_out[], common cathode seg_out[] | |||
assign segs = { dot, seg_out }; | |||
assign buf_digs = (number > 20'hFFFF) ? 5'b11111 : | |||
(number > 20'hFFF) ? 5'b01111 : | |||
(number > 20'hFF) ? 5'b00111 : | |||
(number > 20'hF) ? 5'b00011 : | |||
5'b00001; // default shouldn't happen | |||
assign digs = buf_digs & (1'b1 << active_digit); | |||
assign a_number = (number & (4'b1111 << (active_digit*4))) >> (active_digit*4); | |||
always @(posedge clk) | |||
begin | |||
active_digit <= active_digit + 1'b1; | |||
if(active_digit > 3'd3) | |||
active_digit <= 1'b0; | |||
end | |||
endmodule |
@@ -0,0 +1,33 @@ | |||
# For the iCE40 UltraPlus (iCE40UP5K-QFN) Breakout Board | |||
# 12 MHz Clock | |||
set_io clk 35 | |||
set_io LED_R 41 | |||
set_io LED_G 40 | |||
set_io LED_B 39 | |||
set_io SW[0] 23 | |||
set_io SW[1] 25 | |||
set_io SW[2] 34 | |||
set_io SW[3] 43 | |||
# bank 0,segments | |||
set_io seg_b 26 # IOT_39A | |||
set_io seg_a 27 # IOT_38B | |||
set_io seg_p 28 # IOT_41A | |||
set_io seg_f 31 # IOT_42B | |||
set_io seg_g 32 # IOT_43A | |||
set_io seg_e 37 # IOT_45A_G1 | |||
set_io seg_d 42 # IOT_51A | |||
set_io seg_c 38 # IOT_50B | |||
# bank1 digit | |||
set_io dig_1 21 # IOT_23B | |||
set_io dig_2 20 # IOT_25B_G3 | |||
set_io dig_3 19 # IOT_29B | |||
set_io dig_4 18 # IOT_31B | |||
set_io dig_5 11 # IOT_20A | |||
#spi | |||
set_io SPI_SS 16 | |||
set_io SPI_SCK 15 | |||
set_io SPI_MOSI 17 | |||
set_io SPI_MISO 14 |
@@ -0,0 +1,24 @@ | |||
//pwm module, outputs a pulse width according to the value written | |||
//max width 255 cycles | |||
module pwm(input clk, input en, input [7:0] value_input, output out); | |||
reg [7:0] counter; | |||
reg [7:0] value; //max 255 | |||
assign out = (counter < value); | |||
initial begin | |||
counter = 0; | |||
value = 255; | |||
end | |||
always @(posedge clk) | |||
begin | |||
counter <= counter + 1; | |||
if(en == 1'b1) | |||
value <= value_input; | |||
else | |||
value <= 0; | |||
end | |||
endmodule |
@@ -0,0 +1,90 @@ | |||
`include "digit_driver.v" | |||
`include "pwm.v" | |||
`include "clocks.v" | |||
`include "counter.v" | |||
// A verilog module transforms a 4-bit number into a displayable 7-bit value. | |||
// This number is incremented every ~0.25sec. | |||
module top( input clk, | |||
output LED_R, output LED_G, output LED_B, | |||
output seg_b, output seg_a, output seg_f, | |||
output seg_g, output seg_d, output seg_e, | |||
output seg_c, output seg_p, input [3:0] SW, | |||
output dig_1, output dig_2, output dig_3, output dig_4, output dig_5 | |||
); | |||
wire clk_pwm; | |||
wire clk_7seg; | |||
wire clk_counter; | |||
clocks #(.PRE_PWM(28'd12), .PRE_7SEG(28'd12000), .PRE_COUNTER(28'd12000)) clocks_inst | |||
( | |||
.clk(clk), | |||
.clk_pwm(clk_pwm), | |||
.clk_7seg(clk_7seg), | |||
.clk_counter(clk_counter) | |||
); | |||
wire rst; | |||
wire updown; | |||
wire load; | |||
reg [19:0] data = 20'h1337; | |||
wire [19:0] data_out; | |||
assign rst = SW[0]; | |||
assign updown = SW[1]; | |||
assign load = SW[2]; | |||
counter TIM1 ( | |||
.clk(clk_counter), | |||
.rst(rst), | |||
.data(data), | |||
.updown(updown), | |||
.load(load), | |||
.data_out(data_out) | |||
); | |||
wire pwm_en_write; | |||
assign pwm_en_write = SW[3]; | |||
wire [7:0] pwm_brightness; | |||
reg [7:0] led_brightness; | |||
assign pwm_brightness = led_brightness; | |||
wire pwm_out; | |||
pwm pwm_inst(.clk(clk_pwm), .en(pwm_en_write), .value_input(pwm_brightness), .out(pwm_out)); | |||
// active low, color white | |||
assign LED_R = ~pwm_out; | |||
assign LED_G = ~pwm_out; | |||
assign LED_B = ~pwm_out; | |||
wire [19:0] number; | |||
assign number = data_out; | |||
assign dot = rst; | |||
wire [7:0] segs; | |||
assign seg_a = segs[0]; | |||
assign seg_b = segs[1]; | |||
assign seg_c = segs[2]; | |||
assign seg_d = segs[3]; | |||
assign seg_e = segs[4]; | |||
assign seg_f = segs[5]; | |||
assign seg_g = segs[6]; | |||
assign seg_p = segs[7]; | |||
wire [4:0] digs; | |||
assign dig_1 = digs[0]; | |||
assign dig_2 = digs[1]; | |||
assign dig_3 = digs[2]; | |||
assign dig_4 = digs[3]; | |||
assign dig_5 = digs[4]; | |||
digit_driver dig_inst(.clk(clk_7seg), .number(number), .dot(dot), .segs(segs), .digs(digs)); | |||
initial begin | |||
led_brightness = 10; | |||
end | |||
endmodule |