数字IC手撕代码-串转并、并转串

 前言:

        本专栏旨在记录高频笔面试手撕代码题,以备数字前端秋招,本专栏所有文章提供原理分析、代码及波形,所有代码均经过本人验证。

目录如下:

1.数字IC手撕代码-分频器(任意偶数分频)

2.数字IC手撕代码-分频器(任意奇数分频)

3.数字IC手撕代码-分频器(任意小数分频)

4.数字IC手撕代码-异步复位同步释放

5.数字IC手撕代码-边沿检测(上升沿、下降沿、双边沿)

6.数字IC手撕代码-序列检测(状态机写法)

7.数字IC手撕代码-序列检测(移位寄存器写法)

8.数字IC手撕代码-半加器、全加器

9.数字IC手撕代码-串转并、并转串

10.数字IC手撕代码-数据位宽转换器(宽-窄,窄-宽转换)

11.数字IC手撕代码-有限状态机FSM-饮料机

12.数字IC手撕代码-握手信号(READY-VALID)

13.数字IC手撕代码-流水握手(利用握手解决流水线断流、反压问题)

14.数字IC手撕代码-泰凌微笔试真题

15.数字IC手撕代码-平头哥技术终面手撕真题

16.数字IC手撕代码-兆易创新笔试真题

17.数字IC手撕代码-乐鑫科技笔试真题(4倍频)

18.数字IC手撕代码-双端口RAM(dual-port-RAM)

        ...持续更新

为了方便可以收藏导览博客: 数字IC手撕代码-导览目录


目录

串并转换

1.串转并

代码

testbench

波形

 并转串

代码

testbench

波形


串并转换

        串转并的使用环境非常多,在接口处用到最多,在某些模块的输入仅允许串行输入时,而总线上的数时并行的,那就需要通过串并转换,把并行的数据转换成串行的数据,包括在输出的时候,需要把串行的数据转换成并行的数据,才能送到总线中,使用方法都是用一个计数器来计数实现 。   

串转并

        用一个计数器count,每输入8个数,就输出一次,每周期dout_temp左移一位,然后再将输入的1bit串行据存入dout_temp的最低位。

代码

module serial_to_parallel(
    input               rstn          ,
    input               clk           ,
    input               din_serial    ,
    input               din_valid     ,
    output  reg  [7:0]  dout_parallel ,
    output  reg         dout_valid
);

reg [7:0] dout_temp;
reg [3:0] count;

always @(posedge clk)begin
    if(!rstn)begin
        dout_temp  <= 8'd0;
        count      <= 4'd0;
        dout_valid <= 1'b0;
    end
    else if(din_valid && count <= 4'd7)begin
        dout_temp <= {dout_temp[6:0],din_serial};
        count     <= count + 1'b1;
    end
    else begin
        dout_valid <= 1'b0;
        dout_temp  <= 8'd0;
        count      <= 4'd0;
    end
end

always @(posedge clk)begin
    if(count == 4'd8)begin
        count         <= 4'd0;
        dout_parallel <= dout_temp;
        dout_valid    <= 1'b1;
    end
end

endmodule

testbench

module serial_to_parallel_tb();
reg clk,rstn;
reg din_serial,din_valid;
wire dout_valid,dout_parallel;

always #5 clk = ~clk;

initial begin
    clk  <= 1'b0;
    rstn <= 1'b0;
    #15
    rstn <= 1'b1;
    din_valid  <= 1'b1;
    din_serial <= 1'b1; #10
    din_serial <= 1'b1; #10
    din_serial <= 1'b1; #10
    din_serial <= 1'b1; #10

    din_serial <= 1'b0; #10
    din_serial <= 1'b0; #10
    din_serial <= 1'b0; #10
    din_serial <= 1'b0; #10
    din_valid  <= 1'b0;
    #30

    din_valid  <= 1'b1;
    din_serial <= 1'b1; #10
    din_serial <= 1'b1; #10
    din_serial <= 1'b0; #10
    din_serial <= 1'b0; #10

    din_serial <= 1'b0; #10
    din_serial <= 1'b0; #10
    din_serial <= 1'b1; #10
    din_serial <= 1'b1; #10
    din_valid  <= 1'b0;
    $stop();
end 

serial_to_parallel u_serial_to_parallel(
    .clk           (clk)           ,
    .rstn          (rstn)          ,
    .din_serial    (din_serial)    ,
    .dout_parallel (dout_parallel) ,
    .din_valid     (din_valid)     ,
    .dout_valid    (dout_valid)
);  
endmodule

波形

 并转串

        并转串的原理和串转并差不多,都是用一个计数器来技术,根据串行和并行之间的关系来决定计数器计数的上下限。        

        在输入数据有效的时候din_valid为高时,把输入的数据寄存一下,寄存到din_parallel_temp中,然后再用一个计数器去检测输出,当计数器处在1~8的范围内时,让输出的串行数据等于输入的并行数据的最高位,然后每周期让并行数据左移一bit。这样,八周期后,就实现了并转串。

代码

module parallel_to_serial(
    input clk,
    input rstn,
    input [7:0] din_parallel,
    input din_valid,
    output reg dout_valid,
    output reg dout_serial
);

reg [3:0] count;
reg [7:0] din_parallel_temp;

always @(posedge clk)begin
    if(!rstn)begin
        dout_valid <= 1'b0;
        dout_serial <= 1'b0;
    end
    else if(din_valid && (count == 4'b0))begin
        din_parallel_temp <= din_parallel;
    end
    else if((count >= 4'd1) && (count <= 4'd8))begin
        dout_serial <= din_parallel_temp[7];
        din_parallel_temp <= din_parallel_temp << 1;
        dout_valid <= 1'b1;
    end    
    else begin
        dout_valid <= 1'b0;
        dout_serial <= 1'b0;
    end
end

always @(posedge clk)begin
    if(!rstn)begin
        count <= 4'd0;
    end        
    else if(din_valid)begin
        count <= count + 1'b1;
    end
    else begin
        count <= 4'b0;
    end
end

endmodule

testbench

module parallel_to_serial_tb();
reg clk, rstn;
reg [7:0] din_parallel;
reg din_valid;

wire dout_valid,dout_serial;

always #5 clk = ~clk;

initial begin
    clk <= 1'b0;
    rstn <= 1'b0;
    #15
    rstn <= 1'b1;   
    din_valid <= 1'b1;
    din_parallel <= 8'b11110000;
    #80
    din_valid <= 1'b0;
    #40
    din_valid <= 1'b1;
    din_parallel <= 8'b10100011;
    #80
    din_valid <= 1'b0;
    #50
    $stop();
end

parallel_to_serial u_parallel_to_serial(
    .clk           (clk)          ,    
    .rstn          (rstn)         ,    
    .din_parallel  (din_parallel) ,
    .din_valid     (din_valid)    ,
    .dout_serial   (dout_serial)  ,
    .dout_valid    (dout_valid)
);

endmodule

波形

        由此我们就实现了串并转换,其中valid信号表示有效信号,当输入有效的时候,输入的valid信号就拉高,输出有效的时候,输出valid就拉高,这有利于我们看波形,同时也有利于模块和外部通信。

猜你喜欢

转载自blog.csdn.net/qq_57502075/article/details/127093547#comments_27635556
今日推荐