芯路恒电子技术论坛

 找回密码
 立即注册
热搜: 合集
查看: 4211|回复: 3

小梅哥开发视频的布置作业,用串口控制设计一个24进制时钟

[复制链接]
  • TA的每日心情
    大哭
    2021-12-19 21:03
  • 1

    主题

    1

    帖子

    28

    积分

    新手上路

    Rank: 2

    积分
    28
    发表于 2021-12-5 13:09:12 | 显示全部楼层 |阅读模式

    本帖最后由 52Hertz 于 2021-12-5 13:16 编辑

    刚看完小梅哥的视频,花了几个钟头写成了作业,就两个功能,24小时计时和用串口设置时间。默认波特率为115200,上电开始从00:00:00计时,开发板是720,漏洞坑定有,还请各位指正。

    这是最顶层文件

    
    module digital_clock(
        clk,
        reset_n,
        sh_cp,
        st_cp,
        rx,
        ds
        );
        input clk;
        input reset_n;
        input rx;
        output sh_cp;
        output st_cp;
        output ds;
        reg [31:0] disp_data;
        reg [25:0] counter;
        parameter second_cnt = 26'h2FAF080;
        smg_top smg_top_demo(
        .clk(clk),
        .reset_n(reset_n),
        .sh_cp(sh_cp),
        .st_cp(st_cp),
        .ds(ds),
        .disp_data(disp_data)
        );
        wire [7:0] data;
        wire rx_done;
        uart_byte_rx uart_byte_rx_demo(
        .clk(clk),
        .reset_n(reset_n),
        .baud_set(3'd4),
        .uart_rx(rx),
        .data_byte(data),
        .rx_done(rx_done)
    );
        reg [1:0] set_done;
        reg [7:0]second;
        reg [7:0]minute;
        reg [7:0]hour;
        always@(posedge clk or negedge reset_n)begin
            if(!reset_n)
                set_done <= 0;
            else if(set_done == 2'd3)
                    set_done <= 1'd0;
            else if(rx_done)
                    set_done <= set_done + 1'd1;
        end
        always@(posedge clk or negedge reset_n)begin
            if(!reset_n)
                counter <= 0;
            else if(counter == second_cnt - 1'b1)
                counter <= 0;
            else
                counter <= counter + 1'b1;  
    
        end
        reg clk_second;
        always@(posedge clk or negedge reset_n)begin//产生秒脉冲
            if(!reset_n)
                clk_second <= 1'b0;
            else if(counter == second_cnt - 1'b1)
                clk_second <= 1'b1;
            else
                clk_second <= 1'b0;
        end
    
        always@(posedge clk or negedge reset_n)begin
            if(!reset_n)
                second <= 8'd0;
            else if((rx_done )&&(set_done == 2'd2))
                second <= data;
            else if(clk_second)begin
                if((second[7:4] == 4'd5)&&(second[3:0] == 4'd9))begin
                    second <=8'd0;
                end
                else if(second[3:0] == 4'd9)begin
                    second[7:4] <= second[7:4] + 1;
                    second[3:0] <= 4'd0;
                end
                else
                    second[3:0] <= second[3:0] + 1'b1;
            end
    
        end
    
         always@(posedge clk or negedge reset_n)begin
            if(!reset_n)
               minute <= 8'd0;
             else if((rx_done )&&(set_done == 2'd1))
                minute <= data;
            else if(clk_second)begin
                if((second[7:4] == 4'd5)&&(second[3:0] == 4'd9))begin
                    if((minute[7:4]== 4'd5)&&(minute[3:0]== 4'd9))
                    minute <= 8'd0;
                     else if(minute[3:0] == 4'd9)begin
                    minute[7:4] <= minute[7:4] + 1'b1;
                    minute[3:0] <= 4'd0;
                      end   
                    else
                    minute[3:0] <= minute[3:0] + 1'b1;
            end
            end
    
        end
    
        always@(posedge clk or negedge reset_n)begin
            if(!reset_n)
               hour <= 8'd0;
             else if((rx_done )&&(set_done == 2'd0))
                hour <= data;
              else if(clk_second)begin
                 if((second[7:4] == 4'd5)&&(second[3:0] == 4'd9)&&(minute[7:4] == 4'd5)&&(minute[3:0] == 4'd9))begin
                    if((hour[7:4]==4'd2)&&(hour[3:0] == 4'd3))
                    hour <= 8'd0;
                 else if(hour[3:0] == 4'd9)begin
                    hour[3:0] <= 4'd0;
                    hour[7:4] <= hour[7:4] + 1'b1;
                   end
                else
                    hour[3:0] <= hour[3:0] + 1'b1;
            end
           end
         end
         always@(posedge clk or negedge reset_n)begin
            if(!reset_n)
                disp_data <= 32'd0;
            else if(clk_second)
                disp_data <= {second[3:0],second[7:4],minute[3:0],minute[7:4],hour[3:0],hour[7:4],8'd0};
         end
    endmodule
    

    这是smg_top模块

    
    module smg_top(
        clk,
        reset_n,
        sh_cp,
        st_cp,
        ds,
        disp_data
        );
        input clk;
        input reset_n;
        input [31:0]disp_data;
        output sh_cp;
        output st_cp;
        output ds;
        wire[7:0] sel;
        wire[7:0] seg;
        wire [15:0] data;
        assign data = {seg,sel};
        smg_dispaly smg_display_demo(
        .clk(clk),
        .reset_n(reset_n),
        .disp_data(disp_data),
        .sel(sel),
        .seg(seg)
        );
    
        smg_hc595 smg_hc595_demo(
        .clk(clk),
        .reset_n(reset_n),
        .data(data),
        .sh_cp(sh_cp),
        .st_cp(st_cp),
        .en(1'b1),
        .ds(ds)
        );
    endmodule
    

    这是smg译码和hc595驱动模块,都被例化在smg_top文件中

    
    module smg_dispaly(
        clk,
        reset_n,
        disp_data,
        sel,
        seg
        );
        input clk;
        input reset_n;
        input [31:0] disp_data;//要现实的数据一共对应八位数码管的八位
        output reg [7:0] sel;//位选输出
        output reg [7:0] seg;//译码输出 a-h : seg[0]-seg[7]
    
        reg clk_div;
        reg [14:0]div_cnt;
        reg [2:0]num_cnt;
        always@(posedge clk or negedge reset_n)begin
            if(!reset_n)
                div_cnt <= 15'd0;
            else if(div_cnt == 24999)
                div_cnt <= 15'd0;
            else
                div_cnt <= div_cnt + 1'd1;
    
        end
    
        always@(posedge clk or negedge reset_n)begin
            if(!reset_n)
                clk_div <= 1;
            else if(div_cnt == 24999)
                clk_div <= 1'b1;
            else 
                clk_div <= 0;
        end
    
        always@(posedge clk or negedge reset_n)begin
            if(!reset_n)
                num_cnt <= 0;
            else if(clk_div)
                num_cnt <= num_cnt + 1;
        end
    
        always@(*)begin
            case(num_cnt)
                0: sel <= 8'b00000001;
                1: sel <= 8'b00000010;
                2: sel <= 8'b00000100;
                3: sel <= 8'b00001000;
                4: sel <= 8'b00010000;
                5: sel <= 8'b00100000;
                6: sel <= 8'b01000000;
                7: sel <= 8'b10000000;
            endcase
        end
    
        reg [3:0]disp_temp;
        always@(*)begin
            case(num_cnt)
                0: disp_temp <= disp_data[31:28];
                1: disp_temp <= disp_data[27:24];
                2: disp_temp <= disp_data[23:20];
                3: disp_temp <= disp_data[19:16];
                4: disp_temp <= disp_data[15:12];
                5: disp_temp <= disp_data[11:8];
                6: disp_temp <= disp_data[7:4];
                7: disp_temp <= disp_data[3:0];
            endcase
        end
    
        always@(*)begin
            case(disp_temp)
                4'h0:   seg = 8'hc0;
                4'h1:   seg = 8'hf9;
                4'h2:   seg = 8'ha4;
                4'h3:   seg = 8'hb0;
                4'h4:   seg = 8'h99;
                4'h5:   seg = 8'h92;
                4'h6:   seg = 8'h82;
                4'h7:   seg = 8'hf8;
                4'h8:   seg = 8'h80;
                4'h9:   seg = 8'h90;
                4'ha: seg = 8'h88;
                4'hb: seg = 8'h83;
                4'hc: seg = 8'hc6;
                4'hd: seg = 8'ha1;
                4'he: seg =  8'h86;
                4'hf : seg =  8'h8e;
            endcase
        end
    endmodule
    
    
    module smg_hc595(
        clk,
        reset_n,
        data,
        sh_cp,
        st_cp,
        en,
        ds
        );
        input clk;
        input reset_n;
        input [15:0] data;
        input en;
        output reg sh_cp;
        output reg st_cp;
        output reg ds;
        reg [5:0] shcp_edge_cnt;
        reg [15:0] r_data;
        always@(posedge clk)begin
            if(en)
              r_data <= data;
        end
        reg[2:0] div_cnt;
        always@(posedge clk or negedge reset_n)begin
            if(!reset_n)
                div_cnt <= 0;
            else  if(div_cnt == 1'b1)
                div_cnt <= 0;
            else
                div_cnt <= div_cnt + 1'b1;
            end
        wire sck;
        assign sck = (div_cnt == 1'b1);
    
    
        always@(posedge clk or negedge reset_n)begin
            if(!reset_n)
            shcp_edge_cnt <= 0;
            else if(sck)begin
                if(shcp_edge_cnt == 6'd32)
                    shcp_edge_cnt <= 0;
                else 
                    shcp_edge_cnt <= shcp_edge_cnt + 1'b1;
            end
            else
            shcp_edge_cnt <= shcp_edge_cnt;
        end
    
        always@(posedge clk or negedge reset_n)begin
            if(!reset_n)begin
                sh_cp <= 1'b0;
                st_cp <= 1'b0;
                ds <= 1'b0;
            end
            else begin
                case(shcp_edge_cnt)
                    0:begin sh_cp <= 1'd0; ds <= r_data[15];end
                    1:begin sh_cp <= 1'd1;st_cp <= 1'd0;end
                    2:begin sh_cp <= 1'd0; st_cp <= 1'd0;ds <= r_data[14];end
                    3:sh_cp <= 1'd1;
                    4:begin sh_cp <= 1'd0; st_cp <= 1'd0;ds <= r_data[13];end
                    5:sh_cp <= 1'd1;
                    6:begin sh_cp <= 1'd0; st_cp <= 1'd0;ds <= r_data[12];end
                    7:sh_cp <= 1'd1;
                    8:begin sh_cp <= 1'd0; st_cp <= 1'd0;ds <= r_data[11];end
                    9:sh_cp <= 1'd1;
                    10:begin sh_cp <= 1'd0; st_cp <= 1'd0;ds <= r_data[10];end
                    11:sh_cp <= 1'd1;
                    12:begin sh_cp <= 1'd0; st_cp <= 1'd0;ds <= r_data[9];end
                    13:sh_cp <= 1'd1;
                    14:begin sh_cp <= 1'd0; st_cp <= 1'd0;ds <= r_data[8];end
                    15:sh_cp <= 1'd1;
                    16:begin sh_cp <= 1'd0; st_cp <= 1'd0;ds <= r_data[7];end
                    17:sh_cp <= 1'd1;
                    18:begin sh_cp <= 1'd0; st_cp <= 1'd0;ds <= r_data[6];end
                    19:sh_cp <= 1'd1;
                    20:begin sh_cp <= 1'd0; st_cp <= 1'd0;ds <= r_data[5];end
                    21:sh_cp <= 1'd1;
                    22:begin sh_cp <= 1'd0; st_cp <= 1'd0;ds <= r_data[4];end
                    23:sh_cp <= 1'd1;
                    24:begin sh_cp <= 1'd0; st_cp <= 1'd0;ds <= r_data[3];end
                    25:sh_cp <= 1'd1;
                    26:begin sh_cp <= 1'd0; st_cp <= 1'd0;ds <= r_data[2];end
                    27:sh_cp <= 1'd1;
                    28:begin sh_cp <= 1'd0; st_cp <= 1'd0;ds <= r_data[1];end
                    29:sh_cp <= 1'd1;
                    30:begin sh_cp <= 1'd0; st_cp <= 1'd0;ds <= r_data[0];end
                    31:sh_cp <= 1'd1;
                    32:st_cp <= 1'd1;
                    default : begin sh_cp <= 1'b0;st_cp <= 1'b0;ds <= 1'b0;end
                endcase 
              end
            end
    endmodule
    

    最后的是串口接收模块,和smg_top一起被例化在digital_clock顶层文件中

    
    module uart_byte_rx(
        clk,
        reset_n,
    
        baud_set,
        uart_rx,
    
        data_byte,
        rx_done
    );
        assign reset=~reset_n;
    
        input clk;    //模块全局时钟输入,50M
        input reset_n;   //复位信号输入,低有效
    
        input [2:0]baud_set;  //波特率设置
        input uart_rx;   //串口输入信号
    
        output [7:0]data_byte; //串口接收的1byte数据
        output rx_done;   //1byte数据接收完成标志
    
        reg [7:0]data_byte;
        reg rx_done;
        reg uart_rx_sync1;   //同步寄存器
        reg uart_rx_sync2;   //同步寄存器
    
        reg uart_rx_reg1;    //数据寄存器
        reg uart_rx_reg2;    //数据寄存器
    
        reg [15:0]bps_DR;    //分频计数最大值
        reg [15:0]div_cnt;   //分频计数器
        reg bps_clk;   //波特率时钟
        reg [7:0] bps_cnt;   //波特率时钟计数器
        reg uart_state;//接收数据状态
    
        wire uart_rx_nedge;  
    
        reg [2:0]START_BIT;
        reg [2:0]STOP_BIT;
        reg [2:0]data_byte_pre [7:0];
    
        //同步串行输入信号,消除亚稳态
        always@(posedge clk or posedge reset)
        if(reset)begin
            uart_rx_sync1 <= 1'b0;
            uart_rx_sync2 <= 1'b0;
        end
        else begin
            uart_rx_sync1 <= uart_rx;
            uart_rx_sync2 <= uart_rx_sync1;
        end
    
        //数据寄存器
        always@(posedge clk or posedge reset)
        if(reset)begin
            uart_rx_reg1 <= 1'b0;
            uart_rx_reg2 <= 1'b0;
        end
        else begin
            uart_rx_reg1 <= uart_rx_sync2;
            uart_rx_reg2 <= uart_rx_reg1;
        end
    
      //下降沿检测
        assign uart_rx_nedge = !uart_rx_reg1 & uart_rx_reg2;
    
        always@(posedge clk or posedge reset)
        if(reset)
            bps_DR <= 16'd324;
        else begin
            case(baud_set)
                0:bps_DR <= 16'd324;
                1:bps_DR <= 16'd162;
                2:bps_DR <= 16'd80;
                3:bps_DR <= 16'd53;
                4:bps_DR <= 16'd26;
                default:bps_DR <= 16'd324;      
            endcase
        end
    
        //counter
        always@(posedge clk or posedge reset)
        if(reset)
            div_cnt <= 16'd0;
        else if(uart_state)begin
            if(div_cnt == bps_DR)
                div_cnt <= 16'd0;
            else
                div_cnt <= div_cnt + 1'b1;
        end
        else
            div_cnt <= 16'd0;
    
        // bps_clk gen
        always@(posedge clk or posedge reset)
        if(reset)
            bps_clk <= 1'b0;
        else if(div_cnt == 16'd1)
            bps_clk <= 1'b1;
        else
            bps_clk <= 1'b0;
    
        //bps counter
        always@(posedge clk or posedge reset)
        if(reset)
            bps_cnt <= 8'd0;
        else if(bps_cnt == 8'd159 | (bps_cnt == 8'd12 && (START_BIT > 2)))
            bps_cnt <= 8'd0;
        else if(bps_clk)
            bps_cnt <= bps_cnt + 1'b1;
        else
            bps_cnt <= bps_cnt;
    
        always@(posedge clk or posedge reset)
        if(reset)
            rx_done <= 1'b0;
        else if(bps_cnt == 8'd159)
            rx_done <= 1'b1;
        else
            rx_done <= 1'b0;    
    
        always@(posedge clk or posedge reset)
        if(reset)begin
            START_BIT <= 3'd0;
            data_byte_pre[0] <= 3'd0;
            data_byte_pre[1] <= 3'd0;
            data_byte_pre[2] <= 3'd0;
            data_byte_pre[3] <= 3'd0;
            data_byte_pre[4] <= 3'd0;
            data_byte_pre[5] <= 3'd0;
            data_byte_pre[6] <= 3'd0;
            data_byte_pre[7] <= 3'd0;
            STOP_BIT <= 3'd0;
        end
        else if(bps_clk)begin
            case(bps_cnt)
                0:begin
            START_BIT <= 3'd0;
            data_byte_pre[0] <= 3'd0;
            data_byte_pre[1] <= 3'd0;
            data_byte_pre[2] <= 3'd0;
            data_byte_pre[3] <= 3'd0;
            data_byte_pre[4] <= 3'd0;
            data_byte_pre[5] <= 3'd0;
            data_byte_pre[6] <= 3'd0;
            data_byte_pre[7] <= 3'd0;
            STOP_BIT <= 3'd0;       
          end
                6 ,7 ,8 ,9 ,10,11:START_BIT <= START_BIT + uart_rx_sync2;
                22,23,24,25,26,27:data_byte_pre[0] <= data_byte_pre[0] + uart_rx_sync2;
                38,39,40,41,42,43:data_byte_pre[1] <= data_byte_pre[1] + uart_rx_sync2;
                54,55,56,57,58,59:data_byte_pre[2] <= data_byte_pre[2] + uart_rx_sync2;
                70,71,72,73,74,75:data_byte_pre[3] <= data_byte_pre[3] + uart_rx_sync2;
                86,87,88,89,90,91:data_byte_pre[4] <= data_byte_pre[4] + uart_rx_sync2;
                102,103,104,105,106,107:data_byte_pre[5] <= data_byte_pre[5] + uart_rx_sync2;
                118,119,120,121,122,123:data_byte_pre[6] <= data_byte_pre[6] + uart_rx_sync2;
                134,135,136,137,138,139:data_byte_pre[7] <= data_byte_pre[7] + uart_rx_sync2;
                150,151,152,153,154,155:STOP_BIT <= STOP_BIT + uart_rx_sync2;
                default:
          begin
            START_BIT <= START_BIT;
            data_byte_pre[0] <= data_byte_pre[0];
            data_byte_pre[1] <= data_byte_pre[1];
            data_byte_pre[2] <= data_byte_pre[2];
            data_byte_pre[3] <= data_byte_pre[3];
            data_byte_pre[4] <= data_byte_pre[4];
            data_byte_pre[5] <= data_byte_pre[5];
            data_byte_pre[6] <= data_byte_pre[6];
            data_byte_pre[7] <= data_byte_pre[7];
            STOP_BIT <= STOP_BIT;
          end
            endcase
        end
    
        always@(posedge clk or posedge reset)
        if(reset)
            data_byte <= 8'd0;
        else if(bps_cnt == 8'd159)begin
            data_byte[0] <= data_byte_pre[0][2];
            data_byte[1] <= data_byte_pre[1][2];
            data_byte[2] <= data_byte_pre[2][2];
            data_byte[3] <= data_byte_pre[3][2];
            data_byte[4] <= data_byte_pre[4][2];
            data_byte[5] <= data_byte_pre[5][2];
            data_byte[6] <= data_byte_pre[6][2];
            data_byte[7] <= data_byte_pre[7][2];
        end
    
        always@(posedge clk or posedge reset)
        if(reset)
            uart_state <= 1'b0;
        else if(uart_rx_nedge)
            uart_state <= 1'b1;
        else if(rx_done || (bps_cnt == 8'd12 && (START_BIT > 2)) || (bps_cnt == 8'd155 && (STOP_BIT < 3)))
            uart_state <= 1'b0;
        else
            uart_state <= uart_state;   
    
    endmodule
    回复

    使用道具 举报

    该用户从未签到

    0

    主题

    1

    帖子

    33

    积分

    新手上路

    Rank: 2

    积分
    33
    发表于 2022-4-14 22:21:53 来自手机 | 显示全部楼层
    大佬 想问一下通过串口以一秒一次的速率发送到电脑实现了吗
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    开心
    2022-9-12 10:41
  • 0

    主题

    1

    帖子

    49

    积分

    新手上路

    Rank: 2

    积分
    49
    发表于 2022-8-17 18:15:17 | 显示全部楼层
    回复

    使用道具 举报

  • TA的每日心情
    萌哒
    2023-3-28 09:40
  • 0

    主题

    1

    帖子

    48

    积分

    新手上路

    Rank: 2

    积分
    48
    发表于 2022-9-8 16:51:08 | 显示全部楼层
    我仿真按1ms看的,没板子,不知道好不好使
    回复 支持 反对

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|小黑屋|Archiver|芯路恒电子技术论坛 |鄂ICP备2021003648号

    GMT+8, 2024-5-2 04:30 , Processed in 0.185203 second(s), 35 queries .

    Powered by Discuz! X3.4

    © 2001-2017 Comsenz Inc. Template By 【未来科技】【 www.wekei.cn 】

    快速回复 返回顶部 返回列表