Scan-multiplexed LED display driver simple demo.
One display digit is illuminated at a time according to which segement strobe is active. The human eye integrates this and does not see any flicker provided the scanning is sufficiently fast (> 100 Hz).
The following CSharp file was compiled with mono mcs.
//
// Kiwi Scientific Acceleration - Simple 7-segment display driver - net level
// (C) 2008 D J Greaves, University of Cambridge Computer Laboratory.
//
using System;
using System.Text;
using KiwiSystem;
public static class seven_segment
{
const int n_digits = 4;
[Kiwi.InputBitPort("clear")] static bool clear;
[Kiwi.OutputWordPort("segments")] static uint segments;
[Kiwi.OutputWordPort("strobes")] static uint strobes;
// Digit data in an array
static int [] digit_data = new int [n_digits];
// Seven segment character set ROM
// Digits 0-9 and a minus sign. Bit g is lsb, zero for on.
static int [] cbg_seven_seg = new int [] { 0x01, 0x4f, 0x12, 0x06, 0x4c, 0x24, 0x60, 0x0f, 0x00, 0x0c, 0x7E };
static int seven_seg_encode_data(int d)
{
return cbg_seven_seg[d];
}
static int digit_on_display = 0;
static void scan()
{
digit_on_display = (digit_on_display + 1) % n_digits;
strobes = 1u << digit_on_display;
segments = (uint)(seven_seg_encode_data(digit_data[digit_on_display]));
for (int delay=0;delay<4; delay++) Kiwi.Pause();
}
static public void reset_data()
{
for (int i=0; i < n_digits; i++)
{
digit_data[i] = 0;
}
}
static void increment_bcd()
{
for (int d=0; d
Object File
The dotnet .exe file was converted to the following Verilog RTL file with KiwiC.
// Verilog output file generated at 29/04/2016 14:28:14
// Kiwi Scientific Acceleration (KiwiC .net/CIL/C# to Verilog/SystemC compiler): Version alpha 2.03c Interim: 25-Apr-2016 Unix 3.13.0.65
// /home/djg11/d320/hprls/kiwipro/kiwic/distro/lib/kiwic.exe seven-segment.exe -vnl-roundtrip=disable -vnl-resets=synchronous -vnl=seven-segment.v -vnl-rootmodname=DUT
module DUT(input clear, output reg [31:0] segments, output reg [31:0] strobes, input clk, input reset);
integer seven_segment_digit_on_display;
integer sTMT4Main_V_0;
integer Tsre2_0_V_0;
integer Tssc3_5_V_0;
integer Tsin4_0_V_0;
integer Tsin4_0_V_1;
reg signed [31:0] A_SINT_CC_SCALbx12_ARB0[10:0];
reg signed [31:0] A_SINT_CC_SCALbx10_ARA0[3:0];
reg [3:0] xpc10nz;
always @(posedge clk ) begin
//Start structure HPR seven-segment.exe
if (reset) begin
Tsre2_0_V_0 <= 32'd0;
strobes <= 32'd0;
segments <= 32'd0;
Tsin4_0_V_1 <= 32'd0;
Tsin4_0_V_0 <= 32'd0;
Tssc3_5_V_0 <= 32'd0;
seven_segment_digit_on_display <= 32'd0;
sTMT4Main_V_0 <= 32'd0;
xpc10nz <= 4'd0;
end
else begin
case (xpc10nz)
0/*0:US*/: begin
seven_segment_digit_on_display <= 32'd0;
sTMT4Main_V_0 <= 32'd0;
A_SINT_CC_SCALbx10_ARA0[2'd3] <= 32'd0;
A_SINT_CC_SCALbx10_ARA0[2'd2] <= 32'd0;
A_SINT_CC_SCALbx10_ARA0[1'd1] <= 32'd0;
A_SINT_CC_SCALbx10_ARA0[0] <= 32'd0;
xpc10nz <= 4'd9/*9:xpc10nz*/;
end
1'd1/*1:US*/: begin
Tssc3_5_V_0 <= 32'd1+Tssc3_5_V_0;
xpc10nz <= 3'd6/*6:xpc10nz*/;
end
2'd2/*2:US*/: if (!(!Tsin4_0_V_1)) begin
A_SINT_CC_SCALbx10_ARA0[Tsin4_0_V_0] <= 32'hffffffff&Tsin4_0_V_1;
xpc10nz <= 3'd4/*4:xpc10nz*/;
end
else begin
Tsin4_0_V_0 <= 32'd1+Tsin4_0_V_0;
A_SINT_CC_SCALbx10_ARA0[Tsin4_0_V_0] <= 32'hffffffff&Tsin4_0_V_1;
xpc10nz <= 3'd5/*5:xpc10nz*/;
end
3'd4/*4:US*/: begin
sTMT4Main_V_0 <= 32'd0;
xpc10nz <= 2'd3/*3:xpc10nz*/;
end
3'd5/*5:US*/: begin
if ((Tsin4_0_V_0<3'd4)) xpc10nz <= 2'd2/*2:xpc10nz*/;
else xpc10nz <= 3'd4/*4:xpc10nz*/;
if ((Tsin4_0_V_0<3'd4) && (4'd10/*10:MS*/==(32'hffffffff&Tsin4_0_V_0+A_SINT_CC_SCALbx10_ARA0[Tsin4_0_V_0]))) Tsin4_0_V_1
<= 32'd0;
if ((Tsin4_0_V_0<3'd4) && (4'd10/*10:MS*/!=(32'hffffffff&Tsin4_0_V_0+A_SINT_CC_SCALbx10_ARA0[Tsin4_0_V_0])))
Tsin4_0_V_1 <= Tsin4_0_V_0+A_SINT_CC_SCALbx10_ARA0[Tsin4_0_V_0];
end
3'd6/*6:US*/: begin
if ((Tssc3_5_V_0>=3'd4) && (sTMT4Main_V_0==4'd10/*10:US*/)) begin
Tsin4_0_V_0 <= 32'd0;
xpc10nz <= 3'd5/*5:xpc10nz*/;
end
if ((Tssc3_5_V_0>=3'd4) && (sTMT4Main_V_0!=4'd10/*10:US*/)) xpc10nz <= 2'd3/*3:xpc10nz*/;
if ((Tssc3_5_V_0<3'd4)) xpc10nz <= 1'd1/*1:xpc10nz*/;
end
3'd7/*7:US*/: begin
strobes <= (32'd1<<(5'd31&32'hffffffff&((1'd1+seven_segment_digit_on_display)%3'd4)));
segments <= A_SINT_CC_SCALbx12_ARB0[A_SINT_CC_SCALbx10_ARA0[32'hffffffff&((1'd1+seven_segment_digit_on_display
)%3'd4)]];
Tssc3_5_V_0 <= 32'd0;
seven_segment_digit_on_display <= ((1'd1+seven_segment_digit_on_display)%3'd4);
sTMT4Main_V_0 <= 32'd1+sTMT4Main_V_0;
xpc10nz <= 3'd6/*6:xpc10nz*/;
end
4'd8/*8:US*/: if ((Tsre2_0_V_0<3'd4)) begin
Tsre2_0_V_0 <= 32'd1+Tsre2_0_V_0;
A_SINT_CC_SCALbx10_ARA0[Tsre2_0_V_0] <= 32'd0;
xpc10nz <= 4'd8/*8:xpc10nz*/;
end
else xpc10nz <= 3'd7/*7:xpc10nz*/;
4'd9/*9:US*/: if (clear) begin
Tsre2_0_V_0 <= 32'd0;
xpc10nz <= 4'd8/*8:xpc10nz*/;
end
else xpc10nz <= 3'd7/*7:xpc10nz*/;
endcase
if ((xpc10nz==2'd3/*3:US*/)) xpc10nz <= 4'd9/*9:xpc10nz*/;
end
//End structure HPR seven-segment.exe
end
initial begin
//ROM data table: 11 words of 32 bits.
A_SINT_CC_SCALbx12_ARB0[0] = 32'h1;
A_SINT_CC_SCALbx12_ARB0[1] = 32'h4f;
A_SINT_CC_SCALbx12_ARB0[2] = 32'h12;
A_SINT_CC_SCALbx12_ARB0[3] = 32'h6;
A_SINT_CC_SCALbx12_ARB0[4] = 32'h4c;
A_SINT_CC_SCALbx12_ARB0[5] = 32'h24;
A_SINT_CC_SCALbx12_ARB0[6] = 32'h60;
A_SINT_CC_SCALbx12_ARB0[7] = 32'hf;
A_SINT_CC_SCALbx12_ARB0[8] = 32'h0;
A_SINT_CC_SCALbx12_ARB0[9] = 32'hc;
A_SINT_CC_SCALbx12_ARB0[10] = 32'h7e;
end
// 1 vectors of width 4
// 15 array locations of width 32
// 192 bits in scalar variables
// Total state bits in module = 676 bits.
// Total number of leaf cells = 0
endmodule
Alternate output code when ROMs were disabled: withoutrom.v.
Alternate output code with pipelined ROMs: withoutrom.v.
Makefile
#
# Kiwi Scientific Acceleration - Simple 7-segment display driver - net level
# (C) 2008 D J Greaves, University of Cambridge Computer Laboratory.
#
# Scan-multiplexed LED display driver simple demo.
#
# One display digit is illuminated at a time according to which segement strobe is active.
# The human eye integrates this and does not see any flicker provided the scanning is sufficiently fast (> 100 Hz).
SRC=seven-segment
MCS ?=mcs
KLIB1 ?=${HPRLS}/kiwipro/kiwic/distro/support/Kiwi.dll
KIWIC ?=${HPRLS}/kiwipro/kiwic/distro/bin/kiwic
simulate: $(SRC).v vsys.v
iverilog $(SRC).v vsys.v
./a.out
cp vcd.vcd ~/Dropbox
$(SRC).v: $(SRC).exe
$(KIWIC) $(SRC).exe -vnl-roundtrip=disable -vnl-resets=synchronous -restructure2=disable -vnl=seven-segment.v -vnl-rootmodname=DUT
# -res2-no-dram-ports=0
$(SRC).exe: $(SRC).cs
$(MCS) $(SRC).cs -r $(KLIB1)
zip:
zip kiwi-sevenseg-demo.zip Makefile $(SRC).v $(SRC).cs vsys.v kiwi-seven-segment-drive-waveforms.png
# eof
Simulation Test Bench
//
// Kiwi Scientific Acceleration
// University of Cambridge, Computer Laboratory
//
// vsys.v - A test wrapper for simulating very simple tests with clock and reset.
//
//
//
`timescale 1ns/10ps
module SIMSYS();
reg clk, reset;
initial begin reset = 1; clk = 1; # 43 reset = 0; end
always #5 clk = !clk;
initial begin # (100 * 1000) $display("Finish HDL simulation on timeout %t.", $time); $finish(); end
initial begin $dumpfile("vcd.vcd"); $dumpvars(); end
wire clear = 0;
wire [7:0] segments;
wire [3:0] strobes;
DUT the_dut(.clk(clk), .reset(reset), .clear(clear), .strobes(strobes), .segments(segments));
always @(posedge clk) begin
// $display("pc, thread0 = %d", the_dut.xpc10nz);
end
endmodule
// eof
Timing Waveforms
LARGER.
Updated April 2016
UP.