跳转至

并行数据转为串行数据

  • [ ] 对程序仿真,添加仿真时序图便于理解

应用场景

1. 并行数据转换为串行数据

应用场景

  • 串行通信
  • SPI(Serial Peripheral Interface):在SPI通信中,主机(Master)需要将并行数据转换为串行数据发送给从机(Slave)。移位寄存器可以将并行数据逐位移出,形成串行数据流。
  • UART(Universal Asynchronous Receiver-Transmitter):在UART通信中,数据通常以并行形式存储在寄存器中,然后通过移位寄存器转换为串行数据发送。
  • 数据压缩
  • 在某些数据压缩算法中,需要将并行数据逐位处理。移位寄存器可以将并行数据逐位移出,便于逐位处理。
  • 显示驱动
  • 在某些显示驱动电路中,需要将并行数据逐位发送到显示面板。移位寄存器可以实现这种转换。

2. 串行数据转换为并行数据

应用场景

  • 串行通信
  • SPI:从机(Slave)接收到的串行数据需要转换为并行数据以便进一步处理。移位寄存器可以将串行数据逐位存储,最终形成并行数据。
  • UART:接收端需要将接收到的串行数据转换为并行数据,以便存储到寄存器中。
  • 数据采集
  • 在某些数据采集系统中,传感器输出的串行数据需要转换为并行数据以便进行快速处理。
  • FPGA/CPLD
  • 在FPGA或CPLD中,串行数据输入通常需要转换为并行数据以便进行复杂的逻辑处理。

3. 单向移位寄存器

应用场景

  • 数据延迟
  • 在某些时序控制电路中,需要对数据进行逐位延迟。单向移位寄存器可以实现这种延迟功能。
  • 计数器
  • 通过环形移位寄存器(将输出反馈到输入)可以实现简单的计数器。
  • 序列发生器
  • 用于生成特定的序列信号,常用于测试和控制电路。

4. 双向移位寄存器

应用场景

  • 数据缓冲
  • 在某些数据缓冲电路中,需要根据不同的操作需求将数据向左移或向右移。双向移位寄存器可以灵活地实现这种功能。
  • 数字信号处理
  • 在某些数字信号处理算法中,需要根据不同的处理步骤将数据向左移或向右移。双向移位寄存器可以实现这种灵活的数据处理。
  • 通信协议
  • 在某些通信协议中,需要根据不同的通信阶段将数据向左移或向右移。双向移位寄存器可以实现这种灵活的数据处理。

参考资料

