数字频率计设计

全国大学生电子设计竞赛相关题目

1997年B题 - 简易数字频率计设计

1 任务 - 设计并制作一台数字显示的简易频率计
2 要求

2.1 基本要求

  1. 频率测量
    1. 测量范围
      1. 信号:方波、正弦波
      2. 幅度:0.5-5V
      3. 频率:1Hz - 1MHz
    2. 测量误差:《0.1%
  2. 周期测量
    1. 测量范围
      • 信号:方波、正弦波
      • 幅度:0.5-5V
      • 频率:1Hz - 1MHz
    2. 测量误差:《0.1%
  3. 脉冲宽度测量
    1. 测量范围:
      1. 信号:脉冲波
      2. 幅度:0.5-5V
      3. 脉冲宽度:> 100us
    2. 测量误差:《1%
  4. 显示器:10进制数字显示,显示刷新时间1-10s连续可调,对上述三种测量功能分别用不同颜色的发光二极管指示
  5. 具有自校功能,时标信号频率为1MHz
  6. 自行设计并制作满足本设计任务要求的稳压电源

2.2 发挥部分

  1. 扩展频率测量范围为0.1Hz - 10MHz(信号幅度0.5-5V), 测试误差降低为0.01%(最大闸门时间《10s)
  2. 测量并显示周期脉冲信号(幅度0.5-5V,频率1Hz - 1KHz)的占空比。占空比变化范围为10%-90%,测试误差《1%
  3. 在1Hz-1MHz范围内及测试误差《0.1%的条件下,进行小信号的频率测量,提出并实现抗干扰的措施

2015年F题 - 数字频率计

1 任务

设计并制作一台闸门时间为1s的数字频率计

2 要求

2.1 基本要求

  1. 频率和周期测量功能
    1. 被测信号为正弦波,频率范围为1Hz ~ 10MHz
    2. 被测信号有效值电压范围为50mV - 1V
    3. 测量相对误差的绝对值不大于10-4
  2. 时间间隔测量功能
    1. 被测信号为方波,频率范围为100Hz-1MHz
    2. 被测信号峰峰值电压为50mV - 1V
    3. 被测时间间隔的范围为0.1us - 100ms
    4. 测量相对误差的绝对值不小于10-2
  3. 测量数据刷新时间不大于2s,测量结果稳定,并能够自动显示单位

2.2 发挥部分

  1. 频率和周期测量的正弦波信号频率范围为1H ~ 100MHz,其它要求同基本要求(1)和(3)
  2. 频率和周期测量时被测正弦信号的最小有效值电压为10mV, 其它要求同基本要求(1)和(3)
  3. 增加脉冲信号占空比的测量功能,要求:
    1. 被测信号为矩形波,频率范围为1Hz ~ 5MHz
    2. 被测信号峰峰值电压范围为50mV ~ 1V
    3. 被测脉冲信号占空比范围为10% ~ 90%
    4. 显示的分辨率为0.1%, 测量相对误差的绝对值不大于10-2
  4. 其它(例如,进一步降低被测信号电压电压的幅度等)

2015年全国大学生电子设计竞赛 - F题 - 数字频率计设计

本设计基于 step-max0-08sam核心板 和 training功能板 平台,测量模拟信号调理后的脉冲信号 fxa 的频率、周期、占空比、以及 fxa 和 fxb 信号的相位差。整体RTL图如下所示

RTL框图

设计只包含数字部分,系统主要由4个模块组成:

  1. 频率采样测量
  2. 频率数据运算
  3. BCD转码实现
  4. OLED显示实现

1. 频率采样测量

频率采样测量主要分为三种方法,直接测频法、周期测频法、等精度测频法。

等精度测量原理

通过对比,最终选择等精度测频法。

占空比测量在等精度测量的基础上,测量闸门时间内,使用标准信号对被测信号为高电平状态时间计数,占空比结果等于 Nduty * 100% / Ns


Verilog代码

//==========================================================================
//
// Author: STEP
// Module: freq_measure
// Description: 
// Web: www.stepfapga.com
//--------------------------------------------------------------------------
// Info:
//   V1.0---yyyy/mm/dd---Initial version
//
//==========================================================================
 
