跳到主要内容

6.1.3 Verilog HDL建模描述

(1)设计文件MMA7660_test.v

// **************************************************************
// File name : MMA7660_test
// Module name : MMA7660_test
//
// Author : STEP
// Date : 2023.4.19
// Version : V 1.0
// Description : MMA7660 instance module
//
// Modification history
// //
// $Log$
//
// *********************************************************************-
// *****************************
// DEFINE MODULE PORT //
// ******************************
module MMA7660_test
(
// INPUT
input rst_n, //系统复位,低有效
// OUTPUT
output i2c_scl, //I2C时钟总线
inout i2c_sda, //I2C数据总线
output oled_rst, //
output oled_dcn, //
output oled_clk, //
output oled_dat
);


//WIRES
wire [7:0] xout, yout, zout, tilt, srst ,x_data_bcd, y_data_bcd, z_data_bcd;
wire clk;
// ******************************
// INSTANCE MODULE //
// ******************************
HSOSC #(
.CLKHF_DIV ("0b10")
) OSCInst0 (
.CLKHFEN (1'b1 ),
.CLKHFPU (1'b1 ),
.CLKHF (clk)
);

MMA7660_driver U_MMA7660_driver
(
.clk (clk ), //系统时钟
.rst_n (rst_n ), //系统复位,低有效
.i2c_scl (i2c_scl ), //I2C总线SCL
.i2c_sda (i2c_sda ), //I2C总线SDA
.xout (xout ), //读取数据
.yout (yout ), //读取数据
.zout (zout ) //读取数据
);

Calculate U_Calculate
(
.rst_n (rst_n),
.xout (xout),
.yout (yout),
.zout (zout),
.x_data_bcd (x_data_bcd),
.y_data_bcd (y_data_bcd),
.z_data_bcd (z_data_bcd)
);

OLED_driver U_OLED_driver
(
.clk (clk ), //系统时钟
.rst_n (rst_n ), //系统复位,低有效
.x_data_bcd (x_data_bcd ),
.y_data_bcd (y_data_bcd ),
.z_data_bcd (z_data_bcd ),
.oled_rst (oled_rst ),
.oled_dcn (oled_dcn ),
.oled_clk (oled_clk ),
.oled_dat (oled_dat )
);

endmodule

(2)设计文件MMA7660_driver.v

// **************************************************************
// File name : MMA7660_test
// Module name : MMA7660_driver
//
// Author : STEP
// Date : 2023.4.19
// Version : V 1.0
// Description : MMA7660 Driver
//
// Modification history
// //
// $Log$
//
// *********************************************************************
// *****************************
// DEFINE MODULE PORT //
// ******************************
module MMA7660_driver
(
// INPUT
input clk, //系统时钟
input rst_n, //系统复位,低有效
// OUTPUT
output reg [7:0] xout, //读取数据
output reg [7:0] yout,
output reg [7:0] zout,
output i2c_scl, //I2C总线SCL
inout i2c_sda //I2C总线SDA
);
// *****************************
// DEFINE PARAMETER //
// ******************************
parameter CNT_NUM = 15;
localparam IDLE = 4'd0;
localparam MAIN = 4'd1;
localparam MODE1 = 4'd2;
localparam MODE2 = 4'd3;
localparam START = 4'd4;
localparam WRITE = 4'd5;
localparam READ = 4'd6;
localparam STOP = 4'd7;
localparam DELAY = 4'd8;
localparam ACK = 1'b0;
localparam NACK = 1'b1;
// REGS
reg clk_400khz;
reg [9:0] cnt_400khz;
reg scl,sda,ack,ack_flag;
reg [3:0] cnt, cnt_main, cnt_mode1, cnt_mode2, cnt_start, cnt_write, cnt_read, cnt_stop;
reg [7:0] data_wr, dev_addr, dev_addr_r, reg_addr, data_r, reg_wr, read_data;
reg [23:0] cnt_delay, num_delay;
reg [3:0] state, state_back;
// ******************************
// MAIN CODE //
// ******************************
//使用计数器分频产生400KHz时钟信号clk_400khz
always@(posedge clk or negedge rst_n)
begin
if(!rst_n) begin
cnt_400khz <= 10'd0;
clk_400khz <= 1'b0;
end else if(cnt_400khz >= CNT_NUM-1) begin
cnt_400khz <= 10'd0;
clk_400khz <= ~clk_400khz;
end else begin
cnt_400khz <= cnt_400khz + 1'b1;
end
end
always@(posedge clk_400khz or negedge rst_n)
begin
if(!rst_n)
begin //如果按键复位,将相关数据初始化
scl <= 1'd1; sda <= 1'd1; ack <= ACK; ack_flag <= 1'b0; cnt <= 1'b0;
cnt_main <= 1'b0; cnt_mode1 <= 1'b0; cnt_mode2 <= 1'b0;
cnt_start <= 1'b0; cnt_write <= 1'b0; cnt_read <= 1'b0; cnt_stop <= 1'b0;
cnt_delay <= 1'b0; num_delay <= 24'd48000;
state <= IDLE; state_back <= IDLE;
end else begin
case(state)
IDLE:begin //软件自复位,主要用于程序跑飞后的处理
scl <= 1'd1; sda <= 1'd1; ack <= ACK; ack_flag <= 1'b0; cnt <= 1'b0;
cnt_main <= 1'b0;
cnt_start <= 1'b0; cnt_write <= 1'b0; cnt_read <= 1'b0; cnt_stop <= 1'b0;
cnt_delay <= 1'b0; num_delay <= 24'd48000;
state <= MAIN; state_back <= IDLE;
end
MAIN:begin
if(cnt_main >= 4'd8)
cnt_main <= 4'd2; //写完控制指令后循环读数据
else
cnt_main <= cnt_main + 1'b1;
case(cnt_main)
4'd0: begin dev_addr <= 8'h98; reg_addr <= 8'h07; reg_wr <= 8'h01; state <= MODE1; end //写入数据
4'd1: begin num_delay <= 24'd2000; state <= DELAY; end //5ms延时
4'd2: begin dev_addr <= 8'h98; dev_addr_r <= 8'h99; reg_addr <= 8'h01; state <= MODE2; end //读取数据
4'd3: begin xout <= read_data; end
4'd4: begin dev_addr <= 8'h98; dev_addr_r <= 8'h99; reg_addr <= 8'h02; state <= MODE2; end //读取数据
4'd5: begin yout <= read_data; end
4'd6: begin dev_addr <= 8'h98; dev_addr_r <= 8'h99; reg_addr <= 8'h03; state <= MODE2; end //读取数据
4'd7: begin zout <= read_data; end //读取数据
4'd8: begin num_delay <= 32'd48000; state <= DELAY; end //120ms延时
default: state <= IDLE; //如果程序失控,进入IDLE自复位状态
endcase
end
MODE1:begin //单次写操作
if(cnt_mode1 >= 3'd5)
cnt_mode1 <= 1'b0; //对START中的子状态执行控制cnt_start
else cnt_mode1 <= cnt_mode1 + 1'b1;
state_back <= MODE1;
case(cnt_mode1)
3'd0: begin state <= START; end //I2C通信时序中的START
3'd1: begin data_wr <= dev_addr; state <= WRITE; end //设备地址
3'd2: begin data_wr <= reg_addr; state <= WRITE; end //寄存器地址
3'd3: begin data_wr <= reg_wr; state <= WRITE; end //写入数据
3'd4: begin state <= STOP; end //I2C通信时序中的STOP
3'd5: begin state <= MAIN; end //返回MAIN
default: state <= IDLE; //如果程序失控,进入IDLE自复位状态
endcase
end
MODE2:begin //单次读操作
if(cnt_mode2 >= 4'd8)
cnt_mode2 <= 1'b0; //对START中的子状态执行控制cnt_start
else
cnt_mode2 <= cnt_mode2 + 1'b1;
state_back <= MODE2;
case(cnt_mode2)
4'd0: begin state <= START; end //I2C通信时序中的START
4'd1: begin data_wr <= dev_addr; state <= WRITE; end //设备地址
4'd2: begin data_wr <= reg_addr; state <= WRITE; end //寄存器地址
4'd3: begin state <= START; end //I2C通信时序中的START
4'd4: begin data_wr <= dev_addr_r; state <= WRITE; end //设备地址
4'd5: begin ack <= NACK; state <= READ; end //发送NACK信号,读寄存器数据
4'd6: begin read_data <= data_r; end
4'd7: begin state <= STOP; end //I2C通信时序中的STOP
4'd8: begin state <= MAIN; end //返回MAIN
default: state <= IDLE; //如果程序失控,进入IDLE自复位状态
endcase
end
START:begin //I2C通信时序中的起始START
if(cnt_start >= 3'd5)
cnt_start <= 1'b0; //对START中的子状态执行控制cnt_start
else
cnt_start <= cnt_start + 1'b1;
case(cnt_start)
3'd0: begin sda <= 1'b1; scl <= 1'b1; end //将SCL和SDA拉高,保持4.7us以上
3'd1: begin sda <= 1'b1; scl <= 1'b1; end //clk_400khz每个周期2.5us,需要两个周期
3'd2: begin sda <= 1'b0; end //SDA拉低到SCL拉低,保持4.0us以上
3'd3: begin sda <= 1'b0; end //clk_400khz每个周期2.5us,需要两个周期
3'd4: begin scl <= 1'b0; end //SCL拉低,保持4.7us以上
3'd5: begin scl <= 1'b0; state <= state_back; end //clk_400khz每个周期2.5us,需要两个周期,返回MAIN
default: state <= IDLE; //如果程序失控,进入IDLE自复位状态
endcase
end
WRITE:begin //I2C通信时序中的写操作WRITE和相应判断操作ACK
if(cnt <= 3'd6)
begin //共需要发送8bit的数据,这里控制循环的次数
if(cnt_write >= 3'd3)
begin
cnt_write <= 1'b0; cnt <= cnt + 1'b1;
end
else
begin
cnt_write <= cnt_write + 1'b1; cnt <= cnt;
end
end
else
begin
if(cnt_write >= 3'd7)
begin
cnt_write <= 1'b0; cnt <= 1'b0;
end //两个变量都恢复初值
else
begin
cnt_write <= cnt_write + 1'b1; cnt <= cnt;
end
end
case(cnt_write)
//按照I2C的时序传输数据
3'd0: begin scl <= 1'b0; sda <= data_wr[7-cnt]; end //SCL拉低,并控制SDA输出对应的位
3'd1: begin scl <= 1'b1; end //SCL拉高,保持4.0us以上
3'd2: begin scl <= 1'b1; end //clk_400khz每个周期2.5us,需要两个周期
3'd3: begin scl <= 1'b0; end //SCL拉低,准备发送下1bit的数据
//获取从设备的响应信号并判断
3'd4: begin sda <= 1'bz; end //释放SDA线,准备接收从设备的响应信号
3'd5: begin scl <= 1'b1; end //SCL拉高,保持4.0us以上
3'd6: begin ack_flag <= i2c_sda; end //获取从设备的响应信号并判断
3'd7: begin scl <= 1'b0; if(ack_flag)state <= state; else state <= state_back; end //SCL拉低,如果不应答循环写
default: state <= IDLE; //如果程序失控,进入IDLE自复位状态
endcase
end
READ:begin //I2C通信时序中的读操作READ和返回ACK的操作
if(cnt <= 3'd6) begin //共需要接收8bit的数据,这里控制循环的次数
if(cnt_read >= 3'd3) begin cnt_read <= 1'b0; cnt <= cnt + 1'b1; end
else begin cnt_read <= cnt_read + 1'b1; cnt <= cnt; end
end else begin
if(cnt_read >= 3'd7) begin cnt_read <= 1'b0; cnt <= 1'b0; end //两个变量都恢复初值
else begin cnt_read <= cnt_read + 1'b1; cnt <= cnt; end
end
case(cnt_read)
//按照I2C的时序接收数据
3'd0: begin scl <= 1'b0; sda <= 1'bz; end //SCL拉低,释放SDA线,准备接收从设备数据
3'd1: begin scl <= 1'b1; end //SCL拉高,保持4.0us以上
3'd2: begin data_r[7-cnt] <= i2c_sda; end //读取从设备返回的数据
3'd3: begin scl <= 1'b0; end //SCL拉低,准备接收下1bit的数据
//向从设备发送响应信号
3'd4: begin sda <= ack; end //发送响应信号,将前面接收的数据锁存
3'd5: begin scl <= 1'b1; end //SCL拉高,保持4.0us以上
3'd6: begin scl <= 1'b1; end //SCL拉高,保持4.0us以上
3'd7: begin scl <= 1'b0; state <= state_back; end //SCL拉低,返回MAIN状态
default: state <= IDLE; //如果程序失控,进入IDLE自复位状态
endcase
end
STOP:begin //I2C通信时序中的结束STOP
if(cnt_stop >= 3'd5) cnt_stop <= 1'b0; //对STOP中的子状态执行控制cnt_stop
else cnt_stop <= cnt_stop + 1'b1;
case(cnt_stop)
3'd0: begin sda <= 1'b0; end //SDA拉低,准备STOP
3'd1: begin sda <= 1'b0; end //SDA拉低,准备STOP
3'd2: begin scl <= 1'b1; end //SCL提前SDA拉高4.0us
3'd3: begin scl <= 1'b1; end //SCL提前SDA拉高4.0us
3'd4: begin sda <= 1'b1; end //SDA拉高
3'd5: begin sda <= 1'b1; state <= state_back; end //完成STOP操作,返回MAIN状态
default: state <= IDLE; //如果程序失控,进入IDLE自复位状态
endcase
end
DELAY:begin //12ms延时
if(cnt_delay >= num_delay) begin
cnt_delay <= 1'b0;
state <= MAIN;
end else cnt_delay <= cnt_delay + 1'b1;
end
default:;
endcase
end
end
assign i2c_scl = scl; //对SCL端口赋值
assign i2c_sda = sda; //对SDA端口赋值
endmodule

(3)设计文件OLED_driver.v

// **************************************************************
// File name : MMA7660_test
// Module name : OLED_driver
//
// Author : STEP
// Date : 2023.4.19
// Version : V 1.0
// Description : OLED Driver
//
// Modification history
// //
// $Log$
//
// *********************************************************************
// *****************************
// DEFINE MODULE PORT //
// ******************************
module OLED_driver
(
// INPUT
input clk, //
input rst_n, //
input [7:0] x_data_bcd,//写入数据
input [7:0] y_data_bcd,
input [7:0] z_data_bcd,
// OUTPUT
output reg oled_rst, //
output reg oled_dcn, //
output reg oled_clk, //
output reg oled_dat
);
// *****************************
// DEFINE PARAMETER //
// ******************************
localparam INIT_DEPTH = 16'd28; //
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;
// REGS
reg [7:0] cmd [27: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;
// ******************************
// MAIN CODE //
// ******************************
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_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_rst <= HIGH; oled_dcn <= CMD; oled_clk <= HIGH; oled_dat <= LOW;
state <= MAIN; state_back <= MAIN;
end
MAIN:begin
if(cnt_main >= 5'd14) cnt_main <= 5'd9;
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'h3 ; x_pl <= 8'h00; num <= 5'd16; char <= "x: ";state <= SCAN; end
5'd2: begin y_p <= 8'hb1; x_ph <= 8'h3 ; x_pl <= 8'h00; num <= 5'd16; char <= "y: ";state <= SCAN; end
5'd3: begin y_p <= 8'hb2; x_ph <= 8'h3 ; x_pl <= 8'h00; num <= 5'd16; char <= "z: ";state <= SCAN; end
5'd4: begin y_p <= 8'hb3; x_ph <= 8'h10; x_pl <= 8'h00; num <= 5'd16; char <= " ";state <= SCAN; end
5'd5: begin y_p <= 8'hb4; x_ph <= 8'h10; x_pl <= 8'h00; num <= 5'd16; char <= " ";state <= SCAN; end
5'd6: begin y_p <= 8'hb5; x_ph <= 8'h10; x_pl <= 8'h00; num <= 5'd16; char <= " ";state <= SCAN; end
5'd7: begin y_p <= 8'hb6; x_ph <= 8'h10; x_pl <= 8'h00; num <= 5'd16; char <= " ";state <= SCAN; end
5'd8: begin y_p <= 8'hb7; x_ph <= 8'h10; x_pl <= 8'h00; num <= 5'd16; char <= " ";state <= SCAN; end
5'd9: begin y_p <= 8'hb0; x_ph <= 8'h12; x_pl <= 8'h08; num <= 5'd 1; char <= x_data_bcd[7:4]; state <= SCAN; end
5'd10: begin y_p <= 8'hb0; x_ph <= 8'h12; x_pl <= 8'h00; num <= 5'd 1; char <= x_data_bcd[3:0]; state <= SCAN; end
5'd11: begin y_p <= 8'hb1; x_ph <= 8'h12; x_pl <= 8'h08; num <= 5'd 1; char <= y_data_bcd[7:4]; state <= SCAN; end
5'd12: begin y_p <= 8'hb1; x_ph <= 8'h12; x_pl <= 8'h00; num <= 5'd 1; char <= y_data_bcd[3:0]; state <= SCAN; end
5'd13: begin y_p <= 8'hb2; x_ph <= 8'h12; x_pl <= 8'h08; num <= 5'd 1; char <= z_data_bcd[7:4]; state <= SCAN; end
5'd14: begin y_p <= 8'hb2; x_ph <= 8'h12; x_pl <= 8'h00; num <= 5'd 1; char <= z_data_bcd[3:0]; 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 //
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 //
5'd4: begin
if(cnt>=INIT_DEPTH) begin //
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 //
default: state <= IDLE;
endcase
end
SCAN:begin //
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'd 5: begin oled_dcn <= DATA; char_reg <= 8'h00; state <= WRITE; state_back <= SCAN; end //
5'd 6: begin oled_dcn <= DATA; char_reg <= 8'h00; state <= WRITE; state_back <= SCAN; end //
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 //
if(cnt_write >= 5'd16) cnt_write <= 1'b0;
else cnt_write <= cnt_write + 1'b1;
case(cnt_write)
5'd 0: begin oled_clk <= LOW; oled_dat <= char_reg[7]; end //
5'd 1: begin oled_clk <= HIGH; end
5'd 2: begin oled_clk <= LOW; oled_dat <= char_reg[6]; end
5'd 3: begin oled_clk <= HIGH; end
5'd 4: begin oled_clk <= LOW; oled_dat <= char_reg[5]; end
5'd 5: begin oled_clk <= HIGH; end
5'd 6: begin oled_clk <= LOW; oled_dat <= char_reg[4]; end
5'd 7: begin oled_clk <= HIGH; end
5'd 8: begin oled_clk <= LOW; oled_dat <= char_reg[3]; end
5'd 9: begin oled_clk <= HIGH; end
5'd10: begin oled_clk <= LOW; oled_dat <= char_reg[2]; end
5'd11: begin oled_clk <= HIGH; end
5'd12: begin oled_clk <= LOW; oled_dat <= char_reg[1]; end
5'd13: begin oled_clk <= HIGH; end
5'd14: begin oled_clk <= LOW; oled_dat <= char_reg[0]; end //
5'd15: begin oled_clk <= HIGH; end
5'd16: begin 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

//
always@(negedge rst_n)

begin
cmd[ 0] = {8'hae};
cmd[ 1] = {8'h00};
cmd[ 2] = {8'h10};
cmd[ 3] = {8'h40};
cmd[ 4] = {8'h81};
cmd[ 5] = {8'hcf};
cmd[ 6] = {8'ha1};
cmd[ 7] = {8'hc8};
cmd[ 8] = {8'ha6};
cmd[ 9] = {8'ha8};
cmd[10] = {8'h3f};
cmd[11] = {8'hd3};
cmd[12] = {8'h00};
cmd[13] = {8'hd5};
cmd[14] = {8'h80};
cmd[15] = {8'hd9};
cmd[16] = {8'hf1};
cmd[17] = {8'hda};
cmd[18] = {8'h12};
cmd[19] = {8'hdb};
cmd[20] = {8'h40};
cmd[21] = {8'h20};
cmd[22] = {8'h02};
cmd[23] = {8'h8d};
cmd[24] = {8'h14};
cmd[25] = {8'ha4};
cmd[26] = {8'ha6};
cmd[27] = {8'haf};
end

always@(negedge rst_n)
//initial
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

(4)设计文件Calculate.v

// **************************************************************
// File name : MMA7660_test
// Module name : Calculate
//
// Author : STEP
// Date : 2023.4.19
// Version : V 1.0
// Description : Calculate module
//
// Modification history
// //
// $Log$
//
// *********************************************************************-
// *****************************
// DEFINE MODULE PORT //
// ******************************
module Calculate
(
// INPUT
input rst_n, //复位信号
input [7:0] xout, //写入数据
input [7:0] yout,
input [7:0] zout,
// OUTPUT
output [7:0] x_data_bcd,
output [7:0] y_data_bcd,
output [7:0] z_data_bcd
);
// ******************************
// INSTANCE MODULE //
// ******************************
bin_to_bcd u1
(
.rst_n (rst_n ), //系统复位,低有效
.bin_code (xout ), //需要进行BCD转码的二进制数据
.bcd_code (x_data_bcd ) //转码后的BCD码型数据输出
);

bin_to_bcd u2
(
.rst_n (rst_n ), //系统复位,低有效
.bin_code (yout ), //需要进行BCD转码的二进制数据
.bcd_code (y_data_bcd ) //转码后的BCD码型数据输出
);

bin_to_bcd u3
(
.rst_n (rst_n ), //系统复位,低有效
.bin_code (zout ), //需要进行BCD转码的二进制数据
.bcd_code (z_data_bcd ) //转码后的BCD码型数据输出
);
endmodule

(5)设计文件bin_to_bcd.v

// **************************************************************
// File name : MMA7660_test
// Module name : bin_to_bcd
//
// Author : STEP
// Date : 2023.4.19
// Version : V 1.0
// Description : bin_to_bcd module
//
// Modification history
// //
// $Log$
//
// *********************************************************************-
// *****************************
// DEFINE MODULE PORT //
// ******************************
module bin_to_bcd
(
// INPUT
input rst_n, //系统复位,低有效
input [7:0] bin_code, //需要进行BCD转码的二进制数据
// OUTPUT
output reg [7:0] bcd_code //转码后的BCD码型数据输出
);

/*
此模块为了将ADC采样的数据转换为我们常用的十进制显示而存在,
主要知识涉及数学中不同制式数据的转换,详细原理这里不做介绍,去百度搜索<FPGA 二进制转BCD码>可得
*/
// REGS
reg [15:0] shift_reg;
always@(bin_code or rst_n)begin
shift_reg = {8'h0,bin_code};
if(!rst_n) bcd_code = 0;
else begin
repeat(8) begin //循环8次
//BCD码各位数据作满5加3操作,
if (shift_reg[11:8] >= 5) shift_reg[11:8] = shift_reg[11:8] + 2'b11;
if (shift_reg[15:12] >= 5) shift_reg[15:12] = shift_reg[15:12] + 2'b11;
shift_reg = shift_reg << 1;
end
bcd_code = shift_reg[15:8];
end
end

endmodule
//module bin2bcd
//#( parameter W = 18) // input width
// ( input [W-1 :0] bin , // binary
// output reg [W+(W-4)/3:0] bcd ); // bcd {...,thousands,hundreds,tens,ones}

// integer i,j;

// always @(bin) begin
// for(i = 0; i <= W+(W-4)/3; i = i+1) bcd[i] = 0; // initialize with zeros
// bcd[W-1:0] = bin; // initialize with input vector
// for(i = 0; i <= W-4; i = i+1) // iterate on structure depth
// for(j = 0; j <= i/3; j = j+1) // iterate on structure width
//if (bcd[W-i+4*j -: 4] > 4) // if > 4
// bcd[W-i+4*j -: 4] = bcd[W-i+4*j -: 4] + 4'd3; // add 3
// end

//endmodule