基于FPGA使用串口发送B码时间信息-强化篇

绘制模块框图及状态图

彩色模块是ip核,灰色模块的b_code和uart_tx直接调用之前的模块代码即可。

编写模块代码

uart_send_IRIG_data_top

复制代码
module  uart_send_IRIG_data_top(
    input   wire        clk         ,
    input   wire        rst_n       ,

    output  wire        tx
);

wire        clk_125Mhz  ;
wire        locked      ;
wire        ex_b_code   ;
wire [3:0]  miao_gewei  ;
wire [2:0]  miao_shiwei ;
wire [3:0]  fen_gewei   ;
wire [2:0]  fen_shiwei  ;
wire [3:0]  shi_gewei   ;
wire [1:0]  shi_shiwei  ;
wire [3:0]  day_gewei   ;
wire [3:0]  day_shiwei  ;
wire [1:0]  day_baiwei  ;
wire [3:0]  year_gewei  ;
wire [3:0]  year_shiwei ;
wire        send_done   ;
wire        pi_flag     ;
wire [7:0]  pi_data     ;

pll_125Mhz  pll_125Mhz_inst (
    .areset ( ~rst_n    ),
    .inclk0 ( clk       ),
    .c0     ( clk_125Mhz),
    .locked ( locked    )
);

b_code_gen      
#(
    .TIME_1S     ( 32'd124_999_999),//32'd124_999_999
    .TIME_10MS   ( 32'd1_249_999  ),//32'd1_249_999  
    .TIME_8MS    ( 32'd999_999    ),//32'd999_999    
    .TIME_5MS    ( 32'd624_999    ),//32'd624_999    
    .TIME_2MS    ( 32'd249_999    )//32'd249_999    
)
b_code_gen_inst
(
    .clk       (clk_125Mhz),//125Mhz
    .rst_n     (locked    ),

    .ex_b_code (ex_b_code )
);

b_code
#(
    .TIME_10MS ( 32'd1_249_999),//32'd1_249_999
    .TIME_8MS  ( 32'd999_999  ),//32'd999_999  
    .TIME_2MS  ( 32'd249_999  ),//32'd249_999  
    .TIME_5MS  ( 32'd624_999  ),//32'd624_999  
    .WUCHA_8US ( 32'd1000     ) //32'd1000
)
b_code_inst
(
    .clk_125Mhz  (clk_125Mhz ),
    .rst_n       (locked     ),
    .ex_b_code   (ex_b_code  ),
                  
    .miao_gewei  (miao_gewei ),
    .miao_shiwei (miao_shiwei),
                  
    .fen_gewei   (fen_gewei  ),
    .fen_shiwei  (fen_shiwei ),
                  
    .shi_gewei   (shi_gewei  ),
    .shi_shiwei  (shi_shiwei ),
                  
    .day_gewei   (day_gewei  ),
    .day_shiwei  (day_shiwei ),
    .day_baiwei  (day_baiwei ),
                  
    .year_gewei  (year_gewei ),
    .year_shiwei (year_shiwei)
);

fsm     
#(
    .TIME_1S     (32'd124_999_999)//32'd124_999_999
)
fsm_inst
(
    .clk         (clk_125Mhz ),
    .rst_n       (locked     ),
    .send_done   (send_done  ),//控制串口发送信号线
    .miao_gewei  (miao_gewei ),
    .miao_shiwei (miao_shiwei),

    .fen_gewei   (fen_gewei  ),
    .fen_shiwei  (fen_shiwei ),

    .shi_gewei   (shi_gewei  ),
    .shi_shiwei  (shi_shiwei ),

    .day_gewei   (day_gewei  ),
    .day_shiwei  (day_shiwei ),
    .day_baiwei  (day_baiwei ),

    .year_gewei  (year_gewei ),
    .year_shiwei (year_shiwei),

    .pi_flag     (pi_flag    ),
    .pi_data     (pi_data    )
);

uart_tx     
#(
    .CLK_FREQ  ('d124_999_999),
    .BPS       ('d9600       )
)
uart_tx_inst
(
    .clk       (clk_125Mhz   ) ,
    .rst_n     (locked       ) ,
    .pi_flag   (pi_flag      ) ,
    .pi_data   (pi_data      ) ,
                             
    .send_done (send_done    ) ,
    .tx        (tx           )
);
endmodule

b_code_gen

复制代码
module  b_code_gen
#(
    parameter   TIME_1S     = 32'd124_999_999,
    parameter   TIME_10MS   = 32'd1_249_999  ,
    parameter   TIME_8MS    = 32'd999_999    ,
    parameter   TIME_5MS    = 32'd624_999    ,
    parameter   TIME_2MS    = 32'd249_999
)
(
    input   wire        clk     ,//125Mhz
    input   wire        rst_n   ,
    
    output  reg         ex_b_code
);

parameter   idle = 8'd0;
parameter   s0   = 8'd1;
parameter   s1   = 8'd2;
parameter   s2   = 8'd3;
parameter   s3   = 8'd4;
parameter   s4   = 8'd5;
parameter   s5   = 8'd6;

//给3个基本码元类型编码
parameter	MAYUAN_P = 8'h50;
parameter	MAYUAN_0 = 8'h30;
parameter	MAYUAN_1 = 8'h31;

parameter   MAYUAN_NUM = 'd100;

//定义B码的一帧数据的数组,B码一帧数据有100个码元
wire [7:0]	mem	[99:0];
//26年154天12时59分48秒
assign	mem[0]	= MAYUAN_P;//位置分隔符
assign	mem[1]	= MAYUAN_P;
assign	mem[2]	= MAYUAN_0;//秒个位
assign	mem[3]	= MAYUAN_0;
assign	mem[4]	= MAYUAN_0;
assign	mem[5]	= MAYUAN_1;
assign	mem[6]	= MAYUAN_0;//索引标志,置0
assign	mem[7]	= MAYUAN_0;//秒十位
assign	mem[8]	= MAYUAN_0;
assign	mem[9]	= MAYUAN_1;

assign	mem[10]	= MAYUAN_P;//位置分隔符
assign	mem[11]	= MAYUAN_1;//分个位
assign	mem[12]	= MAYUAN_0;
assign	mem[13]	= MAYUAN_0;
assign	mem[14]	= MAYUAN_1;
assign	mem[15]	= MAYUAN_0;//索引标志,置0
assign	mem[16]	= MAYUAN_1;//分十位
assign	mem[17]	= MAYUAN_0;
assign	mem[18]	= MAYUAN_1;
assign	mem[19]	= MAYUAN_0;//保留,置0

assign	mem[20]	= MAYUAN_P;//位置分隔符
assign	mem[21]	= MAYUAN_0;//时个位
assign	mem[22]	= MAYUAN_1;
assign	mem[23]	= MAYUAN_0;
assign	mem[24]	= MAYUAN_0;
assign	mem[25]	= MAYUAN_0;//索引标志,置0
assign	mem[26]	= MAYUAN_1;//时十位
assign	mem[27]	= MAYUAN_0;
assign	mem[28]	= MAYUAN_0;//保留,置0
assign	mem[29]	= MAYUAN_0;//保留,置0

assign	mem[30]	= MAYUAN_P;//位置分隔符
assign	mem[31]	= MAYUAN_0;//日个位
assign	mem[32]	= MAYUAN_0;
assign	mem[33]	= MAYUAN_1;
assign	mem[34]	= MAYUAN_0;
assign	mem[35]	= MAYUAN_0;//索引标志,置0
assign	mem[36]	= MAYUAN_1;//日十位
assign	mem[37]	= MAYUAN_0;
assign	mem[38]	= MAYUAN_1;
assign	mem[39]	= MAYUAN_0;

assign	mem[40]	= MAYUAN_P;//位置分隔符
assign	mem[41]	= MAYUAN_1;//日百位
assign	mem[42]	= MAYUAN_0;
assign	mem[43]	= MAYUAN_0;//保留,置0
assign	mem[44]	= MAYUAN_0;//保留,置0
assign	mem[45]	= MAYUAN_0;//保留,置0
assign	mem[46]	= MAYUAN_0;//保留,置0
assign	mem[47]	= MAYUAN_0;//保留,置0
assign	mem[48]	= MAYUAN_0;//保留,置0
assign	mem[49]	= MAYUAN_0;//保留,置0

assign	mem[50]	= MAYUAN_P;//位置分隔符
assign	mem[51]	= MAYUAN_0;//年个位
assign	mem[52]	= MAYUAN_1;
assign	mem[53]	= MAYUAN_1;
assign	mem[54]	= MAYUAN_0;
assign	mem[55]	= MAYUAN_0;//索引标志,置0
assign	mem[56]	= MAYUAN_0;//年十位
assign	mem[57]	= MAYUAN_1;
assign	mem[58]	= MAYUAN_0;
assign	mem[59]	= MAYUAN_0;

assign	mem[60]	= MAYUAN_P;//p//位置分隔符
assign	mem[61]	= MAYUAN_0;//0//闰秒预告LSP
assign	mem[62]	= MAYUAN_0;//0//闰秒标志LS
assign	mem[63]	= MAYUAN_0;//0//夏制时预告DSP
assign	mem[64]	= MAYUAN_0;//0//夏制时标志DST
assign	mem[65]	= MAYUAN_0;//0//时间偏移符号位
assign	mem[66]	= MAYUAN_0;//0
assign	mem[67]	= MAYUAN_0;//0
assign	mem[68]	= MAYUAN_0;//0
assign	mem[69]	= MAYUAN_0;//0

assign	mem[70]	= MAYUAN_P;//p位置分隔符
assign	mem[71]	= MAYUAN_0;//0不增加时间偏移量
assign	mem[72]	= MAYUAN_0;//0正常工作状态
assign	mem[73]	= MAYUAN_0;//0正常工作状态
assign	mem[74]	= MAYUAN_0;//0正常工作状态
assign	mem[75]	= MAYUAN_0;//0正常工作状态
assign	mem[76]	= MAYUAN_1;//1(校验位)
assign	mem[77]	= MAYUAN_0;//0//保留,置0
assign	mem[78]	= MAYUAN_0;//0//保留,置0
assign	mem[79]	= MAYUAN_0;//0//保留,置0

assign	mem[80]	= MAYUAN_P;//位置分隔符
assign	mem[81]	= MAYUAN_0;//0 //一天中的秒数(二进制低9位)
assign	mem[82]	= MAYUAN_0;//0 //一天中的秒数86400
assign	mem[83]	= MAYUAN_0;//0
assign	mem[84]	= MAYUAN_0;//0
assign	mem[85]	= MAYUAN_0;//0
assign	mem[86]	= MAYUAN_0;//0
assign	mem[87]	= MAYUAN_0;//0
assign	mem[88]	= MAYUAN_1;//1
assign	mem[89]	= MAYUAN_1;//1

assign	mem[90]	= MAYUAN_P;//位置分隔符
assign	mem[91]	= MAYUAN_0;//0 //一天中的秒数(二进制高9位)
assign	mem[92]	= MAYUAN_0;//0
assign	mem[93]	= MAYUAN_0;//0
assign	mem[94]	= MAYUAN_1;//1
assign	mem[95]	= MAYUAN_0;//0
assign	mem[96]	= MAYUAN_1;//1
assign	mem[97]	= MAYUAN_0;//0
assign	mem[98]	= MAYUAN_1;//1
assign	mem[99]	= MAYUAN_0;//0

reg [7:0]   state       ;
reg [31:0]  cnt_10ms    ;
reg [7:0]   index       ;
reg [7:0]   cnt_mayuan  ;

always@(posedge clk or negedge rst_n)
begin
    if(!rst_n)
        begin
            state       <=  idle;
            cnt_10ms    <=  32'd0;
            index       <=  8'd0;
            cnt_mayuan  <=  8'd0;
            ex_b_code   <=  1'b0;
        end
    else
        case(state)
            idle:
                begin
                    state       <=  s0;
                    cnt_10ms    <=  32'd0;
                    index       <=  8'd0;
                    cnt_mayuan  <=  8'd0;
                    ex_b_code   <=  1'b0;
                end
            s0  :
                begin
                    if(mem[index] == MAYUAN_P)
                        state       <=  s1;
                    else    if(mem[index] == MAYUAN_0)
                        state       <=  s2;
                    else//    if(mem[index] == MAYUAN_1)
                        state       <=  s3;
                end
            s1  :
                begin
                    if(cnt_10ms == TIME_10MS)
                        begin
                            state       <=  s4;
                            cnt_10ms    <=  32'd0;
                        end
                    else    if(cnt_10ms <= TIME_8MS)
                        begin
                            ex_b_code   <=  1'b1;
                            cnt_10ms    <=  cnt_10ms + 1'b1;
                        end
                    else
                        begin
                            ex_b_code   <=  1'b0;
                            cnt_10ms    <=  cnt_10ms + 1'b1;
                        end
                end
            s2  :
                begin
                    if(cnt_10ms == TIME_10MS)
                        begin
                            state       <=  s4;
                            cnt_10ms    <=  32'd0;
                        end
                    else    if(cnt_10ms <= TIME_2MS)
                        begin
                            ex_b_code   <=  1'b1;
                            cnt_10ms    <=  cnt_10ms + 1'b1;
                        end
                    else
                        begin
                            ex_b_code   <=  1'b0;
                            cnt_10ms    <=  cnt_10ms + 1'b1;
                        end
                end
            s3  :
                begin
                    if(cnt_10ms == TIME_10MS)
                        begin
                            state       <=  s4;
                            cnt_10ms    <=  32'd0;
                        end
                    else    if(cnt_10ms <= TIME_5MS)
                        begin
                            ex_b_code   <=  1'b1;
                            cnt_10ms    <=  cnt_10ms + 1'b1;
                        end
                    else
                        begin
                            ex_b_code   <=  1'b0;
                            cnt_10ms    <=  cnt_10ms + 1'b1;
                        end
                end
            s4  :
                begin
                    index       <=  index + 1'b1;
                    cnt_mayuan  <=  cnt_mayuan + 1'b1;
                    state       <=  s5;
                end
            s5  :
                begin
                    if(cnt_mayuan == MAYUAN_NUM)
                        state       <=  idle;
                    else
                        state       <=  s0;
                end
            default:
                begin
                    state       <=  idle;
                    cnt_10ms    <=  32'd0;
                    index       <=  8'd0;
                    cnt_mayuan  <=  8'd0;
                    ex_b_code   <=  1'b0;
                end
        endcase
end
endmodule

b_code

复制代码
module  b_code
#(
    parameter   TIME_10MS = 32'd1_249_999,
    parameter   TIME_8MS  = 32'd999_999  ,
    parameter   TIME_2MS  = 32'd249_999  ,
    parameter   TIME_5MS  = 32'd629_999  ,
    parameter   WUCHA_8US = 32'd1000
)
(
    input   wire        clk_125Mhz  ,
    input   wire        rst_n       ,
    input   wire        ex_b_code   ,
    
    output  reg [3:0]   miao_gewei  ,
    output  reg [2:0]   miao_shiwei ,
    
    output  reg [3:0]   fen_gewei   ,
    output  reg [2:0]   fen_shiwei  ,
    
    output  reg [3:0]   shi_gewei   ,
    output  reg [1:0]   shi_shiwei  ,
    
    output  reg [3:0]   day_gewei   ,
    output  reg [3:0]   day_shiwei  ,
    output  reg [1:0]   day_baiwei  ,
    
    output  reg [3:0]   year_gewei  ,
    output  reg [3:0]   year_shiwei
);
// 消除ex_b_code亚稳态,提高信号质量
reg         ex_b_code_0;
reg         ex_b_code_1;
reg         ex_b_code_2;

reg         fall_0      ;//用于确定当前码元类型(now_type)
reg         fall_1      ;//同时有锁定的码元类型(latch_type)和当前码元类型(now_type),用于开始信号双p检测
reg         fall_2      ;//更新锁定的上一个码元信息(latch_type)
reg         fall_3      ;//用于定位一帧数据中当前码元对应的序号
reg         fall_4      ;//用于完成当前码元的时间信息解析
reg         fall_5      ;//用于全部解析完成的整体输出
reg         fall_6      ;//预留
reg         fall_7      ;//用于高电平计数器计数值的清零(高电平计数器:计数高电平保持时常确定码元)

reg [31:0]  cnt_b       ;
reg [1:0]   now_type    ;
reg         work_state  ;
reg [1:0]   latch_type  ;
reg [7:0]   cnt_mem     ;
// 多级打拍处理,消除ex_b_code亚稳态,提高信号质量,下降沿检测
always@(posedge clk_125Mhz or negedge rst_n)
begin
    if(!rst_n)
        begin
            ex_b_code_0 <= 1'b0;
            ex_b_code_1 <= 1'b0;
            ex_b_code_2 <= 1'b0;

            fall_0      <= 1'b0;
            fall_1      <= 1'b0;
            fall_2      <= 1'b0;
            fall_3      <= 1'b0;
            fall_4      <= 1'b0;
            fall_5      <= 1'b0;
            fall_6      <= 1'b0;
            fall_7      <= 1'b0;
        end
    else
        begin
            ex_b_code_0 <= ex_b_code    ;
            ex_b_code_1 <= ex_b_code_0  ;
            ex_b_code_2 <= ex_b_code_1  ;

            fall_0      <= ~ex_b_code_1 && ex_b_code_2;
            fall_1      <= fall_0   ;
            fall_2      <= fall_1   ;
            fall_3      <= fall_2   ;
            fall_4      <= fall_3   ;
            fall_5      <= fall_4   ;
            fall_6      <= fall_5   ;
            fall_7      <= fall_6   ;
        end
end
// cnt_b:高电平计数器,低电平保持,fall_7清零
always@(posedge clk_125Mhz or negedge rst_n)
begin
    if(!rst_n)
        cnt_b <= 32'd0;
    else    if(fall_7)//注意优先级
        cnt_b <= 32'd0;
    else    if(ex_b_code_2)
        cnt_b <= cnt_b + 1'b1;
    else
        cnt_b <= cnt_b;
end
// now_type:当前码元类型 0码:00;1码:01;p码:10
always@(posedge clk_125Mhz or negedge rst_n)
begin
    if(!rst_n)
        now_type <= 2'b11   ;
    else    if(fall_0 && TIME_8MS - WUCHA_8US <= cnt_b && cnt_b <= TIME_8MS + WUCHA_8US)
        now_type <= 2'b10   ;//p
    else    if(fall_0 && TIME_5MS - WUCHA_8US <= cnt_b && cnt_b <= TIME_5MS + WUCHA_8US)
        now_type <= 2'b01   ;//1
    else    if(fall_0 && TIME_2MS - WUCHA_8US <= cnt_b && cnt_b <= TIME_2MS + WUCHA_8US)
        now_type <= 2'b00   ;//0
    else    if(fall_0)
        now_type <= 2'b11   ;//出现错码
    else
        now_type <= now_type;
end
// latch_type:锁定上一个码元
always@(posedge clk_125Mhz or negedge rst_n)
begin
    if(!rst_n)
        latch_type <= 2'b11     ;
    else    if(fall_2)
        latch_type <= now_type  ;
    else
        latch_type <= latch_type;
end
// work_state:工作状态(双p检测)
always@(posedge clk_125Mhz or negedge rst_n)
begin
    if(!rst_n)
        work_state <= 1'b0;
    else    if(fall_1 && now_type == 2'b10 && latch_type == 2'b10)
        work_state <= 1'b1;
    else    if(cnt_mem == 8'd61)
        work_state <= 1'b0;
    else
        work_state <= work_state;
end
// cnt_mem:码元序号
always@(posedge clk_125Mhz or negedge rst_n)
begin
    if(!rst_n)
        cnt_mem <= 8'd0;
    else    if(~work_state)
        cnt_mem <= 8'd0;
    else    if(fall_3)
        cnt_mem <= cnt_mem + 1'b1;
    else
        cnt_mem <= cnt_mem;
end
// 时间输出寄存器(为了统一输出时间)
reg [3:0]   miao_gewei_r ;
reg [2:0]   miao_shiwei_r;
reg [3:0]   fen_gewei_r  ;
reg [2:0]   fen_shiwei_r ;
reg [3:0]   shi_gewei_r  ;
reg [1:0]   shi_shiwei_r ;
reg [3:0]   day_gewei_r  ;
reg [3:0]   day_shiwei_r ;
reg [1:0]   day_baiwei_r ;
reg [3:0]   year_gewei_r ;
reg [3:0]   year_shiwei_r;
/////////////秒个位时间信息	序号2~5 miao_gewei_r
always@(posedge clk_125Mhz or negedge rst_n)
begin
    if(!rst_n)
        miao_gewei_r <= 4'd0;
    else    if(fall_4 && 8'd2 <= cnt_mem && cnt_mem <= 8'd5)
        miao_gewei_r <= {now_type[0],miao_gewei_r[3:1]};
    else
        miao_gewei_r <= miao_gewei_r;
end
/////////////秒十位时间信息	序号7~9 miao_shiwei_r
always@(posedge clk_125Mhz or negedge rst_n)
begin
    if(!rst_n)
        miao_shiwei_r <= 3'd0;
    else    if(fall_4 && 8'd7 <= cnt_mem && cnt_mem <= 8'd9)
        miao_shiwei_r <= {now_type[0],miao_shiwei_r[2:1]};
    else
        miao_shiwei_r <= miao_shiwei_r;
end
/////////////分个位时间信息 	序号11~14 fen_gewei_r
always@(posedge clk_125Mhz or negedge rst_n)
begin
    if(!rst_n)
        fen_gewei_r <= 4'd0;
    else    if(fall_4 && 8'd11 <= cnt_mem && cnt_mem <= 8'd14)
        fen_gewei_r <= {now_type[0],fen_gewei_r[3:1]};
    else
        fen_gewei_r <= fen_gewei_r;
end
/////////////分十位时间信息	序号16~18 fen_shiwei_r
always@(posedge clk_125Mhz or negedge rst_n)
begin
    if(!rst_n)
        fen_shiwei_r <= 3'd0;
    else    if(fall_4 && 8'd16 <= cnt_mem && cnt_mem <= 8'd18)
        fen_shiwei_r <= {now_type[0],fen_shiwei_r[2:1]};
    else
        fen_shiwei_r <= fen_shiwei_r;
end
/////////////时个位时间信息 	序号21~24 shi_gewei_r
always@(posedge clk_125Mhz or negedge rst_n)
begin
    if(!rst_n)
        shi_gewei_r <= 4'd0;
    else    if(fall_4 && 8'd21 <= cnt_mem && cnt_mem <= 8'd24)
        shi_gewei_r <= {now_type[0],shi_gewei_r[3:1]};
    else
        shi_gewei_r <= shi_gewei_r;
end
/////////////时十位时间信息 	序号26~27 shi_shiwei_r
always@(posedge clk_125Mhz or negedge rst_n)
begin
    if(!rst_n)
        shi_shiwei_r <= 2'd0;
    else    if(fall_4 && 8'd26 <= cnt_mem && cnt_mem <= 8'd27)
        shi_shiwei_r <= {now_type[0],shi_shiwei_r[1]};
    else
        shi_shiwei_r <= shi_shiwei_r;
end
/////////////日个位时间信息 	序号31~34 day_gewei_r
always@(posedge clk_125Mhz or negedge rst_n)
begin
    if(!rst_n)
        day_gewei_r <= 4'd0;
    else    if(fall_4 && 8'd31 <= cnt_mem && cnt_mem <= 8'd34)
        day_gewei_r <= {now_type[0],day_gewei_r[3:1]};
    else
        day_gewei_r <= day_gewei_r;
end
/////////////日十位时间信息 	序号36~39 day_shiwei_r
always@(posedge clk_125Mhz or negedge rst_n)
begin
    if(!rst_n)
        day_shiwei_r <= 4'd0;
    else    if(fall_4 && 8'd36 <= cnt_mem && cnt_mem <= 8'd39)
        day_shiwei_r <= {now_type[0],day_shiwei_r[3:1]};
    else
        day_shiwei_r <= day_shiwei_r;
end
/////////////日百位时间信息 	序号41~42 day_baiwei_r
always@(posedge clk_125Mhz or negedge rst_n)
begin
    if(!rst_n)
        day_baiwei_r <= 2'd0;
    else    if(fall_4 && 8'd41 <= cnt_mem && cnt_mem <= 8'd42)
        day_baiwei_r <= {now_type[0],day_baiwei_r[1]};
    else
        day_baiwei_r <= day_baiwei_r;
end
/////////////年个位时间信息 	序号51~54 year_gewei_r
always@(posedge clk_125Mhz or negedge rst_n)
begin
    if(!rst_n)
        year_gewei_r <= 4'd0;
    else    if(fall_4 && 8'd51 <= cnt_mem && cnt_mem <= 8'd54)
        year_gewei_r <= {now_type[0],year_gewei_r[3:1]};
    else
        year_gewei_r <= year_gewei_r;
end
/////////////年十位时间信息 	序号56~59 year_shiwei_r
always@(posedge clk_125Mhz or negedge rst_n)
begin
    if(!rst_n)
        year_shiwei_r <= 4'd0;
    else    if(fall_4 && 8'd56 <= cnt_mem && cnt_mem <= 8'd59)
        year_shiwei_r <= {now_type[0],year_shiwei_r[3:1]};
    else
        year_shiwei_r <= year_shiwei_r;
end
/////////////////////////////////////////////////////////////
// 统一输出
always@(posedge clk_125Mhz or negedge rst_n)
begin
    if(!rst_n)
        begin
            miao_gewei   <= 4'd0;
            miao_shiwei  <= 3'd0;
            fen_gewei    <= 4'd0;
            fen_shiwei   <= 3'd0;
            shi_gewei    <= 4'd0;
            shi_shiwei   <= 2'd0;
            day_gewei    <= 4'd0;
            day_shiwei   <= 4'd0;
            day_baiwei   <= 2'd0;
            year_gewei   <= 4'd0;
            year_shiwei  <= 4'd0;
        end
    else if(fall_5 && cnt_mem == 8'd60)
        begin
            miao_gewei   <= miao_gewei_r ;
            miao_shiwei  <= miao_shiwei_r;
            fen_gewei    <= fen_gewei_r  ;
            fen_shiwei   <= fen_shiwei_r ;
            shi_gewei    <= shi_gewei_r  ;
            shi_shiwei   <= shi_shiwei_r ;
            day_gewei    <= day_gewei_r  ;
            day_shiwei   <= day_shiwei_r ;
            day_baiwei   <= day_baiwei_r ;
            year_gewei   <= year_gewei_r ;
            year_shiwei  <= year_shiwei_r;
        end
    else
        begin
            miao_gewei   <= miao_gewei   ;
            miao_shiwei  <= miao_shiwei  ;
            fen_gewei    <= fen_gewei    ;
            fen_shiwei   <= fen_shiwei   ;
            shi_gewei    <= shi_gewei    ;
            shi_shiwei   <= shi_shiwei   ;
            day_gewei    <= day_gewei    ;
            day_shiwei   <= day_shiwei   ;
            day_baiwei   <= day_baiwei   ;
            year_gewei   <= year_gewei   ;
            year_shiwei  <= year_shiwei  ;
        end
end
endmodule

fsm

复制代码
module  fsm
#(
    parameter   TIME_1S  = 32'd50_000_000
)
(
    input   wire        clk         ,
    input   wire        rst_n       ,
    input   wire        send_done   ,//控制串口发送信号线
    input   wire [3:0]  miao_gewei  ,
    input   wire [2:0]  miao_shiwei ,

    input   wire [3:0]  fen_gewei   ,
    input   wire [2:0]  fen_shiwei  ,

    input   wire [3:0]  shi_gewei   ,
    input   wire [1:0]  shi_shiwei  ,

    input   wire [3:0]  day_gewei   ,
    input   wire [3:0]  day_shiwei  ,
    input   wire [1:0]  day_baiwei  ,

    input   wire [3:0]  year_gewei  ,
    input   wire [3:0]  year_shiwei ,
    
    output  reg         pi_flag     ,
    output  reg  [7:0]  pi_data
);

//parameter   TIME_1S  = 32'd50_000;//用于仿真测试,缩短仿真时间
parameter   BYTE_NUM = 32'd14         ;//发送的字节数

parameter   idle = 8'd0;
parameter   s0   = 8'd1;
parameter   s1   = 8'd2;
parameter   s2   = 8'd3;
parameter   s3   = 8'd4;

//定义一个数组,存放8个字节需要发送的数据
wire [7:0]	mem	[0:13];

assign	mem[0]	= 8'h55;//帧头
assign	mem[1]	= 8'h55;
assign	mem[2]	= 8'h55;
assign	mem[3]	= {4'd0,miao_gewei  [3:0]  };//秒个位,1个字节
assign	mem[4]	= {5'd0,miao_shiwei [2:0] };//秒十位,1个字节
assign	mem[5]	= {4'd0,fen_gewei   [3:0]};//分个位,1个字节
assign	mem[6]	= {5'd0,fen_shiwei  [2:0]};//分十位,1个字节
assign	mem[7]	= {4'd0,shi_gewei   [3:0]};//时个位,1个字节
assign	mem[8]	= {6'd0,shi_shiwei  [1:0]};//时十位,1个字节
assign	mem[9]	= {4'd0,day_gewei   [3:0]};//天个位,1个字节
assign	mem[10]	= {4'd0,day_shiwei  [3:0]};//天十位,1个字节
assign	mem[11]	= {6'd0,day_baiwei  [1:0]};//天百位,1个字节
assign	mem[12]	= {4'd0,year_gewei  [3:0]};//年个位,1个字节
assign	mem[13]	= {4'd0,year_shiwei [3:0]};//年十位,1个字节

reg [7:0]   state;

//内部变量的定义
reg [31:0]  delay_cnt;
reg [7:0]   send_done_cnt;
reg [7:0]   index;

always@(posedge clk or negedge rst_n)
begin
    if(!rst_n)
        begin
            delay_cnt       <= 32'd0;
            send_done_cnt   <=  8'd0;
            index           <=  8'd0;
            state           <=  idle;
            pi_flag         <=  1'b0;
            pi_data         <=  8'd0;
        end
    else
        begin
            case(state)
                idle:  
                    begin
                        if(delay_cnt == TIME_1S)
                            begin
                                delay_cnt       <= 32'd0;
                                send_done_cnt   <=  8'd0;
                                pi_flag         <=  1'b0;
                                pi_data         <=  8'd0;
                                index           <=  8'd0;
                                state           <=  s0  ;
                            end
                        else
                            begin
                                state       <= state;
                                delay_cnt   <= delay_cnt + 1'b1;
                            end
                    end
                s0  :
                    begin
                        pi_flag <= 1'b1;
                        pi_data <= mem[index];
                        state   <= s1;
                    end
                s1  :
                    begin
                        pi_flag <= 1'b0;
                        
                        if(send_done)
                            begin
                                state <= s2;
                                send_done_cnt <= send_done_cnt + 1'b1;
                                index <= index + 1'b1;
                            end
                        else
                            begin
                                state <= state;
                                send_done_cnt <= send_done_cnt;
                                index <= index;
                            end
                    end
                s2  :
                    begin
                        if(send_done_cnt == BYTE_NUM)
                            state <= s3;
                        else
                            state <= s0;
                    end
                s3  :
                    begin
                        delay_cnt       <= 32'd0;
                        send_done_cnt   <=  8'd0;
                        index           <=  8'd0;
                        state           <=  idle;
                        pi_flag         <=  1'b0;
                        pi_data         <=  8'd0;
                    end
                default:
                    begin
                        delay_cnt       <= 32'd0;
                        send_done_cnt   <=  8'd0;
                        index           <=  8'd0;
                        state           <=  idle;
                        pi_flag         <=  1'b0;
                        pi_data         <=  8'd0;
                    end
            endcase
        end
end
endmodule

uart_tx

复制代码
module  uart_tx
#(
    parameter   CLK_FREQ = 'd124_999_999 ,
    parameter   BPS      = 'd9600        
)
(
    input   wire        clk         ,
    input   wire        rst_n       ,
    input   wire        pi_flag     ,
    input   wire [7:0]  pi_data     ,
    
    output  reg         send_done   ,
    output  reg         tx
);

localparam  BAUD_TIME= CLK_FREQ / BPS ;

parameter   idle = 8'd0 ;
parameter   s0   = 8'd1 ;
parameter   s1   = 8'd2 ;
parameter   s2   = 8'd3 ;
parameter   s3   = 8'd4 ;
parameter   s4   = 8'd5 ;
parameter   s5   = 8'd6 ;
parameter   s6   = 8'd7 ;
parameter   s7   = 8'd8 ;
parameter   s8   = 8'd9 ;
parameter   s9   = 8'd10;
parameter   s10  = 8'd11;
parameter   done = 8'd12;

reg [7:0]   state       ;
reg [15:0]  delay_cnt   ;
reg [9:0]   send_data   ;

always@(posedge clk or negedge rst_n)
begin
    if(!rst_n)
        begin
            state     <= idle;
            delay_cnt <= 16'd0;
            send_done <= 1'b0;
            tx        <= 1'b1;
            send_data <= 10'd0;
        end
    else
        case(state)
            idle:
                begin
                    if(pi_flag)
                        state <= s0;
                    else      
                        state <= state;
                    
                    delay_cnt <= 16'd0;
                    tx        <= 1'b1;
                    send_done <= 1'b0;
                end
            s0  :
                begin
                    send_data <= {1'b1,pi_data[7:0],1'b0};
                    state <= s1;
                end
            s1  :
                begin
                    if(delay_cnt == BAUD_TIME - 1'b1)
                        begin
                            state     <= s2;
                            delay_cnt <= 16'd0;
                        end
                    else
                        begin
                            tx        <= send_data[0];
                            delay_cnt <= delay_cnt + 1'b1;
                        end
                end
            s2  :
                begin
                    if(delay_cnt == BAUD_TIME - 1'b1)
                        begin
                            state     <= s3;
                            delay_cnt <= 16'd0;
                        end
                    else
                        begin
                            tx        <= send_data[1];
                            delay_cnt <= delay_cnt + 1'b1;
                        end
                end
            s3  :
                begin
                    if(delay_cnt == BAUD_TIME - 1'b1)
                        begin
                            state     <= s4;
                            delay_cnt <= 16'd0;
                        end
                    else
                        begin
                            tx        <= send_data[2];
                            delay_cnt <= delay_cnt + 1'b1;
                        end
                end
            s4  :
                begin
                    if(delay_cnt == BAUD_TIME - 1'b1)
                        begin
                            state     <= s5;
                            delay_cnt <= 16'd0;
                        end
                    else
                        begin
                            tx        <= send_data[3];
                            delay_cnt <= delay_cnt + 1'b1;
                        end
                end
            s5  :
                begin
                    if(delay_cnt == BAUD_TIME - 1'b1)
                        begin
                            state     <= s6;
                            delay_cnt <= 16'd0;
                        end
                    else
                        begin
                            tx        <= send_data[4];
                            delay_cnt <= delay_cnt + 1'b1;
                        end
                end
            s6  :
                begin
                    if(delay_cnt == BAUD_TIME - 1'b1)
                        begin
                            state     <= s7;
                            delay_cnt <= 16'd0;
                        end
                    else
                        begin
                            tx        <= send_data[5];
                            delay_cnt <= delay_cnt + 1'b1;
                        end
                end
            s7  :
                begin
                    if(delay_cnt == BAUD_TIME - 1'b1)
                        begin
                            state     <= s8;
                            delay_cnt <= 16'd0;
                        end
                    else
                        begin
                            tx        <= send_data[6];
                            delay_cnt <= delay_cnt + 1'b1;
                        end
                end
            s8  :
                begin
                    if(delay_cnt == BAUD_TIME - 1'b1)
                        begin
                            state     <= s9;
                            delay_cnt <= 16'd0;
                        end
                    else
                        begin
                            tx        <= send_data[7];
                            delay_cnt <= delay_cnt + 1'b1;
                        end
                end
            s9  :
                begin
                    if(delay_cnt == BAUD_TIME - 1'b1)
                        begin
                            state     <= s10;
                            delay_cnt <= 16'd0;
                        end
                    else
                        begin
                            tx        <= send_data[8];
                            delay_cnt <= delay_cnt + 1'b1;
                        end
                end
            s10 :
                begin
                    if(delay_cnt == BAUD_TIME - 1'b1)
                        begin
                            state     <= done;
                            delay_cnt <= 16'd0;
                        end
                    else
                        begin
                            tx        <= send_data[9];
                            delay_cnt <= delay_cnt + 1'b1;
                        end
                end
            done:
                begin
                    state <= idle;
                    send_done <= 1'b1;
                end
            default:
                begin
                    state     <= idle;
                    delay_cnt <= 16'd0;
                    send_done <= 1'b0;
                    tx        <= 1'b1;
                end
        endcase
end
endmodule

编写仿真代码

复制代码
`timescale  1ns/1ps
module  uart_send_IRIG_data_top_tb();

reg     clk     ;
reg     rst_n   ;

initial
begin
    clk   = 1'b0;
    rst_n = 1'b0;
    #123
    rst_n = 1'b1;
end

always #10 clk = ~clk;

defparam    uart_send_IRIG_data_top_inst.b_code_gen_inst.TIME_1S     = 32'd124_999;
defparam    uart_send_IRIG_data_top_inst.b_code_gen_inst.TIME_10MS   = 32'd1_249  ;
defparam    uart_send_IRIG_data_top_inst.b_code_gen_inst.TIME_8MS    = 32'd999    ;
defparam    uart_send_IRIG_data_top_inst.b_code_gen_inst.TIME_5MS    = 32'd624    ;
defparam    uart_send_IRIG_data_top_inst.b_code_gen_inst.TIME_2MS    = 32'd249    ;

defparam    uart_send_IRIG_data_top_inst.b_code_inst.TIME_10MS = 32'd1_249;
defparam    uart_send_IRIG_data_top_inst.b_code_inst.TIME_8MS  = 32'd999  ;
defparam    uart_send_IRIG_data_top_inst.b_code_inst.TIME_2MS  = 32'd249  ;
defparam    uart_send_IRIG_data_top_inst.b_code_inst.TIME_5MS  = 32'd624  ;
defparam    uart_send_IRIG_data_top_inst.b_code_inst.WUCHA_8US = 32'd10   ;

defparam    uart_send_IRIG_data_top_inst.fsm_inst.TIME_1S     = 32'd124_999;

defparam    uart_send_IRIG_data_top_inst.uart_tx_inst.CLK_FREQ = 'd124_999_999;
defparam    uart_send_IRIG_data_top_inst.uart_tx_inst.BPS      = 'd9600       ;

uart_send_IRIG_data_top     uart_send_IRIG_data_top_inst(
    .clk   (clk   ),
    .rst_n (rst_n ),

    .tx    ()
);
endmodule

仿真验证

可以看出顶层没问题。

上板验证