//timescale
`timescale 1ns / 1ns
module freq_measure (
    input clk_200m, //采用200MHz时钟信号
    input rst_n,
    input fxa,
    input fxb,
    input start,
 
    output reg done,
    output reg done1,
    output reg [WIDTH-1:0] FxCnt,
    output reg [WIDTH-1:0] FsCnt,
    output reg [WIDTH-1:0] DutyCnt,
    output reg [WIDTH-1:0] DelayDutyCnt,
    output reg [WIDTH-1:0] DelayCnt
);
 
//The defination of parameters
parameter WIDTH = 32; //
parameter CNT_1S = 'd199_999_999; //CLK=200M,then time=1S
 
reg t1s_gate;
reg fDelay_gate;
reg fxa_r1, fxa_r2, fxa_r3, fxa_pos;
reg fxb_r1, fxb_r2, fxb_r3, fxb_pos;
reg start_r, start_pos;
reg freq_real_gate;
reg delay_real_gate;
reg gate_done_r;
reg gate_done1_r;
reg [WIDTH-1:0] cnt_1s;
reg [WIDTH-1:0] fsCntTemp;
reg [WIDTH-1:0] fxCntTemp;
reg [WIDTH-1:0] DutyCntTemp;
reg [WIDTH-1:0] DelayDutyCntTemp;
reg [WIDTH-1:0] DelayCntTemp;
 
//检测两路信号的上升沿
////////////////////////////////////////////////////////////////////
//logic for fxa_r1, fxa_r2, fxa_r3
always @(posedge clk_200m) begin
    fxa_r1 <= fxa;
    fxa_r2 <= fxa_r1;
    fxa_r3 <= fxa_r2;
end
 
always @(posedge clk_200m) fxa_pos <= (!fxa_r3) && fxa_r2; 
 
//logic for fxb_r1, fxb_r2, fxb_r3
always @(posedge clk_200m) begin
    fxb_r1 <= fxb;
    fxb_r2 <= fxb_r1;
    fxb_r3 <= fxb_r2;
end
 
always @(posedge clk_200m) fxb_pos <= (!fxb_r3) && fxb_r2; 
 
//检测测试的start信号
////////////////////////////////////////////////////////////////////
//start signal detect
always @(posedge clk_200m) start_r <= start;
always @(posedge clk_200m) start_pos <= (!start_r) && start; 
 
//产生1秒时间的闸门参考信号
////////////////////////////////////////////////////////////////////
always @(posedge clk_200m or negedge rst_n) begin
    if(!rst_n) cnt_1s <= 1'b0;
    else if(cnt_1s >= CNT_1S) cnt_1s <= 1'b0;
    else if(t1s_gate) cnt_1s <= cnt_1s + 1'b1;
    else cnt_1s <= 1'b0;
end
 
always @(posedge clk_200m or negedge rst_n) begin
    if(!rst_n) t1s_gate <= 1'b0;
    else if(start_pos) t1s_gate <= 1'b1;
    else if(cnt_1s >= CNT_1S) t1s_gate <= 1'b0;
    else t1s_gate <= t1s_gate;
end
 
//根据被测信号的上升沿,产生被测信号周期整数倍的闸门信号
////////////////////////////////////////////////////////////////////
//synchronous gate of frequency count of signal fx
always @(posedge fxa_r2) begin
    if(t1s_gate) freq_real_gate <= 1'b1;
    else freq_real_gate <= 1'b0;
end
 
//根据闸门信号对 标准信号 和 被测信号 计数
always @(posedge clk_200m) fsCntTemp <= (freq_real_gate)? (fsCntTemp + 1'b1) : 1'b0;
always @(posedge fxa_r2)   fxCntTemp <= (freq_real_gate)? (fxCntTemp + 1'b1) : 1'b0;
 
//对闸门有效期间中,被测信号为高电平的时间计数
////////////////////////////////////////////////////////////////////
//Count input signal's duty
always @(posedge clk_200m) begin
    if(start_pos) DutyCntTemp <= 1'b0;
    else if(freq_real_gate && fxa_r2) DutyCntTemp <= DutyCntTemp + 1; //Count the high time
    else DutyCntTemp <= DutyCntTemp;
end 
 
//根据两路信号的上升沿,得到两路信号的相位差信号
////////////////////////////////////////////////////////////////////
//Produce time delay count gate
always @(posedge clk_200m or negedge rst_n) begin
    if(!rst_n) fDelay_gate <= 1'b0;
    else if(fxa_pos) fDelay_gate <= 1'b1;
    else if(fxb_pos) fDelay_gate <= 1'b0;
    else fDelay_gate <= fDelay_gate;
end 
 
//对相位差信号进行等精度测量
//synchronous gate of delay time count
always @(posedge fDelay_gate) begin
    if(t1s_gate) delay_real_gate <= 1'b1;
    else delay_real_gate <= 1'b0;
end
 
always @(posedge clk_200m) begin
    if(start_pos) DelayDutyCntTemp <= 1'b0;
    else if(delay_real_gate && fDelay_gate) DelayDutyCntTemp <= DelayDutyCntTemp + 1; //Count the high time
    else DelayDutyCntTemp <= DelayDutyCntTemp;
end 
 
always @(posedge clk_200m) DelayCntTemp <= (delay_real_gate)? (DelayCntTemp + 1'b1) : 1'b0;
 
//闸门信号结束,返回测量结果
////////////////////////////////////////////////////////////////////
//Output count data when mesure done
always @(negedge freq_real_gate) begin
    FxCnt <= fxCntTemp;
    FsCnt <= fsCntTemp;
    DutyCnt <= DutyCntTemp;
end
 
always @(negedge delay_real_gate) begin
    DelayDutyCnt <= DelayDutyCntTemp;
    DelayCnt <= DelayCntTemp;	
end
 
//产生测量结束信号
////////////////////////////////////////////////////////////////////
wire gate_done = /*delay_real_gate || */freq_real_gate;
 
always @(posedge clk_200m) gate_done_r <= gate_done;
always @(posedge clk_200m) done <= (!gate_done) && gate_done_r; 
 
wire gate_done1 = delay_real_gate/* || freq_real_gate*/;
 
always @(posedge clk_200m) gate_done1_r <= gate_done1;
always @(posedge clk_200m) done1 <= (!gate_done1) && gate_done1_r; 
 
endmodule
  1. 频率数据运算

在频率采样测量环节我们提到等精度测量,最后通过公式 Fx = Fs * Nx / Ns 运算出 被测信号 的频率,通过 Nduty * 100% / Ns 运算出 被测信号 的占空比

这里涉及乘法运算和除法运算,我们的FPGA器件MAX10系列 10M08SAM153C8G 集成了48个9位的乘法器,可以直接调用乘法器功能块。MAX10系列没有集成除法器功能块,直接使用除法逻辑会占用大量逻辑资源,性能也不能保证,所以我们使用流水的算法实现,稳定可靠。

对于64位的无符号数除法,被除数 numer 除以除数 denom,他们的商和余数一定不会超过64位,首先将 numer 转换成高64位为0,低64位为 numer 的tempa,再将 denom 转换成高64位为 denom,低64位为0的tempb。在每个周期开始前,先将tempa左移一位,末尾补0,然后与tempb相比较看是否大于tempb,若大于tempb,则tempa = tempa - tempb + 1,否则继续往下执行。上面的移位操作、比较和减法要执行64次,执行完成后得到的 tempa 的高64位为两数 numer 和 denom 相除的余数,低64位表示商。具体的算法流程可从下图的例子中得到体现

除法器算法原理


任意位宽除法器设计,Verilog代码

//==========================================================================
//
// Author: STEP
// Module: divider 
// Description: 
// Web: www.stepfapga.com
//--------------------------------------------------------------------------
// Info:
//   V1.0---yyyy/mm/dd---Initial version
//
//==========================================================================
 
//timescale
`timescale 1ns / 1ns
module divider #(
    parameter DATA_WIDTH = 64
)
(
    input clk,
    input rst_n,
 
    input start,
    input [DATA_WIDTH-1:0] numer, 
    input [DATA_WIDTH-1:0] denom,
 
    output done,
    output reg [DATA_WIDTH-1:0] quotient,
    output reg [DATA_WIDTH-1:0] remain
); 
 
reg [7:0] cnt;
reg [2*DATA_WIDTH-1:0] temp_a;
reg [2*DATA_WIDTH-1:0] temp_b;
reg done_r;
//------------------------------------------------
always @(posedge clk or negedge rst_n)begin
    if(!rst_n) cnt <= 1'b0;
    else if(start && (cnt < (DATA_WIDTH + 1))) cnt <= cnt + 1'b1; 
    else cnt <= 1'b0;
end
//------------------------------------------------
always @(posedge clk or negedge rst_n)
    if(!rst_n) done_r <= 1'b0;
    else if(cnt == DATA_WIDTH) done_r <= 1'b1;
    else if(cnt == DATA_WIDTH + 1) done_r <= 1'b0;
