*.blif | |||||
*.asc | |||||
*.bin |
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 |
# 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 |
//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 |
// 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 |
////////////////////////////////////////////////////////////// | |||||
// 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 |
`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 |
# 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 |
//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 |
`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 |