用SV书写7位数据位,1位偶校验,115200bps的串行发送端
时间: 2024-05-25 19:18:07 浏览: 9
以下是用SystemVerilog实现7位数据位、1位偶校验、115200bps的串行发送端的代码:
module serial_tx
#(parameter BAUD_RATE = 115200,
DATA_WIDTH = 7)
(
input clk,
input rst,
input [DATA_WIDTH-1:0] data_in,
output reg tx_out
);
reg [7:0] shift_reg;
reg [DATA_WIDTH-1:0] data_reg;
reg [7:0] parity_reg;
reg start_bit;
reg [1:0] bit_count;
parameter DIVIDER = $floor((2e6)/BAUD_RATE); // 2 MHz clock
always @(posedge clk) begin
if (rst) begin
shift_reg <= 8'b11111110; // start bit and mark parity
data_reg <= {DATA_WIDTH{1'b0}};
parity_reg <= 8'b0;
start_bit <= 1'b0;
bit_count <= 2'b00; // start bit
tx_out <= 1'b1;
end else begin
if (tx_out == 1'b0) begin
bit_count <= bit_count + 1;
if (bit_count == 2) begin
start_bit <= 1'b1;
end else begin
start_bit <= 1'b0;
if (bit_count == DATA_WIDTH+2) begin
parity_reg <= {parity_reg[6:0], parity_reg[7]^data_reg[0]};
data_reg <= data_reg >> 1;
end else if (bit_count == 10) begin
shift_reg <= 8'b11111110; // start bit and mark parity
bit_count <= 2'b00; // start bit
tx_out <= 1'b1;
end else begin
shift_reg <= {shift_reg[6:0], start_bit ? 1'b0 : data_reg[DATA_WIDTH-1], parity_reg[7]};
end
end
end else begin
shift_reg <= shift_reg >> 1;
tx_out <= shift_reg[0];
if (tx_out == 1'b0) begin
data_reg <= data_in;
parity_reg <= data_in;
bit_count <= 2'b01; // start bit
end
end
end
end
always @(posedge clk) begin
if (rst) begin
tx_out <= 1'b1;
end else begin
if (tx_out == 1'b1) begin
if (shift_reg == 8'b00000001) begin // stop bit
tx_out <= 1'b1;
end else begin
tx_out <= 1'b0;
end
end
end
end
// clock divider to generate baud rate
reg [31:0] clk_cnt;
always @(posedge clk) begin
if (rst) begin
clk_cnt <= 32'b0;
end else begin
clk_cnt <= clk_cnt + 1;
if (clk_cnt == DIVIDER-1) begin
clk_cnt <= 32'b0;
end
end
end
endmodule
在此代码中,我们使用了一个8位移位寄存器(shift_reg)来存储即将发送的数据位。我们还使用了一个7位移位寄存器(parity_reg)来存储奇偶校验位。我们使用一个7位寄存器(data_reg)来存储即将发送的数据。我们使用一个布尔寄存器(start_bit)来存储起始位。我们使用一个2位寄存器(bit_count)来存储当前发送的位数。
在时钟上升沿时,我们首先检查重置信号(rst),如果为1,则将所有寄存器和寄存器变量重新初始化。否则,我们检查tx_out的状态。如果它是1,则我们将移位寄存器向右移动一位,并将tx_out设置为移位寄存器的最低位。如果tx_out是0,则我们正在发送数据。我们使用bit_count计算当前发送的位数,并根据位数将数据位、奇偶校验位和起始位写入移位寄存器。在发送完最后一位数据位后,我们将移位寄存器设置为停止位,并将tx_out设置为1。
为了生成正确的波特率,我们使用了一个32位计数器(clk_cnt),在时钟上升沿时计数器递增。当计数器达到DIVIDER-1时,我们将其重置为0。DIVIDER是一个参数,它是时钟频率(2 MHz)和波特率之间的比率。在本例中,我们设置DIVIDER为115,因此波特率为115200bps。