1.用System Verilog书写7位数据位,1位偶校验,波特率为115200bps的uart串行发送端 2. 用SV书写对应的行为模型(接收端),并输出激励中的字节值,奇偶性错误的,输出校验错误 3.编写testcase
时间: 2024-05-12 11:20:28 浏览: 76
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
```
阅读全文