设计最简单的RS232通信逻辑,FPGA实现将接收到的数据会发出去,总共两个数据传输引脚,一收一发。将此通信模块分为三个部分:
1、波特率控制模块
2、发送模块。
3、接收模块
下面是代码部分:
//<span style="font-family: Arial, Helvetica, sans-serif;">Baud_Counter.v</span>
module Baud_Counter (
// Inputs
input clk,
input reset,
input reset_counters,
// Outputs
output reg baud_clock_rising_edge,
output reg baud_clock_falling_edge,
output reg all_bits_transmitted
);
parameter BAUD_COUNTER_WIDTH = 9;
parameter BAUD_COUNT = 5;
parameter BAUD_TICK_COUNT = BAUD_COUNT - 1; //9'd433;
parameter HALF_BAUD_TICK_COUNT = BAUD_COUNT / 2; //9'd216;
parameter DATA_WIDTH = 9;
parameter TOTAL_DATA_WIDTH = DATA_WIDTH + 2;
reg [(BAUD_COUNTER_WIDTH - 1):0] baud_counter;
reg [3:0] bit_counter;
// control baud_counter
always @(posedge clk)
begin
if (reset == 1'b1)
baud_counter <= {BAUD_COUNTER_WIDTH{1'b0}};
else if (reset_counters)
baud_counter <= {BAUD_COUNTER_WIDTH{1'b0}};
else if (baud_counter == BAUD_TICK_COUNT)
baud_counter <= {BAUD_COUNTER_WIDTH{1'b0}};
else
baud_counter <= baud_counter + 1'b1;
end
// control baud_clock_rising_edge signal
always @(posedge clk)
begin
if (reset == 1'b1)
baud_clock_rising_edge <= 1'b0;
else if (baud_counter == BAUD_TICK_COUNT)
baud_clock_rising_edge <= 1'b1;
else
baud_clock_rising_edge <= 1'b0;
end
// control baud_clock_falling_edge signal
always @(posedge clk)
begin
if (reset == 1'b1)
baud_clock_falling_edge <= 1'b0;
else if (baud_counter == HALF_BAUD_TICK_COUNT)
baud_clock_falling_edge <= 1'b1;
else
baud_clock_falling_edge <= 1'b0;
end
// control bit counter
always @(posedge clk)
begin
if (reset == 1'b1)
bit_counter <= 4'h0;
else if (reset_counters)
bit_counter <= 4'h0;
else if (bit_counter == TOTAL_DATA_WIDTH)
bit_counter <= 4'h0;
else if (baud_counter == BAUD_TICK_COUNT)
bit_counter <= bit_counter + 4'h1;
end
// control all_bits_transmitted signal
always @(posedge clk)
begin
if (reset == 1'b1)
all_bits_transmitted <= 1'b0;
else if (bit_counter == TOTAL_DATA_WIDTH)
all_bits_transmitted <= 1'b1;
else
all_bits_transmitted <= 1'b0;
end
endmodule
//RS232_Out.v
module RS232_Out(
// Inputs
input clk,
input reset,
input [DATA_WIDTH:1] transmit_data,
input transmit_data_en,
// Outputs
output reg serial_data_out,
output reg transmitting_data
);
parameter DATA_WIDTH = 8;
parameter BAUD_COUNT = 9'd434;
wire shift_data_reg_en, read_input_en;
//wire baud_clock;
wire all_bits_transmitted;
// debug outputs
//assign baud_clock = shift_data_reg_en;
//assign next_bit = data_out_shift_reg[0];
reg [DATA_WIDTH:0] data_out_shift_reg;
initial
begin
serial_data_out <= 1'b1;
data_out_shift_reg <= {(DATA_WIDTH + 1){1'b1}}; // all ones
end
always @(posedge clk)
begin
if (reset == 1'b1)
serial_data_out <= 1'b1;
else
serial_data_out <= data_out_shift_reg[0]; //next bit
end
always @(posedge clk)
begin
if (reset == 1'b1)
transmitting_data <= 1'b0;
else if (all_bits_transmitted == 1'b1)
transmitting_data <= 1'b0;
else if (transmit_data_en)
transmitting_data <= 1'b1;
end
always @(posedge clk)
begin
if (reset == 1'b1)
data_out_shift_reg <= {(DATA_WIDTH + 1){1'b1}}; // all ones
else if (read_input_en)
data_out_shift_reg <= {transmit_data,1'b0};
else if (shift_data_reg_en)
data_out_shift_reg <=
{1'b1, data_out_shift_reg[DATA_WIDTH:1]};
end
assign read_input_en = ~transmitting_data & ~all_bits_transmitted & transmit_data_en;
Baud_Counter Out_Counter (
// Inputs
.clk(clk), .reset(reset), .reset_counters(~transmitting_data),
// Outputs
.baud_clock_rising_edge(shift_data_reg_en),
.baud_clock_falling_edge(),
.all_bits_transmitted(all_bits_transmitted)
);
defparam
Out_Counter.BAUD_COUNT = BAUD_COUNT,
Out_Counter.DATA_WIDTH = DATA_WIDTH;
/*
Altera_UP_SYNC_FIFO RS232_Out_FIFO (
// Inputs
.clk (clk),
.reset (reset),
.write_en (transmit_data_en & ~fifo_is_full),
.write_data (transmit_data),
.read_en (read_fifo_en),
// Bidirectionals
// Outputs
.fifo_is_empty (fifo_is_empty),
.fifo_is_full (fifo_is_full),
.words_used (fifo_used),
.read_data (data_from_fifo)
);
defparam
RS232_Out_FIFO.DATA_WIDTH = DATA_WIDTH,
RS232_Out_FIFO.DATA_DEPTH = 128,
RS232_Out_FIFO.ADDR_WIDTH = 7;
*/
endmodule
//RA232_In.v
module RS232_In (
// Inputs
input clk,
input reset,
input serial_data_in,
input receive_data_en,
// Outputs
output reg [(DATA_WIDTH-1):0] received_data,
output reg receiving_data,
output reg data_received,
output baud_clock
);
parameter BAUD_COUNT = 9'd434;
parameter DATA_WIDTH = 8;
parameter TOTAL_DATA_WIDTH = DATA_WIDTH + 2;
wire shift_data_reg_en;
wire all_bits_received;
assign baud_clock = shift_data_reg_en;
reg [(TOTAL_DATA_WIDTH - 1):0] data_in_shift_reg;
//reg receiving_data;
reg prev_receiving_data;
always @(posedge clk)
begin
if (reset == 1'b1)
receiving_data <= 1'b0;
else if (all_bits_received == 1'b1)
receiving_data <= 1'b0;
else if (serial_data_in == 1'b0)
receiving_data <= 1'b1;
end
always @(posedge clk)
begin
prev_receiving_data <= receiving_data;
if (receiving_data==1'b1)
data_received <= 1'b0;
else if (prev_receiving_data==1'b1)
begin
data_received <= 1'b1;
received_data <= data_in_shift_reg[DATA_WIDTH:1];
end
end
always @(posedge clk)
begin
if (reset == 1'b1)
data_in_shift_reg <= {TOTAL_DATA_WIDTH{1'b0}};
else if (shift_data_reg_en)
data_in_shift_reg <=
{serial_data_in, data_in_shift_reg[(TOTAL_DATA_WIDTH - 1):1]};
end
Baud_Counter RS232_In_Counter (
// Inputs
.clk(clk),
.reset(reset),
.reset_counters(~receiving_data),
// Outputs
.baud_clock_rising_edge(),
.baud_clock_falling_edge(shift_data_reg_en),
.all_bits_transmitted(all_bits_received)
);
defparam
RS232_In_Counter.BAUD_COUNT= BAUD_COUNT,
RS232_In_Counter.DATA_WIDTH= DATA_WIDTH;
/*
Altera_UP_SYNC_FIFO RS232_In_FIFO (
// Inputs
.clk (clk),
.reset (reset),
.write_en (all_bits_received & ~fifo_is_full),
.write_data (data_in_shift_reg[(DATA_WIDTH + 1):1]),
.read_en (receive_data_en & ~fifo_is_empty),
// Bidirectionals
// Outputs
.fifo_is_empty (fifo_is_empty),
.fifo_is_full (fifo_is_full),
.words_used (fifo_used),
.read_data (received_data)
);
defparam
RS232_In_FIFO.DATA_WIDTH = DATA_WIDTH,
RS232_In_FIFO.DATA_DEPTH = 128,
RS232_In_FIFO.ADDR_WIDTH = 7;
*/
endmodule