G
gknight
Guest
I have another verilog question for you. My question is based on the
following: In my top.v I have,
SerialFun serial (
.clk(CLK_24),
.RxD(FROM_PC), // Data line to PC
.TxD(TO_PC), // Data line from PC
.GPout(RxWord_PC), // Byte received
.GPin(TxWord_PC), // Byte to send
.TxReady(TXREADY), // Signal TX line is idle
.RxReady(RXREADY), // Signal byte was received
.TxStart(Send), // Command to init transmission
.RxIdle(),
.baud_tick()
);
// Fifo Controller Module
FIFO_CNTRL fifo_ctrl (
.cPulse(START),
.reset(RESET),
.clk(CLK_100),
.Tx_Rdy(TXREADY),
.Rx_Rdy(RXREADY),
.Tx_Data(TxWord_PC),
.Data_Out(Data_Out), // Data stored in FIFO
.full(bFull), // signal FIFO is full
.empty(bEmpty), // signal FIFO is empty
.RE(RE), // FIFO into read mode
.Write(Write), // FIFO into write mode
.Send(Send) // Signal sent start serial TX
Send->TxStart
);
Its implementation is FIFO_CNTL.v. States SST1
through 6 send the sequence FF FF FF FF FF 01, followed by a dump of the
FIFO buffer that is 1024 elements deep and 24-bits wide. States DT1 to
DT4, handle sending 8-bits at a time over serial. DT1 queues the first
address in the FIFO and DT2 - 4 segment the 24 bits.
When you turn on the FPGA, it fills the FIFO and waits until signaled to
start the serial transmission. Now, once the transmit sequence is
triggered via push button, each transmission occurs when Tx_Rdy is high
(ready to tx byte to PC).
What I want to do is implement a z-modem protocol. Each byte that is
sent
to the PC is sent back to the FPGA acknowledging its receipt. The FPGA
does not preform any error correction. What I have done is added a state
between all transmission states in my FSM that waits for a byte to be
send
back before it progresses.
I was wondering, if you could take a minute to look at the symantics of
my
FSM and see if I have managed my states properly. What I am asking for
is
if you have worked with rs232, did I handly my transitions correctly.
Nizar informed me that you could suggest to me the error in my FSM and
refine its design to something simpler.
The FPFA waits when powered up to be triggered via a push button. While
wiating, it transmits 'z' over serial. When triggered, the FIFO fills
until full signals its full. The FPGA transmits the sequence FF FF FF FF
FF 01, queues up the first address in the FIFO, transmits 3 bytes, loops
and queues the next address. Repeats this process until empty is high.
Returns to the start, and fills the FIFO.
This is a bit of a long email but any help or insight you can provide is
greatly valued. Here is the code:
//FIFO controller with Flags appended to data stream
module FIFO_CNTRL(cPulse, reset, clk, Tx_Rdy, Rx_Rdy, Tx_Data, Data_Out,
full, empty, RE, Write, Send);
input cPulse;
input reset, clk;
input Tx_Rdy;
input Rx_Rdy;
input [23:0] Data_Out;
input full, empty;
output [7:0] Tx_Data;
output Write, Send, RE;
// REGISTERS
reg Send, Write, RE, txRdyPatch;
reg [7:0] Tx_Data;
reg [3:0] state, nxt_state;
// PARAMETER DEFINITIONS
parameter VCC = 1'b1;
parameter GND_1 = 1'b0;
parameter ZS = 0,
SST1 = 1,
ACKSST1 = 2,
SST2 = 3,
ACKSST2 = 4,
SST3 = 5,
ACKSST3 = 6,
SST4 = 7,
ACKSST4 = 8,
SST5 = 9,
ACKSST5 = 10,
SST6 = 11,
ACKSST6 = 12,
DT1 = 13,
DT2 = 14,
ACKDT2 = 15,
DT3 = 16,
ACKDT3 = 17,
DT4 = 18,
ACKDT4 = 19,
RS = 20,
WS = 21;
// State Transition
always@(posedge clk or negedge reset)
begin
if (~reset) begin
state <= ZS;
txRdyPatch <= GND_1;
end
else begin
state <= nxt_state;
if (state != nxt_state) txRdyPatch <= VCC;
else txRdyPatch <= GND_1;
end
end
// Next State Calculations
always@(state or txRdyPatch or Tx_Rdy or Rx_Rdy or full or empty or reset
or cPulse)
begin
case(state)
ZS: begin
if (cPulse) nxt_state = RS;
else nxt_state = ZS;
end
SST1: begin
if (Tx_Rdy & ~txRdyPatch) nxt_state = ACKSST1;
else nxt_state = SST1;
end
ACKSST1: begin
if (Rx_Rdy) nxt_state = SST2;
else nxt_state = ACKSST1;
end
SST2: begin
if (Tx_Rdy & ~txRdyPatch) nxt_state = ACKSST2;
else nxt_state = SST2;
end
ACKSST2: begin
if (Rx_Rdy) nxt_state = SST3;
else nxt_state = ACKSST2;
end
SST3: begin
if (Tx_Rdy & ~txRdyPatch) nxt_state = ACKSST3;
else nxt_state = SST3;
end
ACKSST3: begin
if (Rx_Rdy) nxt_state = SST4;
else nxt_state = ACKSST3;
end
SST4: begin
if (Tx_Rdy & ~txRdyPatch) nxt_state = ACKSST4;
else nxt_state = SST4;
end
ACKSST4: begin
if (Rx_Rdy) nxt_state = SST5;
else nxt_state = ACKSST4;
end
SST5: begin
if (Tx_Rdy & ~txRdyPatch) nxt_state = ACKSST5;
else nxt_state = SST5;
end
ACKSST5: begin
if (Rx_Rdy) nxt_state = SST6;
else nxt_state = ACKSST5;
end
SST6: begin
if (Tx_Rdy & ~txRdyPatch) nxt_state = ACKSST6;
else nxt_state = SST6;
end
ACKSST6: begin
if (Rx_Rdy) nxt_state = DT1;
else nxt_state = ACKSST6;
end
DT1: begin
if (Tx_Rdy & ~txRdyPatch) nxt_state = DT2;
else nxt_state = DT1;
end
DT2: begin
if (Tx_Rdy & ~txRdyPatch) nxt_state = ACKDT2;
else nxt_state = DT2;
end
ACKDT2: begin
if (Rx_Rdy) nxt_state = DT3;
else nxt_state = ACKDT2;
end
DT3: begin
if (Tx_Rdy & ~txRdyPatch) nxt_state = ACKDT3;
else nxt_state = DT3;
end
ACKDT3: begin
if (Rx_Rdy) nxt_state = DT4;
else nxt_state = ACKDT3;
end
DT4: begin
if (empty & Tx_Rdy & ~txRdyPatch) nxt_state = RS;
else if (~empty & Tx_Rdy) nxt_state = ACKDT4;
else nxt_state = DT4;
end
ACKDT4: begin
if (Rx_Rdy) nxt_state = DT1;
else nxt_state = ACKDT4;
end
RS: begin
if (full & Tx_Rdy & ~txRdyPatch) nxt_state = SST1;
else if (full & ~Tx_Rdy) nxt_state = WS;
else nxt_state = RS;
end
WS: begin
if (Tx_Rdy & ~txRdyPatch) nxt_state = SST1;
else nxt_state = WS;
end
default: nxt_state = ZS;
endcase
end
// Output calculations
always@(state)
begin
case(state)
ZS: begin
Tx_Data <= 8'b01111010; // z,7AH,122b
Write <= 0;
RE <= 0;
Send <= 1;
end
SST1: begin
Tx_Data <= 8'b11111111; // 255,0xFF
Write <= 0;
RE <= 0;
Send <=1;
end
ACKSST1: begin
Tx_Data <= 8'b0;
Write <= 0;
RE <= 0;
Send <= 0;
end
SST2: begin
Tx_Data <= 8'b11111111; // 255,0xFF
Write <= 0;
RE <= 0;
Send <=1;
end
ACKSST2: begin
Tx_Data <= 8'b0;
Write <= 0;
RE <= 0;
Send <= 0;
end
SST3: begin
Tx_Data <= 8'b11111111; // 255,0xFF
Write <= 0;
RE <= 0;
Send <=1;
end
ACKSST3: begin
Tx_Data <= 8'b0;
Write <= 0;
RE <= 0;
Send <= 0;
end
SST4: begin
Tx_Data <= 8'b11111111; // 255,0xFF
Write <= 0;
RE <= 0;
Send <=1;
end
ACKSST4: begin
Tx_Data <= 8'b0;
Write <= 0;
RE <= 0;
Send <= 0;
end
SST5: begin
Tx_Data <= 8'b11111111; // 255,0xFF
Write <= 0;
RE <= 0;
Send <=1;
end
ACKSST5: begin
Tx_Data <= 8'b0;
Write <= 0;
RE <= 0;
Send <= 0;
end
SST6: begin
Tx_Data <= 8'b00000001; // 1,0x01
Write <= 0;
RE <= 0;
Send <=1;
end
ACKSST6: begin
Tx_Data <= 8'b0;
Write <= 0;
RE <= 0;
Send <= 0;
end
DT1: begin
Tx_Data <= 8'b00000000; //0
Write <= 0;
RE <= 1;
Send <= 0;
end
DT2: begin
Tx_Data <=
{Data_Out[4],Data_Out[5],Data_Out[6],Data_Out[7],Data_Out[8],Data_Out[9],Data_Out[10],Data_Out[11]};
Write <= 0;
RE <= 0;
Send <= 1;
end
ACKDT2: begin
Tx_Data <= 8'b0;
Write <= 0;
RE <= 0;
Send <= 0;
end
DT3: begin
Tx_Data <=
{Data_Out[20],Data_Out[21],Data_Out[22],Data_Out[23],Data_Out[0],Data_Out[1],Data_Out[2],Data_Out[3]};
Write <= 0;
RE <= 0;
Send <= 1;
end
ACKDT3: begin
Tx_Data <= 8'b0;
Write <= 0;
RE <= 0;
Send <= 0;
end
DT4: begin
Tx_Data <=
{Data_Out[12],Data_Out[13],Data_Out[14],Data_Out[15],Data_Out[16],Data_Out[17],Data_Out[18],Data_Out[19]};
Write <= 0;
RE <= 0;
Send <= 1;
end
ACKDT4: begin
Tx_Data <= 8'b0;
Write <= 0;
RE <= 0;
Send <= 0;
end
RS: begin
Tx_Data <= 8'b01110010; // r,72H, 114b
Write <= 1;
RE <= 0;
Send <= 0;
end
WS: begin
Tx_Data <= 8'b01110111; // w,077H,119b
Write <= 0;
RE <= 0;
Send <= 0;
end
default: begin
Tx_Data <= 8'b01111010; // z,7AH,122b
Write <= 0;
RE <= 0;
Send <= 1;
end
endcase
end
endmodule
following: In my top.v I have,
SerialFun serial (
.clk(CLK_24),
.RxD(FROM_PC), // Data line to PC
.TxD(TO_PC), // Data line from PC
.GPout(RxWord_PC), // Byte received
.GPin(TxWord_PC), // Byte to send
.TxReady(TXREADY), // Signal TX line is idle
.RxReady(RXREADY), // Signal byte was received
.TxStart(Send), // Command to init transmission
.RxIdle(),
.baud_tick()
);
// Fifo Controller Module
FIFO_CNTRL fifo_ctrl (
.cPulse(START),
.reset(RESET),
.clk(CLK_100),
.Tx_Rdy(TXREADY),
.Rx_Rdy(RXREADY),
.Tx_Data(TxWord_PC),
.Data_Out(Data_Out), // Data stored in FIFO
.full(bFull), // signal FIFO is full
.empty(bEmpty), // signal FIFO is empty
.RE(RE), // FIFO into read mode
.Write(Write), // FIFO into write mode
.Send(Send) // Signal sent start serial TX
Send->TxStart
);
Its implementation is FIFO_CNTL.v. States SST1
through 6 send the sequence FF FF FF FF FF 01, followed by a dump of the
FIFO buffer that is 1024 elements deep and 24-bits wide. States DT1 to
DT4, handle sending 8-bits at a time over serial. DT1 queues the first
address in the FIFO and DT2 - 4 segment the 24 bits.
When you turn on the FPGA, it fills the FIFO and waits until signaled to
start the serial transmission. Now, once the transmit sequence is
triggered via push button, each transmission occurs when Tx_Rdy is high
(ready to tx byte to PC).
What I want to do is implement a z-modem protocol. Each byte that is
sent
to the PC is sent back to the FPGA acknowledging its receipt. The FPGA
does not preform any error correction. What I have done is added a state
between all transmission states in my FSM that waits for a byte to be
send
back before it progresses.
I was wondering, if you could take a minute to look at the symantics of
my
FSM and see if I have managed my states properly. What I am asking for
is
if you have worked with rs232, did I handly my transitions correctly.
Nizar informed me that you could suggest to me the error in my FSM and
refine its design to something simpler.
The FPFA waits when powered up to be triggered via a push button. While
wiating, it transmits 'z' over serial. When triggered, the FIFO fills
until full signals its full. The FPGA transmits the sequence FF FF FF FF
FF 01, queues up the first address in the FIFO, transmits 3 bytes, loops
and queues the next address. Repeats this process until empty is high.
Returns to the start, and fills the FIFO.
This is a bit of a long email but any help or insight you can provide is
greatly valued. Here is the code:
//FIFO controller with Flags appended to data stream
module FIFO_CNTRL(cPulse, reset, clk, Tx_Rdy, Rx_Rdy, Tx_Data, Data_Out,
full, empty, RE, Write, Send);
input cPulse;
input reset, clk;
input Tx_Rdy;
input Rx_Rdy;
input [23:0] Data_Out;
input full, empty;
output [7:0] Tx_Data;
output Write, Send, RE;
// REGISTERS
reg Send, Write, RE, txRdyPatch;
reg [7:0] Tx_Data;
reg [3:0] state, nxt_state;
// PARAMETER DEFINITIONS
parameter VCC = 1'b1;
parameter GND_1 = 1'b0;
parameter ZS = 0,
SST1 = 1,
ACKSST1 = 2,
SST2 = 3,
ACKSST2 = 4,
SST3 = 5,
ACKSST3 = 6,
SST4 = 7,
ACKSST4 = 8,
SST5 = 9,
ACKSST5 = 10,
SST6 = 11,
ACKSST6 = 12,
DT1 = 13,
DT2 = 14,
ACKDT2 = 15,
DT3 = 16,
ACKDT3 = 17,
DT4 = 18,
ACKDT4 = 19,
RS = 20,
WS = 21;
// State Transition
always@(posedge clk or negedge reset)
begin
if (~reset) begin
state <= ZS;
txRdyPatch <= GND_1;
end
else begin
state <= nxt_state;
if (state != nxt_state) txRdyPatch <= VCC;
else txRdyPatch <= GND_1;
end
end
// Next State Calculations
always@(state or txRdyPatch or Tx_Rdy or Rx_Rdy or full or empty or reset
or cPulse)
begin
case(state)
ZS: begin
if (cPulse) nxt_state = RS;
else nxt_state = ZS;
end
SST1: begin
if (Tx_Rdy & ~txRdyPatch) nxt_state = ACKSST1;
else nxt_state = SST1;
end
ACKSST1: begin
if (Rx_Rdy) nxt_state = SST2;
else nxt_state = ACKSST1;
end
SST2: begin
if (Tx_Rdy & ~txRdyPatch) nxt_state = ACKSST2;
else nxt_state = SST2;
end
ACKSST2: begin
if (Rx_Rdy) nxt_state = SST3;
else nxt_state = ACKSST2;
end
SST3: begin
if (Tx_Rdy & ~txRdyPatch) nxt_state = ACKSST3;
else nxt_state = SST3;
end
ACKSST3: begin
if (Rx_Rdy) nxt_state = SST4;
else nxt_state = ACKSST3;
end
SST4: begin
if (Tx_Rdy & ~txRdyPatch) nxt_state = ACKSST4;
else nxt_state = SST4;
end
ACKSST4: begin
if (Rx_Rdy) nxt_state = SST5;
else nxt_state = ACKSST4;
end
SST5: begin
if (Tx_Rdy & ~txRdyPatch) nxt_state = ACKSST5;
else nxt_state = SST5;
end
ACKSST5: begin
if (Rx_Rdy) nxt_state = SST6;
else nxt_state = ACKSST5;
end
SST6: begin
if (Tx_Rdy & ~txRdyPatch) nxt_state = ACKSST6;
else nxt_state = SST6;
end
ACKSST6: begin
if (Rx_Rdy) nxt_state = DT1;
else nxt_state = ACKSST6;
end
DT1: begin
if (Tx_Rdy & ~txRdyPatch) nxt_state = DT2;
else nxt_state = DT1;
end
DT2: begin
if (Tx_Rdy & ~txRdyPatch) nxt_state = ACKDT2;
else nxt_state = DT2;
end
ACKDT2: begin
if (Rx_Rdy) nxt_state = DT3;
else nxt_state = ACKDT2;
end
DT3: begin
if (Tx_Rdy & ~txRdyPatch) nxt_state = ACKDT3;
else nxt_state = DT3;
end
ACKDT3: begin
if (Rx_Rdy) nxt_state = DT4;
else nxt_state = ACKDT3;
end
DT4: begin
if (empty & Tx_Rdy & ~txRdyPatch) nxt_state = RS;
else if (~empty & Tx_Rdy) nxt_state = ACKDT4;
else nxt_state = DT4;
end
ACKDT4: begin
if (Rx_Rdy) nxt_state = DT1;
else nxt_state = ACKDT4;
end
RS: begin
if (full & Tx_Rdy & ~txRdyPatch) nxt_state = SST1;
else if (full & ~Tx_Rdy) nxt_state = WS;
else nxt_state = RS;
end
WS: begin
if (Tx_Rdy & ~txRdyPatch) nxt_state = SST1;
else nxt_state = WS;
end
default: nxt_state = ZS;
endcase
end
// Output calculations
always@(state)
begin
case(state)
ZS: begin
Tx_Data <= 8'b01111010; // z,7AH,122b
Write <= 0;
RE <= 0;
Send <= 1;
end
SST1: begin
Tx_Data <= 8'b11111111; // 255,0xFF
Write <= 0;
RE <= 0;
Send <=1;
end
ACKSST1: begin
Tx_Data <= 8'b0;
Write <= 0;
RE <= 0;
Send <= 0;
end
SST2: begin
Tx_Data <= 8'b11111111; // 255,0xFF
Write <= 0;
RE <= 0;
Send <=1;
end
ACKSST2: begin
Tx_Data <= 8'b0;
Write <= 0;
RE <= 0;
Send <= 0;
end
SST3: begin
Tx_Data <= 8'b11111111; // 255,0xFF
Write <= 0;
RE <= 0;
Send <=1;
end
ACKSST3: begin
Tx_Data <= 8'b0;
Write <= 0;
RE <= 0;
Send <= 0;
end
SST4: begin
Tx_Data <= 8'b11111111; // 255,0xFF
Write <= 0;
RE <= 0;
Send <=1;
end
ACKSST4: begin
Tx_Data <= 8'b0;
Write <= 0;
RE <= 0;
Send <= 0;
end
SST5: begin
Tx_Data <= 8'b11111111; // 255,0xFF
Write <= 0;
RE <= 0;
Send <=1;
end
ACKSST5: begin
Tx_Data <= 8'b0;
Write <= 0;
RE <= 0;
Send <= 0;
end
SST6: begin
Tx_Data <= 8'b00000001; // 1,0x01
Write <= 0;
RE <= 0;
Send <=1;
end
ACKSST6: begin
Tx_Data <= 8'b0;
Write <= 0;
RE <= 0;
Send <= 0;
end
DT1: begin
Tx_Data <= 8'b00000000; //0
Write <= 0;
RE <= 1;
Send <= 0;
end
DT2: begin
Tx_Data <=
{Data_Out[4],Data_Out[5],Data_Out[6],Data_Out[7],Data_Out[8],Data_Out[9],Data_Out[10],Data_Out[11]};
Write <= 0;
RE <= 0;
Send <= 1;
end
ACKDT2: begin
Tx_Data <= 8'b0;
Write <= 0;
RE <= 0;
Send <= 0;
end
DT3: begin
Tx_Data <=
{Data_Out[20],Data_Out[21],Data_Out[22],Data_Out[23],Data_Out[0],Data_Out[1],Data_Out[2],Data_Out[3]};
Write <= 0;
RE <= 0;
Send <= 1;
end
ACKDT3: begin
Tx_Data <= 8'b0;
Write <= 0;
RE <= 0;
Send <= 0;
end
DT4: begin
Tx_Data <=
{Data_Out[12],Data_Out[13],Data_Out[14],Data_Out[15],Data_Out[16],Data_Out[17],Data_Out[18],Data_Out[19]};
Write <= 0;
RE <= 0;
Send <= 1;
end
ACKDT4: begin
Tx_Data <= 8'b0;
Write <= 0;
RE <= 0;
Send <= 0;
end
RS: begin
Tx_Data <= 8'b01110010; // r,72H, 114b
Write <= 1;
RE <= 0;
Send <= 0;
end
WS: begin
Tx_Data <= 8'b01110111; // w,077H,119b
Write <= 0;
RE <= 0;
Send <= 0;
end
default: begin
Tx_Data <= 8'b01111010; // z,7AH,122b
Write <= 0;
RE <= 0;
Send <= 1;
end
endcase
end
endmodule