串并转换(串入并出、并入串出、移位寄存器法和计数器法

8位宽的并行输入数据转换为串行数据输出

需要添加额外start信号,当拉高start信号时,开始转换数据

在Verilog中,实现一个8位宽的并行输入数据转换为串行数据输出的过程通常称为串行化(Serialization)。以下是一个简单的Verilog模块示例,它实现了这个功能:

```verilog main.v module ParallelToSerial( input wire clk, // 时钟信号 input wire rst_n, // 复位信号(低电平有效) input wire [7:0] data_in, // 8位并行数据输入 input wire start, // 开始转换信号 output reg serial_out // 串行数据输出 );

reg [7:0] shift_reg; // 移位寄存器,用于存储并行数据 reg [2:0] bit_cnt; // 位计数器,用于跟踪当前输出的位

// 在每个时钟上升沿处理数据 always @(posedge clk or negedge rst_n) begin if (!rst_n) begin // 同步复位 shift_reg <= 8'b0; bit_cnt <= 3'b0; serial_out <= 1'b0; end else if (start) begin // 将并行数据加载到移位寄存器 shift_reg <= data_in; bit_cnt <= 3'd7; // 初始化位计数器为7(从最高位开始) end else if (bit_cnt > 0) begin // 移位输出并行数据到串行输出 serial_out <= shift_reg[7]; // 输出最高位 shift_reg <= shift_reg << 1; // 左移移位寄存器 bit_cnt <= bit_cnt - 1; // 减少位计数器 end end

endmodule


这个模块的工作流程如下:

1. **输入信号**:模块接受一个时钟信号`clk`,一个低电平有效的复位信号`rst_n`,8位并行数据输入`data_in`,以及一个开始转换信号`start`。
2. **寄存器定义**:定义了一个8位的移位寄存器`shift_reg`来存储并行数据,以及一个3位的位计数器`bit_cnt`来跟踪当前输出的位。
3. **处理逻辑**:
   - 当复位信号`rst_n`为低电平时,所有寄存器被清零。
   - 当`start`信号变为高电平时,将并行数据加载到移位寄存器`shift_reg`中,并设置位计数器`bit_cnt`为7,表示从最高位开始输出。
   - 在每个时钟周期,如果位计数器`bit_cnt`大于0,模块将移位寄存器的最高位输出到`serial_out`,然后将移位寄存器左移一位,并减少位计数器的值。
4. **输出**:`serial_out`为串行数据输出,它将按照位的顺序依次输出`data_in`中的每一位。

请注意,这个模块假设`start`信号会在每次需要开始新的串行转换时被激活,并且在转换过程中保持激活状态。此外,这个模块没有实现数据同步或时钟域交叉,这在实际应用中可能需要额外的考虑。



## 串行数据输入转换为8位宽并行数据输出

```verilog main.v
module SerialToParallel(
    input wire clk,          // 时钟信号
    input wire rst_n,        // 复位信号(低电平有效)
    input wire serial_in,    // 串行数据输入
    output reg [7:0] data_out, // 8位并行数据输出
    output reg done          // 转换完成信号
);

reg [7:0] shift_reg; // 移位寄存器,用于存储串行数据
reg [2:0] bit_cnt;   // 位计数器,用于跟踪当前存储的位数

// 在每个时钟上升沿处理数据
always @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
        // 同步复位
        shift_reg <= 8'b0;
        bit_cnt <= 3'b0;
        done <= 1'b0;
    end else begin
        // 移位输入串行数据到移位寄存器
        shift_reg <= {shift_reg[6:0], serial_in}; // 右移移位寄存器,并添加新的串行输入位
        if (bit_cnt < 7) begin
            bit_cnt <= bit_cnt + 1; // 增加位计数器
        end else begin
            // 当接收到8位数据后,将移位寄存器的内容输出到并行数据输出
            data_out <= shift_reg;
            done <= 1'b1; // 标记转换完成
            bit_cnt <= 3'b0; // 重置位计数器
        end
    end
end

endmodule

单向移位寄存器(左移)

module unidirectional_shift_register (
    input clk,          // 时钟信号
    input reset,        // 复位信号
    input serial_in,    // 串行输入数据
    output reg [7:0] serial_out  // 8位串行输出数据
);
    reg [7:0] shift_reg;  // 8位移位寄存器

    always @(posedge clk or posedge reset) begin
        if (reset) begin
            shift_reg <= 8'b0;  // 复位时清空移位寄存器
            serial_out <= 8'b0;  // 清空输出
        end else begin
            shift_reg <= shift_reg << 1;  // 左移操作
            shift_reg[0] <= serial_in;  // 将输入数据存储到最低位
            serial_out <= shift_reg;  // 更新输出
        end
    end
endmodule

双向移位寄存器

双向移位寄存器可以向两个方向移动数据(左移和右移),通过一个控制信号决定移位方向。

module bidirectional_shift_register (
    input clk,          // 时钟信号
    input reset,        // 复位信号
    input serial_in,    // 串行输入数据
    input shift_dir,    // 移位方向控制信号(0:左移,1:右移)
    output reg [7:0] serial_out  // 8位串行输出数据
);
    reg [7:0] shift_reg;  // 8位移位寄存器

    always @(posedge clk or posedge reset) begin
        if (reset) begin
            shift_reg <= 8'b0;  // 复位时清空移位寄存器
            serial_out <= 8'b0;  // 清空输出
        end else begin
            if (shift_dir) begin
                // 右移
                shift_reg <= shift_reg >> 1;
                shift_reg[7] <= serial_in;  // 将输入数据存储到最高位
            end else begin
                // 左移
                shift_reg <= shift_reg << 1;
                shift_reg[0] <= serial_in;  // 将输入数据存储到最低位
            end
            serial_out <= shift_reg;  // 更新输出
        end
    end
endmodule