Estoy tratando de implementar UART TX utilizando tres estados FSM. El problema es que los datos recibidos no se transmiten en serie, siempre que "rd_en" sea alto. (No hay paridad, solo TX & RX)
module SAT_UART (clk,rst,enable,rd_en,tx,rx_data);
input clk,rst,rd_en,enable;
input [7:0] rx_data;
output tx;
reg [7:0] count;
reg tx;
parameter idle=2'd0,start=2'd1,data=2'd2,stop=2'd3;
reg [2:0] state;
reg [2:0] next_state;
always@(state or rd_en or enable)
begin:FSM_COMB //COMBINATIONAL_LOGIC
next_state = 3'b000;
case(state)
idle:if(enable==1'b1 && rd_en==1'b1)
next_state = start;
start:if(enable==1'b1 && rd_en==1'b1)
next_state = data;
data:if(enable==1'b1 && rd_en==1'b1)
next_state = stop;
stop:if(enable==1'b1 && rd_en==1'b1)
begin
next_state = idle;
end
endcase
end
always@(posedge clk)
begin:FSM_SEQ //SEQUENTIAL_LOGIC
if(rst == 1'b1)begin
state <= idle;
end
else if(count == 4'd0)
state <= next_state;
else if(count == 4'd1)
state <= next_state;
else if(count == 4'd2)
state <= next_state;
else if(count == 4'd3)
state <= next_state;
else if(count == 4'd4)
state <= next_state;
else if(count == 4'd5)
state <= next_state;
else if(count == 4'd6)
state <= next_state;
else if(count == 4'd7)
state <= next_state;
else if(count == 4'd8)
state <= next_state;
else
state <= idle;
end
always@(posedge clk)
begin:FSM_OUT //OUTPUT_LOGIC
if(rst == 1'b1)
tx <= 1'b1;
count <= 1'b0;
case(state)
idle:
tx <= 1'b1;
start:
tx <= 1'b0; //START_BIT
data:begin
count <= count+1;
tx <= rx_data[count - 1];
end
stop:if(count == 8)
tx <= 1'b1; //STOP_BIT
else if(enable==1'b1 && rd_en==1'b1)
tx <= 1'b0;
default: tx <= 1'b1;
endcase
end
endmodule
Este es un enfoque modificado que funciona solo para transmisión, no puedo entender por qué el bucle no está terminando. (la simulación se muestra a continuación)
module late_1(clk,rst,rd_en,enable,tx,rx_data);
input [7:0]rx_data;
input clk,rst,rd_en,enable;
output tx;
reg tx;
reg [3:0]state;
reg [3:0]next_state;
reg [7:0]tx_reg;
wire clk,rst,rd_en,enable;
parameter IDLE = 4'b0000,
START = 4'b0001,
DATA_0 = 4'b0010,
DATA_1 = 4'b0011,
DATA_2 = 4'b0100,
DATA_3 = 4'b0101,
DATA_4 = 4'b0110,
DATA_5 = 4'b0111,
DATA_6 = 4'b1000,
DATA_7 = 4'b1001,
STOP = 4'b1010;
always@(state or rd_en or enable)
begin:TX_REGISTER
if(state == STOP)
tx_reg <= 1'b1;
else
tx_reg <= rx_data;
end
always@(state or rd_en or enable)
begin:COMB_LOGIC
next_state = 4'b0000;
if(rst == 1'b1)
begin
next_state = IDLE;
end
else
case(state)
IDLE :
begin
next_state = START;
end
START :
begin
next_state = DATA_0;
end
DATA_0:
begin
next_state = DATA_1;
end
DATA_1:
begin
next_state = DATA_2;
end
DATA_2:
begin
next_state = DATA_3;
end
DATA_3:
begin
next_state = DATA_4;
end
DATA_4:
begin
next_state = DATA_5;
end
DATA_5:
begin
next_state = DATA_6;
end
DATA_6:
begin
next_state = DATA_7;
end
DATA_7:
begin
next_state = STOP;
end
STOP :
begin
next_state = IDLE;
end
default:begin
next_state = IDLE;
end
endcase
end
always@(posedge clk)
begin:SEQ_LOGIC
tx <= 1'b1;
if(rst == 1'b1)
begin
tx <= 1'b1;
state <= IDLE;
tx_reg <= 1'd0;
end
else
begin
state <= next_state;
case(state)
IDLE : if(!rst)
begin
tx <= 1'b1;
end
START : if(rd_en == 1'b1 && enable == 1'b1)
begin
tx <= 1'b0;
end
DATA_0: if(tx == 1'b0)
begin
tx <= tx_reg[0];
end
DATA_1:begin
tx <= tx_reg[1];
end
DATA_2:begin
tx <= tx_reg[2];
end
DATA_3:begin
tx <= tx_reg[3];
end
DATA_4:begin
tx <= tx_reg[4];
end
DATA_5:begin
tx <= tx_reg[5];
end
DATA_6:begin
tx <= tx_reg[6];
end
DATA_7:begin
tx <= tx_reg[7];
end
STOP :if(tx == tx_reg[7])
begin
state <= IDLE;
tx <= 1'b1;
end
default:begin
state <= IDLE;
end
endcase
end
end
endmodule