Бьюсь над модулем конвертера RS232 -> внутренняя шина FPGA. Идея простая: по RS232 приходит $WR(ADDR)(DATA) - проводим цикл записи на шине. $RD(ADDR) - цикл чтения. Интерфейс с внутренней шиной пока опустил, т.к. не работает приём команды.
Проблема: при симуляции в Modelsim всё работает как должно. В железе (Altera FLEX EPF10K100, 40 МГц) не переключается состояние FSM, стоит всегда в 0 (CONV_IDLE). На вентильном уровне решил пока не моделировать, - думаю, проблема в неточном описании логики.
Модуль rs232_rx работает (выводил все сигналы наружу и щупал). Взят с fpga4fun.com, работает на 9600 бод.
Код модуля:
CODE
`timescale 1 ns / 10 ps
`define CONV_IDLE 'd0
`define CONV_WRITE 'd1
`define CONV_READ 'd2
module i41_rs232 (
input clk,
/* RS-232 */
input rs232_rx,
output rs232_tx
);
/* RS-232 */
wire rs232_rx_ready;
wire rs232_rx_idle;
wire [7:0] rs232_rx_data;
rs232_rx u1_rs232_rx (
.clk(clk),
.RxD(rs232_rx),
.RxD_data_ready(rs232_rx_ready),
.RxD_data(rs232_rx_data),
.RxD_idle(rs232_rx_idle)
);
reg rs232_tx_start;
reg [7:0] rs232_tx_data;
wire rs232_tx_busy;
rs232_tx u2_rs232_tx (
.clk(clk),
.TxD_start(rs232_tx_start),
.TxD_data(rs232_tx_data),
.TxD(rs232_tx),
.TxD_busy(rs232_tx_busy)
);
/* Сдвиговый регистр для команды от RS232 */
reg [7:0] rs232_rx_data_buf [5:0];
always @(posedge rs232_rx_ready) begin
rs232_rx_data_buf[0] <= rs232_rx_data_buf[1];
rs232_rx_data_buf[1] <= rs232_rx_data_buf[2];
rs232_rx_data_buf[2] <= rs232_rx_data_buf[3];
rs232_rx_data_buf[3] <= rs232_rx_data_buf[4];
rs232_rx_data_buf[4] <= rs232_rx_data_buf[5];
rs232_rx_data_buf[5] <= rs232_rx_data;
end
/* FSM */
reg [4:0] conv_state, conv_state_next;
always @ (posedge clk) begin
case (conv_state)
`CONV_IDLE: case ({rs232_rx_data_buf[0], rs232_rx_data_buf[1], rs232_rx_data_buf[2]})
"$WR": conv_state_next = `CONV_WRITE;
"$RD": conv_state_next = `CONV_READ;
default: conv_state_next = `CONV_IDLE;
endcase
/* Состояния чтения и записи пока оставил без переходов: */
`CONV_WRITE: ;
`CONV_READ: ;
default: conv_state_next = `CONV_IDLE;
endcase
end
initial begin
rs232_rx_data_buf[0] = 0;
rs232_rx_data_buf[1] = 0;
rs232_rx_data_buf[2] = 0;
rs232_rx_data_buf[3] = 0;
rs232_rx_data_buf[4] = 0;
rs232_rx_data_buf[5] = 0;
conv_state = 0;
conv_state_next = 0;
rs232_tx_start = 0;
rs232_tx_data = 0;
end
endmodule
`define CONV_IDLE 'd0
`define CONV_WRITE 'd1
`define CONV_READ 'd2
module i41_rs232 (
input clk,
/* RS-232 */
input rs232_rx,
output rs232_tx
);
/* RS-232 */
wire rs232_rx_ready;
wire rs232_rx_idle;
wire [7:0] rs232_rx_data;
rs232_rx u1_rs232_rx (
.clk(clk),
.RxD(rs232_rx),
.RxD_data_ready(rs232_rx_ready),
.RxD_data(rs232_rx_data),
.RxD_idle(rs232_rx_idle)
);
reg rs232_tx_start;
reg [7:0] rs232_tx_data;
wire rs232_tx_busy;
rs232_tx u2_rs232_tx (
.clk(clk),
.TxD_start(rs232_tx_start),
.TxD_data(rs232_tx_data),
.TxD(rs232_tx),
.TxD_busy(rs232_tx_busy)
);
/* Сдвиговый регистр для команды от RS232 */
reg [7:0] rs232_rx_data_buf [5:0];
always @(posedge rs232_rx_ready) begin
rs232_rx_data_buf[0] <= rs232_rx_data_buf[1];
rs232_rx_data_buf[1] <= rs232_rx_data_buf[2];
rs232_rx_data_buf[2] <= rs232_rx_data_buf[3];
rs232_rx_data_buf[3] <= rs232_rx_data_buf[4];
rs232_rx_data_buf[4] <= rs232_rx_data_buf[5];
rs232_rx_data_buf[5] <= rs232_rx_data;
end
/* FSM */
reg [4:0] conv_state, conv_state_next;
always @ (posedge clk) begin
case (conv_state)
`CONV_IDLE: case ({rs232_rx_data_buf[0], rs232_rx_data_buf[1], rs232_rx_data_buf[2]})
"$WR": conv_state_next = `CONV_WRITE;
"$RD": conv_state_next = `CONV_READ;
default: conv_state_next = `CONV_IDLE;
endcase
/* Состояния чтения и записи пока оставил без переходов: */
`CONV_WRITE: ;
`CONV_READ: ;
default: conv_state_next = `CONV_IDLE;
endcase
end
initial begin
rs232_rx_data_buf[0] = 0;
rs232_rx_data_buf[1] = 0;
rs232_rx_data_buf[2] = 0;
rs232_rx_data_buf[3] = 0;
rs232_rx_data_buf[4] = 0;
rs232_rx_data_buf[5] = 0;
conv_state = 0;
conv_state_next = 0;
rs232_tx_start = 0;
rs232_tx_data = 0;
end
endmodule
Заранее признателен за ответы.