IC笔试牛客网verilog刷题总结三

30.数据串转并电路

    reg [2:0]count;
    always@(posedge clk or negedge rst_n)begin
        if(~rst_n)begin
            count <= 3'd0;
            ready_a <= 1'b0;
        end
        else begin
            ready_a <= 1'b1;
            if(valid_a)begin
                if(count == 3'd5)begin
                    count <= 3'd0;
                end
                else count <= count + 3'd1;
            end
        end
    end
    reg [5:0] data_b_reg;
    always@(posedge clk or negedge rst_n)begin
        if(~rst_n)begin
            data_b <= 6'b0;
            valid_b <= 1'b0;
            data_b_reg <= 6'b0;
        end
        else begin
            if(valid_a)begin
                data_b_reg <= {data_a, data_b_reg[5:1]};//串并联转换
                if(count == 3'd5)begin
                    valid_b <= 1'b1;
                    data_b <= {data_a, data_b_reg[5:1]};
                end
                else begin
                    valid_b <= 1'b0;
                    data_b <= data_b;
                end
            end
        end
    end

32.非整数倍数据位宽转换24to128

  • 输入数据是24bit,输出数据是128bit。因为128×3=24×16,所以每输入16个有效数据,就可以产生三个完整的输出。因此设置一个仅在输入数据有效时工作的计数器cnt,计数范围是0-15。
  • 设置一个数据暂存器data_lock,每当输入有效时,将数据从低位移入。
  • 每当计数器cnt计数到5、10、15时,data_out要进行更新,并拉高valid_out一个周期。
reg[3:0] cnt;
    reg[127:0] data_lock;
    always@(posedge clk or negedge rst_n)begin
        if(!rst_n)
            cnt <= 0;
        else
            cnt <= ~valid_in ? cnt : cnt+ 1;
    end
    always@(posedge clk or negedge rst_n)begin
        if(!rst_n)
            valid_out <= 1'b0;
        else
            valid_out <= (cnt ==5 || cnt == 10  || cnt ==15) && valid_in;
    end
    always@(posedge clk or negedge rst_n)begin
        if(!rst_n)
            data_lock <= 0;
        else
            data_lock <= valid_in ? {data_lock[103:0],data_in}:data_lock;
    end
    always@(posedge clk or negedge rst_n)begin
        if(!rst_n)
            data_out <= 0;
        else if(cnt == 5)
            data_out <= valid_in ? {data_lock[119:0],data_in[23:16]}:data_out;
        else if(cnt == 10)
            data_out <= valid_in ? {data_lock[111:0],data_in[23:8]}:data_out;
        else if(cnt == 15)
            data_out <= valid_in ? {data_lock[103:0],data_in[23:0]}:data_out;
        else
            data_out <= data_out;
    end

37.时钟分频(偶数)

 reg clk_out2_r,clk_out4_r,clk_out8_r;
    always@(posedge clk_in or negedge rst)begin
        if(!rst)
            clk_out2_r <=0;
        else
            clk_out2_r <= ~clk_out2_r;
    end
    always@(posedge clk_out2_r or negedge rst)begin
        if(!rst)
            clk_out4_r <=0;
        else
            clk_out4_r <= ~clk_out4_r;
    end
    always@(posedge clk_out4_r or negedge rst)begin
        if(!rst)
            clk_out8_r <=0;
        else
            clk_out8_r <= ~clk_out8_r;
    end
    assign clk_out2 = clk_out2_r;
    assign clk_out4 = clk_out4_r;
    assign clk_out8 = clk_out8_r;

38.自动贩售机

   parameter S0 = 'd0, S1 = 'd1, S2 = 'd2, S3 = 'd3 , S4 = 'd4, S5 = 'd5 , S6 = 'd6;
    reg  [2:0]    current_state;
    reg  [2:0]    next_state;
    wire [2:0]   input_state;//将输入组合起来
    assign input_state = {d1,d2,d3};
     
    always@(posedge clk or negedge rst)begin
        if(rst == 1'b0)begin
            current_state <= S0;
        end
        else begin
            current_state <= next_state;
        end
    end   
     
    always@(*)begin
        case(current_state)
            S0:begin
                case(input_state)
                    3'b100:next_state = S1 ;
                    3'b010:next_state = S2 ;
                    3'b001:next_state = S4 ;
                    default:next_state = next_state;
                endcase
            end
            S1:begin
                case(input_state)
                    3'b100:next_state = S2 ;
                    3'b010:next_state = S3 ;
                    3'b001:next_state = S5 ;
                    default:next_state = next_state; 
                endcase
            end
            S2:begin
                case(input_state)
                    3'b100:next_state = S3 ;
                    3'b010:next_state = S4 ;
                    3'b001:next_state = S6 ;
                    default:next_state = next_state;
                endcase            
            end
             
            default:begin
                next_state = S0;
            end
        endcase
    end
     
    always@(posedge clk or negedge rst)begin
        if(rst == 1'b0)begin
            out1 <= 1'b0;
            out2 <= 2'b0;
        end
        else begin
            case(next_state)
                    S3:        begin out1 <= 1'b1;out2 <= 2'b0; end 
                    S4:        begin out1 <= 1'b1;out2 <= 2'b1; end 
                    S5:        begin out1 <= 1'b1;out2 <= 2'b10; end 
                    S6:        begin out1 <= 1'b1;out2 <= 2'b11; end 
                    default:   begin out1 <= 1'b0;out2 <= 2'b0; end 
            endcase
        end
    end

40.占空比50%的奇数分频

   奇数分频比偶数分频复杂一些,当不要求分频的占空比时,对输入时钟clk上升沿计数,可以设置两个计数的翻转点,一个是(N-1)/2,一个是(N-1),计数到(N-1)时输出时钟翻转且将计数器清零,假设计数器计数0~(N-1)/2区间输出低电平,则输出时钟的低电平有(N-1)/2 + 1个clk周期,高电平的计数是(N-1)/2+1 ~ (N-1),共(N-1)/2个clk周期,可见不是50%占空比。

    当要求占空比为50%时,对输入时钟clk的上升沿和下降沿分别计数,根据两个计数器得到两个错位输出的时钟,将两个时钟做“或”运算,可以弥补相差的时钟,达到50%占空比。

 reg clk_neg,clk_pos;
    reg [2:0] cnt;
    always@(posedge clk_in or negedge rst)begin
        if(!rst)
            cnt <= 0;
        else
            cnt <= cnt ==6 ? 0 :cnt + 1;
    end
    always@(posedge clk_in or negedge rst)begin
        if(!rst)
            clk_pos <= 0;
        else
            clk_pos <= cnt ==3 || cnt ==6 ? ~clk_pos : clk_pos;
    end
    always@(negedge clk_in or negedge rst)begin
       if(!rst)
            clk_neg <= 0;
        else
            clk_neg <= cnt ==3 || cnt ==6 ? ~clk_neg : clk_neg;
    end   
    assign clk_out7 = clk_neg | clk_pos;

41.小数分频

假设输出clk_out是输入clk_in的N分频。首先要将分频系数N化为分数形式,比如4.75—>19/4。本题中8.7 —>87/10,这意味着在87个clk_in周期内输出10个clk_out周期就可以实现分频。

然后采用若干种(一般是两种)整数分频在87个原周期clk_in内产生10个新时钟周期clk_out。整数分频的分频系数有很多种选择,但要尽可能接近,提高clk_out的均匀度。一般推荐在小数分频系数N的附近选取。因为8<N<9,所以两个整数分频系数是8和9。接着要计算87个clk_out周期分别有多少个是8分频和9分频的。

\left \{ x+y=10\right \}8x+9y =87  可得x=3x=3x=3,y=7y=7y=7。也就是3个8分频和7个9分频一组,循环输出,就等效于8.7分频。 最后安排组内8分频和9分频的位置。

reg [3:0] clk_cnt;//用于产生分频输出。当div_flag==0时,计数最大值是div_e-1;当div_flag==1时,计数最大值是div_o-1
    reg [6:0] cyc_cnt;//对clk_in进行计数,达到M_N后清零
    reg div_flag;//8/9分频标志。当div_flag==0时是8分频;当div_flag==1时是9分频。cyc_cnt==M_N-1或者cyc_cnt==c89-1时该标志位翻转
    reg clk_out_r;
     
    always@(posedge clk_in or negedge rst) begin
        if(~rst)
            clk_cnt <= 0;
        else if(~div_flag)
            clk_cnt <= clk_cnt==(div_e-1)? 0: clk_cnt+1;
        else
            clk_cnt <= clk_cnt==(div_o-1)? 0: clk_cnt+1;
    end
     
    always@(posedge clk_in or negedge rst) begin
        if(~rst)
            cyc_cnt <= 0;
        else
            cyc_cnt <= cyc_cnt==(M_N-1)? 0: cyc_cnt+1;
    end
     
    always@(posedge clk_in or negedge rst) begin
        if(~rst)
            div_flag <= 0;
        else
            div_flag <= cyc_cnt==(M_N-1)||cyc_cnt==(c89-1)? ~div_flag: div_flag;
    end
     
    always@(posedge clk_in or negedge rst) begin
        if(~rst)
            clk_out_r <= 0;
        else if(~div_flag)
            clk_out_r <= clk_cnt<=((div_e>>2)+1);
        else
            clk_out_r <= clk_cnt<=((div_o>>2)+1);
    end
     
    assign clk_out = clk_out_r;

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值