assign done = done_r;
//------------------------------------------------
always @(posedge clk or negedge rst_n)begin
    if(!rst_n) begin
        temp_a <= 64'h0;
        temp_b <= 64'h0;
    end
    else if(start) begin
        if(cnt == 1'b0) begin
            temp_a = {{DATA_WIDTH{1'b0}},numer};
            temp_b = {denom,{DATA_WIDTH{1'b0}}}; 
        end
        else begin
            temp_a = temp_a << 1;
      if(temp_a >= temp_b) temp_a = temp_a - temp_b + 1'b1;
      else temp_a = temp_a;
        end
     end
end
 
always @(posedge clk) quotient <= (cnt == DATA_WIDTH + 1)? temp_a[31: 0] : quotient;
always @(posedge clk) remain   <= (cnt == DATA_WIDTH + 1)? temp_a[63:32] : remain;
 
endmodule

我们最终计算频率、周期、占空比、以及相位差,将四路运算例化,得到整体的运算模块,Verilog代码

//==========================================================================
//
// Author: Step
// Module: arithmetic
// Description: 
// Web: www.stepfapga.com
//--------------------------------------------------------------------------
// Info:
//   V1.0---2021/01/14---Initial version
//
//==========================================================================
 
//timescale
`timescale 1ns / 1ns
 
//module
module arithmetic #
(
    parameter WIDTH = 32
)
(
    input clk,
    input rst_n,
    input start,
    input [WIDTH-1:0] FxCnt,
    input [WIDTH-1:0] FsCnt,
    input [WIDTH-1:0] DutyCnt,
    input [WIDTH-1:0] DelayDutyCnt,
    input [WIDTH-1:0] DelayCnt,
 
    output [WIDTH-1:0] Fxcnt_quotient,
    output [WIDTH-1:0] FxPeriod_quotient,
    output [WIDTH-1:0] DutyCnt_quotient,
    output [WIDTH-1:0] DelayDutyCnt_quotient
);
 
reg [2*WIDTH-1:0] Fxcnt_numer;
always @(posedge clk) 
    if(start) Fxcnt_numer <= FxCnt * 200_000_000;
    else Fxcnt_numer = Fxcnt_numer;
 
reg [2*WIDTH-1:0] DutyCnt_numer;
always @(posedge clk) 
    if(start) DutyCnt_numer <= DutyCnt * 'd1000;
    else DutyCnt_numer = DutyCnt_numer;
 
reg [2*WIDTH-1:0] DelayDutyCnt_numer;
always @(posedge clk) 
    if(start) DelayDutyCnt_numer <= DelayDutyCnt * 'd1000;
    else DelayDutyCnt_numer = DelayDutyCnt_numer;
 
wire [WIDTH-1:0] Fxcnt_denom = FsCnt;
wire [WIDTH-1:0] FxPeriod_denom = Fxcnt_quotient;
wire [WIDTH-1:0] DutyCnt_denom = FsCnt;
wire [WIDTH-1:0] DelayDutyCnt_denom = DelayCnt;
 
divider Fxcnt_u_div (
    .clk                     ( clk                        ),
    .rst_n                   ( rst_n                      ),
    .start                   ( 1'b1                       ),
    .numer                   ( Fxcnt_numer                ),
    .denom                   ( Fxcnt_denom                ),
    .quotient                ( Fxcnt_quotient             )
);
 
divider FxPeriod_u_div (
    .clk                     ( clk                       ),
    .rst_n                   ( rst_n                     ),
    .start                   ( 1'b1                      ),
    .numer                   ( 1_000_000_000             ),
    .denom                   ( FxPeriod_denom            ),
    .quotient                ( FxPeriod_quotient         ) 
);
 
divider DutyCnt_u_div (
    .clk                     ( clk                       ),
    .rst_n                   ( rst_n                     ),
    .start                   ( 1'b1                      ),
    .numer                   ( DutyCnt_numer             ),
    .denom                   ( DutyCnt_denom             ),
    .quotient                ( DutyCnt_quotient          )
);
 
divider DelayDutyCnt_u_div (
    .clk                     ( clk                       ),
    .rst_n                   ( rst_n                     ),
    .start                   ( 1'b1                      ),
    .numer                   ( DelayDutyCnt_numer        ),
    .denom                   ( DelayDutyCnt_denom        ),
    .quotient                ( DelayDutyCnt_quotient     )
);
 
endmodule //arithmetic
  1. BCD转码实现

通过运算得到的二进制数据,想要显示在OLED屏幕,要以十进制形式显示,需要对二进制数据进行BCD转码。

BCD转码实现原理


Verilog代码

//==========================================================================
//
// Author: STEP
// Module: bin2bcd
// Description: 
// Web: www.stepfapga.com
//--------------------------------------------------------------------------
// Info:
//   V1.0---yyyy/mm/dd---Initial version
//
//==========================================================================
 
//timescale
`timescale 1ns / 1ns
 
module bin2bcd #(
    parameter BIN_WIDTH = 32,
    parameter BCD_WIDTH = 40
)
(
    input clk,
    input rst_n,
    input start,
    input [BIN_WIDTH-1:0] bin_code,
    output reg done,
    output reg [BCD_WIDTH-1:0] bcd_code
);
//-------------------------------------------------------
localparam  IDLE    =   3'b001;
localparam   SHIFT   =   3'b010;
localparam   DONE    =   3'b100;
 
//-------------------------------------------------------
reg [2:0] state_c;
reg [2:0] state_n;
reg [BIN_WIDTH-1:0] shift_cnt;
reg [BIN_WIDTH-1:0] bin_reg;
reg [BCD_WIDTH-1:0] bcd_reg;
wire [BCD_WIDTH-1:0] bcd_temp;
 
//-------------------------------------------------------
//FSM step1
always @(posedge clk or negedge rst_n)begin
    if(!rst_n) state_c <= IDLE;
    else state_c <= state_n;
end
 
//FSM step2
always @(*) begin
    case(state_c)
        IDLE: state_n = (start)? SHIFT : IDLE;
        SHIFT: state_n = (shift_cnt==BIN_WIDTH-1)? DONE : SHIFT;
        DONE: state_n = IDLE;
        default:state_n = IDLE;
    endcase
end
 
//FSM step3
always @(posedge clk) begin
    case(state_c)
        IDLE:begin
            shift_cnt <= 1'b0; 
            bin_reg <= bin_code;
            bcd_reg <= 1'b0;
        end
        SHIFT:begin
            shift_cnt <= shift_cnt + 1'b1;
            bin_reg <= bin_reg << 1;
            bcd_reg <= {bcd_temp[BCD_WIDTH-2:0], bin_reg[BIN_WIDTH-1]};
        end
        default:begin
            shift_cnt <= 1'b0;
            bin_reg <= 1'b0;
            bcd_reg <= bcd_reg; 
        end
    endcase
end
 
//-------------------------------------------------------
assign bcd_temp[ 0+:4] = (bcd_reg[ 0+:4] > 4'd4)? (bcd_reg[ 0+:4] + 4'd3) : bcd_reg[ 0+:4];
assign bcd_temp[ 4+:4] = (bcd_reg[ 4+:4] > 4'd4)? (bcd_reg[ 4+:4] + 4'd3) : bcd_reg[ 4+:4];
assign bcd_temp[ 8+:4] = (bcd_reg[ 8+:4] > 4'd4)? (bcd_reg[ 8+:4] + 4'd3) : bcd_reg[ 8+:4]; 
assign bcd_temp[12+:4] = (bcd_reg[12+:4] > 4'd4)? (bcd_reg[12+:4] + 4'd3) : bcd_reg[12+:4]; 
assign bcd_temp[16+:4] = (bcd_reg[16+:4] > 4'd4)? (bcd_reg[16+:4] + 4'd3) : bcd_reg[16+:4];
assign bcd_temp[20+:4] = (bcd_reg[20+:4] > 4'd4)? (bcd_reg[20+:4] + 4'd3) : bcd_reg[20+:4];
assign bcd_temp[24+:4] = (bcd_reg[24+:4] > 4'd4)? (bcd_reg[24+:4] + 4'd3) : bcd_reg[24+:4]; 
assign bcd_temp[28+:4] = (bcd_reg[28+:4] > 4'd4)? (bcd_reg[28+:4] + 4'd3) : bcd_reg[28+:4]; 
assign bcd_temp[32+:4] = (bcd_reg[32+:4] > 4'd4)? (bcd_reg[32+:4] + 4'd3) : bcd_reg[32+:4]; 
assign bcd_temp[36+:4] = (bcd_reg[36+:4] > 4'd4)? (bcd_reg[36+:4] + 4'd3) : bcd_reg[36+:4];
 
always @(posedge clk) begin
    case(state_c)
        DONE: begin
            done <= 1'b1;
            bcd_code <= bcd_reg;
        end
        default: begin
            done <= 1'b0;
            bcd_code <= bcd_code;
        end
    endcase
end
 
endmodule 

例化多个BCD转码模块,实现多个数据的BCD转码功能,Verilog代码

 //==========================================================================
//
// Author: STEP
// Module: bin2bcd_top
// Description: 
// Web: www.stepfapga.com
//--------------------------------------------------------------------------
// Info:
//   V1.0---yyyy/mm/dd---Initial version
//
//==========================================================================
 
//timescale
`timescale 1ns / 1ns
 
module bin2bcd_top #(
    parameter BIN_WIDTH = 32,
    parameter BCD_WIDTH = 40
)
(
    input clk,
    input rst_n,
 
    input [BIN_WIDTH-1:0] Fxcnt_quotient,
    input [BIN_WIDTH-1:0] FxPeriod_quotient,
    input [BIN_WIDTH-1:0] DutyCnt_quotient,
    input [BIN_WIDTH-1:0] DelayDutyCnt_quotient,
 
    output [BCD_WIDTH-1:0] Fxcnt_quotient_code,
    output [BCD_WIDTH-1:0] FxPeriod_quotient_code,
    output [BCD_WIDTH-1:0] DutyCnt_quotient_code,
    output [BCD_WIDTH-1:0] DelayDutyCnt_quotient_code
);
 
bin2bcd u_bin2bcd_Fxcnt (
    .clk                     ( clk                  ),
    .rst_n                   ( rst_n                ),
    .start                   ( 1'b1                 ),
    .bin_code                ( Fxcnt_quotient       ),
    .bcd_code                ( Fxcnt_quotient_code  )
);
 
bin2bcd u_bin2bcd_FxPeriod (
    .clk                     ( clk                  ),
    .rst_n                   ( rst_n                ),
    .start                   ( 1'b1                 ),
    .bin_code                ( FxPeriod_quotient       ),
    .bcd_code                ( FxPeriod_quotient_code  )
);
 
bin2bcd u_bin2bcd_DutyCnt (
    .clk                     ( clk                  ),
    .rst_n                   ( rst_n                ),
    .start                   ( 1'b1                 ),
    .bin_code                ( DutyCnt_quotient       ),
    .bcd_code                ( DutyCnt_quotient_code  )
);
 
bin2bcd u_bin2bcd_DelayDutyCnt (
    .clk                     ( clk                  ),
    .rst_n                   ( rst_n                ),
    .start                   ( 1'b1                 ),
    .bin_code                ( DelayDutyCnt_quotient       ),
    .bcd_code                ( DelayDutyCnt_quotient_code  )
);
 
endmodule 

BCD转码之后的数据可以直接显示在OLED屏上了,但是为了看起来方便,我们对数据进行高位消零的操作。Verilog代码

//==========================================================================
//
// Author: Step
// Module: zero_clear
// Description: 
// Web: www.stepfapga.com
//--------------------------------------------------------------------------
// Info:
//   V1.0---2021/01/14---Initial version
//
//==========================================================================
 
//timescale
`timescale 1ns / 1ns
 
//include
 
//module
module zero_clear (
    input [39:0] Fxcnt_quotient_code,
    input [39:0] FxPeriod_quotient_code,
    input [11:0] DutyCnt_quotient_code,
    input [11:0] DelayDutyCnt_quotient_code,
 
    output [79:0] data1,
    output [79:0] data2,
    output [31:0] data3,
    output [31:0] data4
);
 
assign data1[72+:8] = Fxcnt_quotient_code[36+: 4]? Fxcnt_quotient_code[36+:4] : " ";
assign data1[64+:8] = Fxcnt_quotient_code[32+: 8]? Fxcnt_quotient_code[32+:4] : " ";
assign data1[56+:8] = Fxcnt_quotient_code[28+:12]? Fxcnt_quotient_code[28+:4] : " ";
assign data1[48+:8] = Fxcnt_quotient_code[24+:16]? Fxcnt_quotient_code[24+:4] : " ";
assign data1[40+:8] = Fxcnt_quotient_code[20+:20]? Fxcnt_quotient_code[20+:4] : " ";
assign data1[32+:8] = Fxcnt_quotient_code[16+:24]? Fxcnt_quotient_code[16+:4] : " ";
assign data1[24+:8] = Fxcnt_quotient_code[12+:28]? Fxcnt_quotient_code[12+:4] : " ";
assign data1[16+:8] = Fxcnt_quotient_code[ 8+:32]? Fxcnt_quotient_code[ 8+:4] : " ";
assign data1[ 8+:8] = Fxcnt_quotient_code[ 4+:36]? Fxcnt_quotient_code[ 4+:4] : " ";
assign data1[ 0+:8] = Fxcnt_quotient_code[ 0+: 4];
 
 
assign data2[72+:8] = FxPeriod_quotient_code[36+:4]? FxPeriod_quotient_code[36+:4] : " ";
assign data2[64+:8] = FxPeriod_quotient_code[32+:8]? FxPeriod_quotient_code[32+:4] : " ";
assign data2[56+:8] = FxPeriod_quotient_code[28+:12]? FxPeriod_quotient_code[28+:4] : " ";
assign data2[48+:8] = FxPeriod_quotient_code[24+:16]? FxPeriod_quotient_code[24+:4] : " ";
assign data2[40+:8] = FxPeriod_quotient_code[20+:20]? FxPeriod_quotient_code[20+:4] : " ";
assign data2[32+:8] = FxPeriod_quotient_code[16+:24]? FxPeriod_quotient_code[16+:4] : " ";
assign data2[24+:8] = FxPeriod_quotient_code[12+:28]? FxPeriod_quotient_code[12+:4] : " ";
assign data2[16+:8] = FxPeriod_quotient_code[ 8+:32]? FxPeriod_quotient_code[ 8+:4] : " ";
assign data2[ 8+:8] = FxPeriod_quotient_code[ 4+:36]? FxPeriod_quotient_code[ 4+:4] : " ";
assign data2[ 0+:8] = FxPeriod_quotient_code[ 0+: 4];
 
 
assign data3[24+:8] = DutyCnt_quotient_code[8+:4]? DutyCnt_quotient_code[8+:4] : " ";
assign data3[16+:8] = DutyCnt_quotient_code[4+:4];
assign data3[ 8+:8] = ".";
assign data3[ 0+:8] = DutyCnt_quotient_code[0+:4];
 
 
assign data4[24+:8] = DelayDutyCnt_quotient_code[8+:4]? DelayDutyCnt_quotient_code[8+:4] : " ";
assign data4[16+:8] = DelayDutyCnt_quotient_code[4+:4];
assign data4[ 8+:8] = ".";
assign data4[ 0+:8] = DelayDutyCnt_quotient_code[0+:4];
 
endmodule //zero_clear
  1. OLED显示实现

板载的OLED屏模块采用SSD1306驱动芯片,128*32分辨率,网上有很多使用单片机驱动的案例可以参考,直接上代码,Verilog代码如下

// --------------------------------------------------------------------
// >>>>>>>>>>>>>>>>>>>>>>>>> COPYRIGHT NOTICE <<<<<<<<<<<<<<<<<<<<<<<<<
// --------------------------------------------------------------------
// Module: OLED12832
// 
// Author: Step
// 
// Description: OLED12832_Driver,使用8*8点阵字库,每行显示128/8=16个字符
// 
// Web: www.stepfpga.com
// 
// --------------------------------------------------------------------
// Code Revision History :
// --------------------------------------------------------------------
// Version: |Mod. Date:   |Changes Made:
// V1.0     |2015/11/11   |Initial ver
// --------------------------------------------------------------------
module OLED12832 (
	input				clk,		//12MHz系统时钟
	input				rst_n,		//系统复位,低有效
 
	input		[79:0]	data1,		//
	input		[79:0]	data2,		//
	input		[79:0]	data3,		//
	input		[79:0]	data4,		//
 
	output	reg			oled_csn,	//OLCD液晶屏使能
	output	reg			oled_rst,	//OLCD液晶屏复位
	output	reg			oled_dcn,	//OLCD数据指令控制
	output	reg			oled_clk,	//OLCD时钟信号
	output	reg			oled_dat	//OLCD数据信号
);
 
	localparam INIT_DEPTH = 16'd25; //LCD初始化的命令的数量
	localparam IDLE = 6'h1, MAIN = 6'h2, INIT = 6'h4, SCAN = 6'h8, WRITE = 6'h10, DELAY = 6'h20;
	localparam HIGH	= 1'b1, LOW = 1'b0;
	localparam DATA	= 1'b1, CMD = 1'b0;
 
	reg [7:0] cmd [24:0];
	reg [39:0] mem [122:0];
	reg	[7:0]	y_p, x_ph, x_pl;
	reg	[(8*21-1):0] char;
	reg	[7:0]	num, char_reg;				//
	reg	[4:0]	cnt_main, cnt_init, cnt_scan, cnt_write;
	reg	[15:0]	num_delay, cnt_delay, cnt;
	reg	[5:0] 	state, state_back;
 
	always@(posedge clk or negedge rst_n) begin
		if(!rst_n) begin
			cnt_main <= 1'b0; cnt_init <= 1'b0; cnt_scan <= 1'b0; cnt_write <= 1'b0;
			y_p <= 1'b0; x_ph <= 1'b0; x_pl <= 1'b0;
			num <= 1'b0; char <= 1'b0; char_reg <= 1'b0;
			num_delay <= 16'd5; cnt_delay <= 1'b0; cnt <= 1'b0;
			oled_csn <= HIGH; oled_rst <= HIGH; oled_dcn <= CMD; oled_clk <= HIGH; oled_dat <= LOW;
			state <= IDLE; state_back <= IDLE;
		end else begin
			case(state)
				IDLE:begin
						cnt_main <= 1'b0; cnt_init <= 1'b0; cnt_scan <= 1'b0; cnt_write <= 1'b0;
						y_p <= 1'b0; x_ph <= 1'b0; x_pl <= 1'b0;
						num <= 1'b0; char <= 1'b0; char_reg <= 1'b0;
						num_delay <= 16'd5; cnt_delay <= 1'b0; cnt <= 1'b0;
						oled_csn <= HIGH; oled_rst <= HIGH; oled_dcn <= CMD; oled_clk <= HIGH; oled_dat <= LOW;
						state <= MAIN; state_back <= MAIN;
					end
				MAIN:begin
						if(cnt_main >= 5'd8) cnt_main <= 5'd5;
						else cnt_main <= cnt_main + 1'b1;
						case(cnt_main)	//MAIN状态
							5'd0:	begin state <= INIT; end
							5'd1:	begin y_p <= 8'hb0; x_ph <= 8'h10; x_pl <= 8'h00; num <= 5'd16; char <= "F:            Hz";state <= SCAN; end
							5'd2:	begin y_p <= 8'hb1; x_ph <= 8'h10; x_pl <= 8'h00; num <= 5'd16; char <= "T:            ns";state <= SCAN; end
							5'd3:	begin y_p <= 8'hb2; x_ph <= 8'h10; x_pl <= 8'h00; num <= 5'd16; char <= "Duty:        . %";state <= SCAN; end
							5'd4:	begin y_p <= 8'hb3; x_ph <= 8'h10; x_pl <= 8'h00; num <= 5'd16; char <= "Phase:       . %";state <= SCAN; end
 
							5'd5:	begin y_p <= 8'hb0; x_ph <= 8'h12; x_pl <= 8'h00; num <= 5'd10; char <= data1; state <= SCAN; end
							5'd6:	begin y_p <= 8'hb1; x_ph <= 8'h12; x_pl <= 8'h00; num <= 5'd10; char <= data2; state <= SCAN; end
							5'd7:	begin y_p <= 8'hb2; x_ph <= 8'h15; x_pl <= 8'h08; num <= 5'd4; char <= data3; state <= SCAN; end
							5'd8:	begin y_p <= 8'hb3; x_ph <= 8'h15; x_pl <= 8'h08; num <= 5'd4; char <= data4; state <= SCAN; end
 
							default: state <= IDLE;
						endcase
					end
				INIT:begin	//初始化状态
						case(cnt_init)
							5'd0:	begin oled_rst <= LOW; cnt_init <= cnt_init + 1'b1; end	//复位有效
							5'd1:	begin num_delay <= 16'd25000; state <= DELAY; state_back <= INIT; cnt_init <= cnt_init + 1'b1; end	//延时大于3us
							5'd2:	begin oled_rst <= HIGH; cnt_init <= cnt_init + 1'b1; end	//复位恢复
							5'd3:	begin num_delay <= 16'd25000; state <= DELAY; state_back <= INIT; cnt_init <= cnt_init + 1'b1; end	//延时大于220us
							5'd4:	begin 
										if(cnt>=INIT_DEPTH) begin	//当25条指令及数据发出后,配置完成
											cnt <= 1'b0;
											cnt_init <= cnt_init + 1'b1;
										end else begin	
											cnt <= cnt + 1'b1; num_delay <= 16'd5;
											oled_dcn <= CMD; char_reg <= cmd[cnt]; state <= WRITE; state_back <= INIT;
										end
									end
							5'd5:	begin cnt_init <= 1'b0; state <= MAIN; end	//初始化完成,返回MAIN状态
							default: state <= IDLE;
						endcase
					end
				SCAN:begin	//刷屏状态,从RAM中读取数据刷屏
						if(cnt_scan == 5'd11) begin
							if(num) cnt_scan <= 5'd3;
							else cnt_scan <= cnt_scan + 1'b1;
						end else if(cnt_scan == 5'd12) cnt_scan <= 1'b0;
						else cnt_scan <= cnt_scan + 1'b1;
						case(cnt_scan)
							5'd 0:	begin oled_dcn <= CMD; char_reg <= y_p; state <= WRITE; state_back <= SCAN; end		//定位列页地址
							5'd 1:	begin oled_dcn <= CMD; char_reg <= x_pl; state <= WRITE; state_back <= SCAN; end	//定位行地址低位
							5'd 2:	begin oled_dcn <= CMD; char_reg <= x_ph; state <= WRITE; state_back <= SCAN; end	//定位行地址高位
 
							5'd 3:	begin num <= num - 1'b1;end
							5'd 4:	begin oled_dcn <= DATA; char_reg <= 8'h00; state <= WRITE; state_back <= SCAN; end	//将5*8点阵编程8*8
							5'd 5:	begin oled_dcn <= DATA; char_reg <= 8'h00; state <= WRITE; state_back <= SCAN; end	//将5*8点阵编程8*8
							5'd 6:	begin oled_dcn <= DATA; char_reg <= 8'h00; state <= WRITE; state_back <= SCAN; end	//将5*8点阵编程8*8
							5'd 7:	begin oled_dcn <= DATA; char_reg <= mem[char[(num*8)+:8]][39:32]; state <= WRITE; state_back <= SCAN; end
							5'd 8:	begin oled_dcn <= DATA; char_reg <= mem[char[(num*8)+:8]][31:24]; state <= WRITE; state_back <= SCAN; end
							5'd 9:	begin oled_dcn <= DATA; char_reg <= mem[char[(num*8)+:8]][23:16]; state <= WRITE; state_back <= SCAN; end
							5'd10:	begin oled_dcn <= DATA; char_reg <= mem[char[(num*8)+:8]][15: 8]; state <= WRITE; state_back <= SCAN; end
							5'd11:	begin oled_dcn <= DATA; char_reg <= mem[char[(num*8)+:8]][ 7: 0]; state <= WRITE; state_back <= SCAN; end
							5'd12:	begin state <= MAIN; end
							default: state <= IDLE;
						endcase
					end
				WRITE:begin	//WRITE状态,将数据按照SPI时序发送给屏幕
						if(cnt_write >= 5'd17) cnt_write <= 1'b0;
						else cnt_write <= cnt_write + 1'b1;
						case(cnt_write)
							5'd 0:	begin oled_csn <= LOW; end	//9位数据最高位为命令数据控制位
							5'd 1:	begin oled_clk <= LOW; oled_dat <= char_reg[7]; end	//先发高位数据
							5'd 2:	begin oled_clk <= HIGH; end
							5'd 3:	begin oled_clk <= LOW; oled_dat <= char_reg[6]; end
							5'd 4:	begin oled_clk <= HIGH; end
							5'd 5:	begin oled_clk <= LOW; oled_dat <= char_reg[5]; end
							5'd 6:	begin oled_clk <= HIGH; end
							5'd 7:	begin oled_clk <= LOW; oled_dat <= char_reg[4]; end
							5'd 8:	begin oled_clk <= HIGH; end
							5'd 9:	begin oled_clk <= LOW; oled_dat <= char_reg[3]; end
							5'd10:	begin oled_clk <= HIGH; end
							5'd11:	begin oled_clk <= LOW; oled_dat <= char_reg[2]; end
							5'd12:	begin oled_clk <= HIGH; end
							5'd13:	begin oled_clk <= LOW; oled_dat <= char_reg[1]; end
							5'd14:	begin oled_clk <= HIGH; end
							5'd15:	begin oled_clk <= LOW; oled_dat <= char_reg[0]; end	//后发低位数据
							5'd16:	begin oled_clk <= HIGH; end
							5'd17:	begin oled_csn <= HIGH; state <= DELAY; end	//
							default: state <= IDLE;
						endcase
					end
				DELAY:begin	//延时状态
						if(cnt_delay >= num_delay) begin
							cnt_delay <= 16'd0; state <= state_back; 
						end else cnt_delay <= cnt_delay + 1'b1;
					end
				default:state <= IDLE;
			endcase
		end
	end
 
	//OLED配置指令数据
	always@(posedge rst_n)
		begin
			cmd[ 0] = {8'hae}; 
			cmd[ 1] = {8'h00}; 
			cmd[ 2] = {8'h10}; 
			cmd[ 3] = {8'h00}; 
			cmd[ 4] = {8'hb0}; 
			cmd[ 5] = {8'h81}; 
			cmd[ 6] = {8'hff}; 
			cmd[ 7] = {8'ha1}; 
			cmd[ 8] = {8'ha6}; 
			cmd[ 9] = {8'ha8}; 
			cmd[10] = {8'h1f}; 
			cmd[11] = {8'hc8};
			cmd[12] = {8'hd3};
			cmd[13] = {8'h00};
			cmd[14] = {8'hd5};
			cmd[15] = {8'h80};
			cmd[16] = {8'hd9};
			cmd[17] = {8'h1f};
			cmd[18] = {8'hda};
			cmd[19] = {8'h00};
			cmd[20] = {8'hdb};
			cmd[21] = {8'h40};
			cmd[22] = {8'h8d};
			cmd[23] = {8'h14};
			cmd[24] = {8'haf};
		end 
 
	//5*8点阵字库数据
	always@(posedge rst_n)
		begin
			mem[  0] = {8'h3E, 8'h51, 8'h49, 8'h45, 8'h3E};   // 48  0
			mem[  1] = {8'h00, 8'h42, 8'h7F, 8'h40, 8'h00};   // 49  1
			mem[  2] = {8'h42, 8'h61, 8'h51, 8'h49, 8'h46};   // 50  2
			mem[  3] = {8'h21, 8'h41, 8'h45, 8'h4B, 8'h31};   // 51  3
			mem[  4] = {8'h18, 8'h14, 8'h12, 8'h7F, 8'h10};   // 52  4
			mem[  5] = {8'h27, 8'h45, 8'h45, 8'h45, 8'h39};   // 53  5
			mem[  6] = {8'h3C, 8'h4A, 8'h49, 8'h49, 8'h30};   // 54  6
			mem[  7] = {8'h01, 8'h71, 8'h09, 8'h05, 8'h03};   // 55  7
			mem[  8] = {8'h36, 8'h49, 8'h49, 8'h49, 8'h36};   // 56  8
			mem[  9] = {8'h06, 8'h49, 8'h49, 8'h29, 8'h1E};   // 57  9
			mem[ 10] = {8'h7C, 8'h12, 8'h11, 8'h12, 8'h7C};   // 65  A
			mem[ 11] = {8'h7F, 8'h49, 8'h49, 8'h49, 8'h36};   // 66  B
			mem[ 12] = {8'h3E, 8'h41, 8'h41, 8'h41, 8'h22};   // 67  C
			mem[ 13] = {8'h7F, 8'h41, 8'h41, 8'h22, 8'h1C};   // 68  D
			mem[ 14] = {8'h7F, 8'h49, 8'h49, 8'h49, 8'h41};   // 69  E
			mem[ 15] = {8'h7F, 8'h09, 8'h09, 8'h09, 8'h01};   // 70  F
 
			mem[ 32] = {8'h00, 8'h00, 8'h00, 8'h00, 8'h00};   // 32  sp 
			mem[ 33] = {8'h00, 8'h00, 8'h2f, 8'h00, 8'h00};   // 33  !  
			mem[ 34] = {8'h00, 8'h07, 8'h00, 8'h07, 8'h00};   // 34  
			mem[ 35] = {8'h14, 8'h7f, 8'h14, 8'h7f, 8'h14};   // 35  #
			mem[ 36] = {8'h24, 8'h2a, 8'h7f, 8'h2a, 8'h12};   // 36  $
			mem[ 37] = {8'h62, 8'h64, 8'h08, 8'h13, 8'h23};   // 37  %
			mem[ 38] = {8'h36, 8'h49, 8'h55, 8'h22, 8'h50};   // 38  &
			mem[ 39] = {8'h00, 8'h05, 8'h03, 8'h00, 8'h00};   // 39  '
			mem[ 40] = {8'h00, 8'h1c, 8'h22, 8'h41, 8'h00};   // 40  (
			mem[ 41] = {8'h00, 8'h41, 8'h22, 8'h1c, 8'h00};   // 41  )
			mem[ 42] = {8'h14, 8'h08, 8'h3E, 8'h08, 8'h14};   // 42  *
			mem[ 43] = {8'h08, 8'h08, 8'h3E, 8'h08, 8'h08};   // 43  +
			mem[ 44] = {8'h00, 8'h00, 8'hA0, 8'h60, 8'h00};   // 44  ,
			mem[ 45] = {8'h08, 8'h08, 8'h08, 8'h08, 8'h08};   // 45  -
			mem[ 46] = {8'h00, 8'h60, 8'h60, 8'h00, 8'h00};   // 46  .
			mem[ 47] = {8'h20, 8'h10, 8'h08, 8'h04, 8'h02};   // 47  /
			mem[ 48] = {8'h3E, 8'h51, 8'h49, 8'h45, 8'h3E};   // 48  0
			mem[ 49] = {8'h00, 8'h42, 8'h7F, 8'h40, 8'h00};   // 49  1
			mem[ 50] = {8'h42, 8'h61, 8'h51, 8'h49, 8'h46};   // 50  2
			mem[ 51] = {8'h21, 8'h41, 8'h45, 8'h4B, 8'h31};   // 51  3
			mem[ 52] = {8'h18, 8'h14, 8'h12, 8'h7F, 8'h10};   // 52  4
			mem[ 53] = {8'h27, 8'h45, 8'h45, 8'h45, 8'h39};   // 53  5
			mem[ 54] = {8'h3C, 8'h4A, 8'h49, 8'h49, 8'h30};   // 54  6
			mem[ 55] = {8'h01, 8'h71, 8'h09, 8'h05, 8'h03};   // 55  7
			mem[ 56] = {8'h36, 8'h49, 8'h49, 8'h49, 8'h36};   // 56  8
			mem[ 57] = {8'h06, 8'h49, 8'h49, 8'h29, 8'h1E};   // 57  9
			mem[ 58] = {8'h00, 8'h36, 8'h36, 8'h00, 8'h00};   // 58  :
			mem[ 59] = {8'h00, 8'h56, 8'h36, 8'h00, 8'h00};   // 59  ;
			mem[ 60] = {8'h08, 8'h14, 8'h22, 8'h41, 8'h00};   // 60  <
			mem[ 61] = {8'h14, 8'h14, 8'h14, 8'h14, 8'h14};   // 61  =
			mem[ 62] = {8'h00, 8'h41, 8'h22, 8'h14, 8'h08};   // 62  >
			mem[ 63] = {8'h02, 8'h01, 8'h51, 8'h09, 8'h06};   // 63  ?
			mem[ 64] = {8'h32, 8'h49, 8'h59, 8'h51, 8'h3E};   // 64  @
			mem[ 65] = {8'h7C, 8'h12, 8'h11, 8'h12, 8'h7C};   // 65  A
			mem[ 66] = {8'h7F, 8'h49, 8'h49, 8'h49, 8'h36};   // 66  B
			mem[ 67] = {8'h3E, 8'h41, 8'h41, 8'h41, 8'h22};   // 67  C
			mem[ 68] = {8'h7F, 8'h41, 8'h41, 8'h22, 8'h1C};   // 68  D
			mem[ 69] = {8'h7F, 8'h49, 8'h49, 8'h49, 8'h41};   // 69  E
			mem[ 70] = {8'h7F, 8'h09, 8'h09, 8'h09, 8'h01};   // 70  F
			mem[ 71] = {8'h3E, 8'h41, 8'h49, 8'h49, 8'h7A};   // 71  G
			mem[ 72] = {8'h7F, 8'h08, 8'h08, 8'h08, 8'h7F};   // 72  H
			mem[ 73] = {8'h00, 8'h41, 8'h7F, 8'h41, 8'h00};   // 73  I
			mem[ 74] = {8'h20, 8'h40, 8'h41, 8'h3F, 8'h01};   // 74  J
			mem[ 75] = {8'h7F, 8'h08, 8'h14, 8'h22, 8'h41};   // 75  K
			mem[ 76] = {8'h7F, 8'h40, 8'h40, 8'h40, 8'h40};   // 76  L
			mem[ 77] = {8'h7F, 8'h02, 8'h0C, 8'h02, 8'h7F};   // 77  M
			mem[ 78] = {8'h7F, 8'h04, 8'h08, 8'h10, 8'h7F};   // 78  N
			mem[ 79] = {8'h3E, 8'h41, 8'h41, 8'h41, 8'h3E};   // 79  O
			mem[ 80] = {8'h7F, 8'h09, 8'h09, 8'h09, 8'h06};   // 80  P
			mem[ 81] = {8'h3E, 8'h41, 8'h51, 8'h21, 8'h5E};   // 81  Q
			mem[ 82] = {8'h7F, 8'h09, 8'h19, 8'h29, 8'h46};   // 82  R
			mem[ 83] = {8'h46, 8'h49, 8'h49, 8'h49, 8'h31};   // 83  S
			mem[ 84] = {8'h01, 8'h01, 8'h7F, 8'h01, 8'h01};   // 84  T
			mem[ 85] = {8'h3F, 8'h40, 8'h40, 8'h40, 8'h3F};   // 85  U
			mem[ 86] = {8'h1F, 8'h20, 8'h40, 8'h20, 8'h1F};   // 86  V
			mem[ 87] = {8'h3F, 8'h40, 8'h38, 8'h40, 8'h3F};   // 87  W
			mem[ 88] = {8'h63, 8'h14, 8'h08, 8'h14, 8'h63};   // 88  X
			mem[ 89] = {8'h07, 8'h08, 8'h70, 8'h08, 8'h07};   // 89  Y
			mem[ 90] = {8'h61, 8'h51, 8'h49, 8'h45, 8'h43};   // 90  Z
			mem[ 91] = {8'h00, 8'h7F, 8'h41, 8'h41, 8'h00};   // 91  [
			mem[ 92] = {8'h55, 8'h2A, 8'h55, 8'h2A, 8'h55};   // 92  .
			mem[ 93] = {8'h00, 8'h41, 8'h41, 8'h7F, 8'h00};   // 93  ]
			mem[ 94] = {8'h04, 8'h02, 8'h01, 8'h02, 8'h04};   // 94  ^
			mem[ 95] = {8'h40, 8'h40, 8'h40, 8'h40, 8'h40};   // 95  _
			mem[ 96] = {8'h00, 8'h01, 8'h02, 8'h04, 8'h00};   // 96  '
			mem[ 97] = {8'h20, 8'h54, 8'h54, 8'h54, 8'h78};   // 97  a
			mem[ 98] = {8'h7F, 8'h48, 8'h44, 8'h44, 8'h38};   // 98  b
			mem[ 99] = {8'h38, 8'h44, 8'h44, 8'h44, 8'h20};   // 99  c
			mem[100] = {8'h38, 8'h44, 8'h44, 8'h48, 8'h7F};   // 100 d
			mem[101] = {8'h38, 8'h54, 8'h54, 8'h54, 8'h18};   // 101 e
			mem[102] = {8'h08, 8'h7E, 8'h09, 8'h01, 8'h02};   // 102 f
			mem[103] = {8'h18, 8'hA4, 8'hA4, 8'hA4, 8'h7C};   // 103 g
			mem[104] = {8'h7F, 8'h08, 8'h04, 8'h04, 8'h78};   // 104 h
			mem[105] = {8'h00, 8'h44, 8'h7D, 8'h40, 8'h00};   // 105 i
			mem[106] = {8'h40, 8'h80, 8'h84, 8'h7D, 8'h00};   // 106 j
			mem[107] = {8'h7F, 8'h10, 8'h28, 8'h44, 8'h00};   // 107 k
			mem[108] = {8'h00, 8'h41, 8'h7F, 8'h40, 8'h00};   // 108 l
			mem[109] = {8'h7C, 8'h04, 8'h18, 8'h04, 8'h78};   // 109 m
			mem[110] = {8'h7C, 8'h08, 8'h04, 8'h04, 8'h78};   // 110 n
			mem[111] = {8'h38, 8'h44, 8'h44, 8'h44, 8'h38};   // 111 o
			mem[112] = {8'hFC, 8'h24, 8'h24, 8'h24, 8'h18};   // 112 p
			mem[113] = {8'h18, 8'h24, 8'h24, 8'h18, 8'hFC};   // 113 q
			mem[114] = {8'h7C, 8'h08, 8'h04, 8'h04, 8'h08};   // 114 r
			mem[115] = {8'h48, 8'h54, 8'h54, 8'h54, 8'h20};   // 115 s
			mem[116] = {8'h04, 8'h3F, 8'h44, 8'h40, 8'h20};   // 116 t
			mem[117] = {8'h3C, 8'h40, 8'h40, 8'h20, 8'h7C};   // 117 u
			mem[118] = {8'h1C, 8'h20, 8'h40, 8'h20, 8'h1C};   // 118 v
			mem[119] = {8'h3C, 8'h40, 8'h30, 8'h40, 8'h3C};   // 119 w
			mem[120] = {8'h44, 8'h28, 8'h10, 8'h28, 8'h44};   // 120 x
			mem[121] = {8'h1C, 8'hA0, 8'hA0, 8'hA0, 8'h7C};   // 121 y
			mem[122] = {8'h44, 8'h64, 8'h54, 8'h4C, 8'h44};   // 122 z
		end
 
endmodule