用System Verilog书写7位数据位,1位偶校验,115200bps的串行发送端(随机填充)
时间: 2024-05-03 18:22:42 浏览: 137
以下是一个例子:
```systemverilog
module serial_transmitter (
input logic clk,
input logic rst_n,
input logic [6:0] data,
output logic tx
);
logic parity;
always_comb begin
parity = ^data; // calculate even parity
end
assign tx = 1'b0; // start bit
always_ff @(posedge clk) begin
if (!rst_n) begin
tx <= 1'b0;
end else if (tx === 1'b0) begin
tx <= {parity, data, 1'b1}; // data bits and parity bit followed by stop bit
end else begin
tx <= 1'b1;
end
end
endmodule
```
这个模块有一个时钟输入(clk)、一个异步复位输入(rst_n)、一个7位数据输入(data)和一个串行输出(tx)。它使用异步复位将 tx 初始化为低电平,然后在时钟上升沿时,按顺序发送起始位(低电平)、数据位(7位加上一个偶校验位)和停止位(高电平)。偶校验是通过异或运算符 (^) 计算的。这个模块的传输速率是 115200bps。
相关问题
用Verilog书写7位数据位,1位偶校验,115200bps的串行发送端(随机填充)
以下是使用Verilog书写的7位数据位,1位偶校验,115200bps的串行发送端:
```
module serial_tx(
input clk, //时钟信号
input reset, //重置信号
input [6:0] data_in, //输入数据位
output reg tx_out //串行输出数据
);
reg [7:0] tx_data; //存储发送的数据位和偶校验位
reg [2:0] tx_count; //计数器,用于确定何时发送下一位数据
reg parity_bit; //偶校验位
always @(posedge clk or posedge reset) begin
if(reset) begin //重置计数器、存储器和输出端口
tx_count <= 0;
tx_data <= 0;
tx_out <= 1;
end
else begin //发送数据
if(tx_count == 0) begin //发送起始位
tx_data <= {1'b0, data_in, parity_bit};
tx_count <= tx_count + 1;
tx_out <= 0;
end
else if(tx_count < 10) begin //发送数据位和偶校验位
tx_data <= {tx_data[6:0], parity_bit};
tx_count <= tx_count + 1;
end
else if(tx_count == 10) begin //发送停止位
tx_out <= 1;
tx_count <= 0;
end
end
end
//计算偶校验位
always @(data_in) begin
integer i;
parity_bit = 1'b0;
for(i = 0; i < 7; i = i + 1) begin
parity_bit = parity_bit ^ data_in[i];
end
end
endmodule
```
1.用System Verilog书写7位数据位,1位偶校验,波特率为115200bps的uart串行发送端 2. 用SV书写对应的行为模型(接收端),并输出激励中的字节值,奇偶性错误的,输出校验错误 3.编写testcase
1. 串行发送端代码:
```verilog
module uart_tx
(
input clk,
input rst,
input [6:0] data_in,
output reg tx,
output reg parity
);
reg [10:0] counter;
reg [7:0] shift_reg;
reg [7:0] data_with_parity;
//计算奇偶校验位
always_comb
begin
data_with_parity = {data_in, 1'b0};
parity = ^data_with_parity;
end
always @(posedge clk or posedge rst)
begin
if (rst) begin
counter <= 11'b0;
shift_reg <= 8'h00;
tx <= 1'b1;
end
else begin
if (counter == 11'b0) begin //发送起始位
shift_reg <= data_with_parity;
counter <= counter + 1;
tx <= 1'b0;
end
else if (counter == 11'd9) begin //发送停止位
shift_reg <= 8'hFF;
counter <= counter + 1;
end
else if (counter == 11'd10) begin //重置状态
counter <= 11'b0;
shift_reg <= 8'h00;
tx <= 1'b1;
end
else begin //发送数据位
shift_reg <= {shift_reg[6:0], data_in[counter - 2]};
counter <= counter + 1;
end
end
end
endmodule
```
2. 串行接收端代码:
```verilog
module uart_rx
(
input clk,
input rst,
input rx,
output reg [6:0] data_out,
output reg parity_error,
output reg frame_error,
output reg overrun_error
);
reg [10:0] counter;
reg [7:0] shift_reg;
reg [6:0] data_reg;
reg last_rx;
//计算奇偶校验位
function automatic bit calc_parity;
input [7:0] data;
begin
calc_parity = ^data;
end
endfunction
always @(posedge clk or posedge rst)
begin
if (rst) begin
counter <= 11'b0;
shift_reg <= 8'h00;
data_reg <= 7'b0;
parity_error <= 1'b0;
frame_error <= 1'b0;
overrun_error <= 1'b0;
end
else begin
if (rx != last_rx) begin //检测起始位
if (rx == 1'b0) begin
counter <= counter + 1;
shift_reg <= 8'h00;
data_reg <= 7'b0;
end
else begin
//起始位错误
frame_error <= 1'b1;
counter <= 11'b0;
shift_reg <= 8'h00;
data_reg <= 7'b0;
end
end
else if (counter > 0 && counter < 11) begin //接收数据位和校验位
shift_reg <= {shift_reg[6:0], rx};
counter <= counter + 1;
if (counter == 11) begin //接收完成
data_reg <= shift_reg[6:0];
shift_reg <= 8'h00;
counter <= 11'b0;
if (calc_parity(data_reg) != rx) begin //校验错误
parity_error <= 1'b1;
end
end
end
else if (counter == 11 && rx == 1'b0) begin //接收停止位
counter <= 11'b0;
shift_reg <= 8'h00;
data_out <= data_reg;
end
else if (counter == 11 && rx == 1'b1) begin //停止位错误
frame_error <= 1'b1;
counter <= 11'b0;
shift_reg <= 8'h00;
data_reg <= 7'b0;
end
if (counter == 0 && rx == 0 && last_rx == 0) begin //溢出错误
overrun_error <= 1'b1;
shift_reg <= 8'h00;
data_reg <= 7'b0;
end
last_rx <= rx;
end
end
endmodule
```
3. 测试代码:
```verilog
module test_uart;
//串行发送端实例
uart_tx tx_inst(
.clk(clk),
.rst(rst),
.data_in(data_in),
.tx(tx),
.parity(parity)
);
//串行接收端实例
uart_rx rx_inst(
.clk(clk),
.rst(rst),
.rx(rx),
.data_out(data_out),
.parity_error(parity_error),
.frame_error(frame_error),
.overrun_error(overrun_error)
);
reg clk;
reg rst;
reg [6:0] data_in;
wire tx;
wire parity;
wire rx;
wire [6:0] data_out;
wire parity_error;
wire frame_error;
wire overrun_error;
//时钟和复位信号
initial begin
clk = 0;
forever #5 clk = ~clk;
end
initial begin
rst = 1;
#10 rst = 0;
end
//初始测试数据
initial begin
data_in = 7'b1001001;
#100;
data_in = 7'b0101010;
#100;
end
//测试奇偶校验错误
initial begin
data_in = 7'b0000111;
#100;
end
//测试帧错误
initial begin
data_in = 7'b1001001;
#100;
data_in = 7'b0101010;
#5 rx = 1;
#5 rx = 0;
#5 rx = 1;
#5 rx = 1;
#5;
end
//测试溢出错误
initial begin
data_in = 7'b1001001;
#100;
data_in = 7'b0101010;
#5 rx = 0;
#100 rx = 0;
end
endmodule
```
阅读全文