jenya7 0 4 декабря, 2023 Опубликовано 4 декабря, 2023 · Жалоба Есть такой процесс SPI_DATA <= buf_in when s_rd_nwr = '1' else "ZZZZ"; process(SPI_CLK) variable clk_count : integer range 0 to 2 := 0; begin if (SPI_CS = '0') then if (s_ready_read = '1') then if (rising_edge(SPI_CLK)) then case clk_count is when 0 => buf_in <= DATA_IN(7 downto 4); clk_count := 1; when 1 => buf_in <= DATA_IN(3 downto 0); clk_count := 0; when others => end case; end if; end if; else buf_in <= DATA_IN(7 downto 4); clk_count := 0; end if; end process; смотрим сигналы когда DATA_IN = 0x12 - buf_in = 0x1 0x2 всё правильно но когда DATA_IN = 0x34 - buf_in = 0x1 0x4 - а должно быть 0x3 0x4 Что не так? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Maverick_ 15 4 декабря, 2023 Опубликовано 4 декабря, 2023 · Жалоба я бы применял сигналы, без variable clk_count : integer range 0 to 2 := 0; как формируется подача DATA_IN ??? я не вижу однобитного сигнала запроса данных DATA_IN Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Flip-fl0p 4 4 декабря, 2023 Опубликовано 4 декабря, 2023 · Жалоба Весь код неправильный. На ПЛИС так писать нельзя. За такой код бить по рукам нужно. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jenya7 0 4 декабря, 2023 Опубликовано 4 декабря, 2023 (изменено) · Жалоба On 12/4/2023 at 9:50 AM, Maverick_ said: я бы применял сигналы, без variable clk_count : integer range 0 to 2 := 0; как формируется подача DATA_IN ??? я не вижу однобитного сигнала запроса данных DATA_IN у меня во всех проектах множество локальных variable в процесах. всегда четко работало. DATA_IN : in std_logic_vector(7 downto 0); - сигнал в top entity. он уже выставлен (как видно из сигнал тап). он соединен с сигналом из другого модуля. port map DATA_IN => s_spi_tx_data, On 12/4/2023 at 9:54 AM, Flip-fl0p said: Весь код неправильный. На ПЛИС так писать нельзя. За такой код бить по рукам нужно. а что не так с кодом? Изменено 4 декабря, 2023 пользователем jenya7 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Zversky 18 4 декабря, 2023 Опубликовано 4 декабря, 2023 · Жалоба Какое у вас дерево тактовых частот? 1 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jenya7 0 4 декабря, 2023 Опубликовано 4 декабря, 2023 · Жалоба On 12/4/2023 at 10:10 AM, Zversky said: Какое у вас дерево тактовых частот? top entity получает с PLL 120 мега. но в данном процессе я сижу на SPI Clock. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Maverick_ 15 4 декабря, 2023 Опубликовано 4 декабря, 2023 · Жалоба еще раз как другой модуль узнает что надо выставить новые даные DATA_IN ??? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jenya7 0 4 декабря, 2023 Опубликовано 4 декабря, 2023 (изменено) · Жалоба On 12/4/2023 at 10:22 AM, Maverick_ said: еще раз как другой модуль узнает что надо выставить новые даные DATA_IN ??? есть процесс в другом модуле process(CLK) begin if (rising_edge(CLK)) then clk1 <= SPI_CLK; clk2 <= clk1; end if; end process; clk3 <= not clk2 and clk1; SPI_TX_DATA <= sspi_data_out when s_out_select = '0' else data_1553_out; ------------ IN PROCESS ------- when ST_READ_1 => s_out_select <= '1' Bustate <= ST_READ_2; when ST_READ_2 => debug <= X"12"; if (clk3 = '1') then clk2_count := clk2_count + 1; end if; case clk2_count is when 0 => data_1553_out <= DOUT(7 downto 0); when 1 => data_1553_out <= DOUT(7 downto 0); when 2 => data_1553_out <= DOUT(7 downto 0); when 3 => data_1553_out <= DOUT(15 downto 8); when 4 => data_1553_out <= DOUT(15 downto 8); clk2_count := 0; Bustate <= ST_READ_3; when others => end case; а SPI_TX_DATA соединен с DATA_IN честно говоря взыл бы готовый QUAD SPI и не парился ни минуты. забавно что нигде не нашел готовый модуль. Изменено 4 декабря, 2023 пользователем jenya7 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Zversky 18 4 декабря, 2023 Опубликовано 4 декабря, 2023 · Жалоба 1 час назад, jenya7 сказал: top entity получает с PLL 120 мега. но в данном процессе я сижу на SPI Clock. а всё посадить на PLL 120 мега, а играться ena для всех триггеров? Например, так: Спойлер // URL : https://github.com/hell03end/verilog-uart /* * Baud rate generator to divide {CLOCK_RATE} (internal board clock) into * a rx/tx {BAUD_RATE} pair with rx oversamples by 16x. # clk period = 10,000 ns, clk freq = 100,000.000 MHz # rxClk period = 6,520.000 us, rxClk freq = 153,000 kHz # txClk period = 104,180.000 us, txClk freq = 009,000 kHz */ module UART_BRG # ( parameter CLOCK_RATE = 100_000_000 , // board internal clock (def == 100MHz) parameter BAUD_RATE = 9_600 )( input logic Clk , // Clock 100 MHz output logic RxClkEna , // Rx clock enable output logic TxClkEna // Tx clock enable ) ; localparam MAX_RATE_RX = CLOCK_RATE / ( 2 * BAUD_RATE * 16 ) ; // 16x oversample localparam MAX_RATE_TX = CLOCK_RATE / ( 2 * BAUD_RATE ) + 7 ; localparam RX_CNT_WIDTH = $clog2 ( MAX_RATE_RX ) ; localparam TX_CNT_WIDTH = $clog2 ( MAX_RATE_TX ) ; `ifdef MODEL_TECH initial begin $printtimescale ( UART_BRG ) ; $display ( "MAX_RATE_RX = d%0d" , MAX_RATE_RX ) ; $display ( "MAX_RATE_TX = d%0d" , MAX_RATE_TX ) ; $display ( "RX_CNT_WIDTH = d%0d" , RX_CNT_WIDTH ) ; $display ( "TX_CNT_WIDTH = d%0d" , TX_CNT_WIDTH ) ; end `endif logic [ RX_CNT_WIDTH - 1 : 0 ] RxCnt = '0 ; logic [ TX_CNT_WIDTH - 1 : 0 ] TxCnt = '0 ; logic RxCntRst ; assign RxCntRst = RxCnt == MAX_RATE_RX ; logic TxCntRst ; assign TxCntRst = TxCnt == MAX_RATE_TX ; always_ff @ ( posedge Clk ) begin RxCnt <= RxCntRst ? '0 : RxCnt + 1'b1 ; TxCnt <= TxCntRst ? '0 : TxCnt + 1'b1 ; RxClkEna <= RxCntRst ; TxClkEna <= TxCntRst ; end endmodule : UART_BRG и потом Спойлер // URL : https://github.com/hell03end/verilog-uart `include "UART_RX.svh" /* * 8-logic UART Receiver. * Able to receive 8 bits of serial data, one start logic, one stop logic. * When receive is complete {done} is driven high for one clock cycle. * Output data should be taken away by a few clocks or can be lost. * When receive is in progress {busy} is driven high. * Clock should be decreased to baud rate. */ module UART_RX ( input logic Clk , // Input - Clock 100 MHz input logic RxClkEna , // Input - Rx clock enable input logic RxEn , // Input - Rx enable input logic RxIn , // Input - Rx input output logic `UART_BIT_RNG RxData , // Output - Received data output logic RxDone , // Output - Rx end of transaction output logic RxBusy , // Output - Rx transaction is in progress output logic RxError // Output - Rx Error while receiving data ) ; typedef enum logic `UART_RX_STATES_RNG { IDLE = `UART_RX_STATES_DIM'b00 , START_BIT = `UART_RX_STATES_DIM'b01 , DATA_BITS = `UART_RX_STATES_DIM'b10 , STOP_BIT = `UART_RX_STATES_DIM'b11 } uart_rx_fsm_states_t ; uart_rx_fsm_states_t uart_rx_fsm_state = IDLE ; logic `UART_RX_SHFT_REG_RNG RXShReg = '1 ; // shift reg for input signal state logic `UART_RX_CLK_CNT_RNG ClkCnt = '0 ; // count clocks for 16x oversample logic `UART_BIT_RNG RxTemp = '0 ; // temporary storage for input data logic `UART_BIT_IDX_RNG BitIdx = '0 ; // for 8-logic data logic ClkCntMax ; // fired when ClkCnt == '1 logic RXShOnes ; logic RXShZero ; logic MidleOfTheBitInterval ; assign ClkCntMax = &ClkCnt ; // UART baud rate = 19200 // Sample data period = 1 / 19200 = 52 us // Sample data period / RxClkEna period = 52 us / 3,26 us = 16 // Clk period = 10,000 ns, Clk freq = 100,000 MHz // RxClkEna period = 3,260 us, RxClkEna freq = 306,000 kHz // ClkCntMax period = 3,260 us assign RXShOnes = &RXShReg ; assign RXShZero = !(|RXShOnes) ; assign MidleOfTheBitInterval = ClkCnt == `UART_RX_CLK_CNT_HALF_RNG_VAL ; `ifdef MODEL_TECH initial $printtimescale ( UART_RX ) ; `endif always_ff @ ( posedge Clk ) begin if ( RxClkEna ) begin RXShReg = { RXShReg [ 0 ] , RxIn } ; case ( uart_rx_fsm_state ) IDLE : begin RxData <= '0 ; RxDone <= '0 ; RxBusy <= '0 ; BitIdx <= '0 ; ClkCnt <= '0 ; RxTemp <= '0 ; RxError <= '0 ; uart_rx_fsm_state <= RXShZero ? START_BIT : IDLE ; end START_BIT : begin RxDone <= '0 ; if ( ClkCntMax ) begin // RxData <= '0 ; BitIdx <= '0 ; ClkCnt <= '0 ; RxTemp <= '0 ; RxBusy <= '1 ; RxError <= '0 ; uart_rx_fsm_state <= DATA_BITS ; end else if ( ! RXShOnes | ( |ClkCnt ) ) begin // Check logic to make sure it's still low if ( RXShOnes ) begin RxError <= '1 ; uart_rx_fsm_state <= IDLE ; end ClkCnt <= ClkCnt + 1'b1 ; end end // Wait 8 full cycles to receive serial data DATA_BITS : begin RxTemp [ BitIdx ] <= MidleOfTheBitInterval ? RXShReg [ 0 ] : RxTemp [ BitIdx ] ; if ( ClkCntMax ) begin // save one logic of received data ClkCnt <= '0 ; if ( &BitIdx ) begin BitIdx <= '0 ; uart_rx_fsm_state <= STOP_BIT ; end else BitIdx <= BitIdx + 1'b1 ; end else ClkCnt <= ClkCnt + 1'b1 ; end /* * Baud clock may not be running at exactly the same rate as the * transmitter. Next start logic is allowed on at least half of stop logic. */ STOP_BIT : if ( ClkCntMax || ( ( ClkCnt >= `UART_RX_CLK_CNT_HALF_RNG_VAL ) && RXShZero ) ) begin RxDone <= '1 ; RxBusy <= '0 ; RxData <= RxTemp ; ClkCnt <= '0 ; uart_rx_fsm_state <= START_BIT ; end else begin ClkCnt <= ClkCnt + 1'b1 ; // Check logic to make sure it's still high if ( RXShZero & MidleOfTheBitInterval ) begin RxError <= '1 ; uart_rx_fsm_state <= IDLE ; end end default : uart_rx_fsm_state <= IDLE ; endcase end end endmodule : UART_RX // RXShReg [ 1 ] , RXShReg [ 0 ] -> |RXShReg -> ! |RXShReg // 1'b0 1'b0 1'b0 -> 1'b1 // end of file UART_RX.sv Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jenya7 0 4 декабря, 2023 Опубликовано 4 декабря, 2023 · Жалоба On 12/4/2023 at 11:25 AM, Zversky said: а всё посадить на PLL 120 мега, а играться ena для всех триггеров? Например, так: Reveal hidden contents // URL : https://github.com/hell03end/verilog-uart /* * Baud rate generator to divide {CLOCK_RATE} (internal board clock) into * a rx/tx {BAUD_RATE} pair with rx oversamples by 16x. # clk period = 10,000 ns, clk freq = 100,000.000 MHz # rxClk period = 6,520.000 us, rxClk freq = 153,000 kHz # txClk period = 104,180.000 us, txClk freq = 009,000 kHz */ module UART_BRG # ( parameter CLOCK_RATE = 100_000_000 , // board internal clock (def == 100MHz) parameter BAUD_RATE = 9_600 )( input logic Clk , // Clock 100 MHz output logic RxClkEna , // Rx clock enable output logic TxClkEna // Tx clock enable ) ; localparam MAX_RATE_RX = CLOCK_RATE / ( 2 * BAUD_RATE * 16 ) ; // 16x oversample localparam MAX_RATE_TX = CLOCK_RATE / ( 2 * BAUD_RATE ) + 7 ; localparam RX_CNT_WIDTH = $clog2 ( MAX_RATE_RX ) ; localparam TX_CNT_WIDTH = $clog2 ( MAX_RATE_TX ) ; `ifdef MODEL_TECH initial begin $printtimescale ( UART_BRG ) ; $display ( "MAX_RATE_RX = d%0d" , MAX_RATE_RX ) ; $display ( "MAX_RATE_TX = d%0d" , MAX_RATE_TX ) ; $display ( "RX_CNT_WIDTH = d%0d" , RX_CNT_WIDTH ) ; $display ( "TX_CNT_WIDTH = d%0d" , TX_CNT_WIDTH ) ; end `endif logic [ RX_CNT_WIDTH - 1 : 0 ] RxCnt = '0 ; logic [ TX_CNT_WIDTH - 1 : 0 ] TxCnt = '0 ; logic RxCntRst ; assign RxCntRst = RxCnt == MAX_RATE_RX ; logic TxCntRst ; assign TxCntRst = TxCnt == MAX_RATE_TX ; always_ff @ ( posedge Clk ) begin RxCnt <= RxCntRst ? '0 : RxCnt + 1'b1 ; TxCnt <= TxCntRst ? '0 : TxCnt + 1'b1 ; RxClkEna <= RxCntRst ; TxClkEna <= TxCntRst ; end endmodule : UART_BRG и потом Reveal hidden contents // URL : https://github.com/hell03end/verilog-uart `include "UART_RX.svh" /* * 8-logic UART Receiver. * Able to receive 8 bits of serial data, one start logic, one stop logic. * When receive is complete {done} is driven high for one clock cycle. * Output data should be taken away by a few clocks or can be lost. * When receive is in progress {busy} is driven high. * Clock should be decreased to baud rate. */ module UART_RX ( input logic Clk , // Input - Clock 100 MHz input logic RxClkEna , // Input - Rx clock enable input logic RxEn , // Input - Rx enable input logic RxIn , // Input - Rx input output logic `UART_BIT_RNG RxData , // Output - Received data output logic RxDone , // Output - Rx end of transaction output logic RxBusy , // Output - Rx transaction is in progress output logic RxError // Output - Rx Error while receiving data ) ; typedef enum logic `UART_RX_STATES_RNG { IDLE = `UART_RX_STATES_DIM'b00 , START_BIT = `UART_RX_STATES_DIM'b01 , DATA_BITS = `UART_RX_STATES_DIM'b10 , STOP_BIT = `UART_RX_STATES_DIM'b11 } uart_rx_fsm_states_t ; uart_rx_fsm_states_t uart_rx_fsm_state = IDLE ; logic `UART_RX_SHFT_REG_RNG RXShReg = '1 ; // shift reg for input signal state logic `UART_RX_CLK_CNT_RNG ClkCnt = '0 ; // count clocks for 16x oversample logic `UART_BIT_RNG RxTemp = '0 ; // temporary storage for input data logic `UART_BIT_IDX_RNG BitIdx = '0 ; // for 8-logic data logic ClkCntMax ; // fired when ClkCnt == '1 logic RXShOnes ; logic RXShZero ; logic MidleOfTheBitInterval ; assign ClkCntMax = &ClkCnt ; // UART baud rate = 19200 // Sample data period = 1 / 19200 = 52 us // Sample data period / RxClkEna period = 52 us / 3,26 us = 16 // Clk period = 10,000 ns, Clk freq = 100,000 MHz // RxClkEna period = 3,260 us, RxClkEna freq = 306,000 kHz // ClkCntMax period = 3,260 us assign RXShOnes = &RXShReg ; assign RXShZero = !(|RXShOnes) ; assign MidleOfTheBitInterval = ClkCnt == `UART_RX_CLK_CNT_HALF_RNG_VAL ; `ifdef MODEL_TECH initial $printtimescale ( UART_RX ) ; `endif always_ff @ ( posedge Clk ) begin if ( RxClkEna ) begin RXShReg = { RXShReg [ 0 ] , RxIn } ; case ( uart_rx_fsm_state ) IDLE : begin RxData <= '0 ; RxDone <= '0 ; RxBusy <= '0 ; BitIdx <= '0 ; ClkCnt <= '0 ; RxTemp <= '0 ; RxError <= '0 ; uart_rx_fsm_state <= RXShZero ? START_BIT : IDLE ; end START_BIT : begin RxDone <= '0 ; if ( ClkCntMax ) begin // RxData <= '0 ; BitIdx <= '0 ; ClkCnt <= '0 ; RxTemp <= '0 ; RxBusy <= '1 ; RxError <= '0 ; uart_rx_fsm_state <= DATA_BITS ; end else if ( ! RXShOnes | ( |ClkCnt ) ) begin // Check logic to make sure it's still low if ( RXShOnes ) begin RxError <= '1 ; uart_rx_fsm_state <= IDLE ; end ClkCnt <= ClkCnt + 1'b1 ; end end // Wait 8 full cycles to receive serial data DATA_BITS : begin RxTemp [ BitIdx ] <= MidleOfTheBitInterval ? RXShReg [ 0 ] : RxTemp [ BitIdx ] ; if ( ClkCntMax ) begin // save one logic of received data ClkCnt <= '0 ; if ( &BitIdx ) begin BitIdx <= '0 ; uart_rx_fsm_state <= STOP_BIT ; end else BitIdx <= BitIdx + 1'b1 ; end else ClkCnt <= ClkCnt + 1'b1 ; end /* * Baud clock may not be running at exactly the same rate as the * transmitter. Next start logic is allowed on at least half of stop logic. */ STOP_BIT : if ( ClkCntMax || ( ( ClkCnt >= `UART_RX_CLK_CNT_HALF_RNG_VAL ) && RXShZero ) ) begin RxDone <= '1 ; RxBusy <= '0 ; RxData <= RxTemp ; ClkCnt <= '0 ; uart_rx_fsm_state <= START_BIT ; end else begin ClkCnt <= ClkCnt + 1'b1 ; // Check logic to make sure it's still high if ( RXShZero & MidleOfTheBitInterval ) begin RxError <= '1 ; uart_rx_fsm_state <= IDLE ; end end default : uart_rx_fsm_state <= IDLE ; endcase end end endmodule : UART_RX // RXShReg [ 1 ] , RXShReg [ 0 ] -> |RXShReg -> ! |RXShReg // 1'b0 1'b0 1'b0 -> 1'b1 // end of file UART_RX.sv изначально я работал по системному клоку process(CLK) variable clk_count : integer range 0 to 2 := 0; begin if (SPI_CS = '0') then if (s_ready_read = '1') then if (rising_edge(CLK)) then if (clk3 = '1') then case clk_count is when 0 => buf_in <= DATA_IN(7 downto 4); clk_count := 1; when 1 => buf_in <= DATA_IN(3 downto 0); clk_count := 0; when others => end case; end if; end if; end if; else buf_in <= DATA_IN(7 downto 4); clk_count := 0; end if; end process; та же херня. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
andrew_b 16 4 декабря, 2023 Опубликовано 4 декабря, 2023 · Жалоба 1 hour ago, jenya7 said: if (SPI_CS = '0') then if (s_ready_read = '1') then if (rising_edge(CLK)) then Ну вы первый год замужем, что ли? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Zversky 18 4 декабря, 2023 Опубликовано 4 декабря, 2023 · Жалоба 2 часа назад, jenya7 сказал: честно говоря взыл бы готовый QUAD SPI и не парился ни минуты. честно говоря, ищите. разбираться в ваших кусках кода, которые вы ещё и словами потом описываете... посмотрите в скрепке: там есть всё, чтобы взять и промоделировать (ну, подставивив свой путь к среде моделирования, конечно). Да: и управление самой средой тоже обязательно (TCL). Всё есть в скрепке. UART_BRG.ZIP Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jenya7 0 4 декабря, 2023 Опубликовано 4 декабря, 2023 · Жалоба On 12/4/2023 at 1:26 PM, andrew_b said: Ну вы первый год замужем, что ли? упс. мой фак. исправил но не помогло. On 12/4/2023 at 1:29 PM, Zversky said: честно говоря, ищите. разбираться в ваших кусках кода, которые вы ещё и словами потом описываете... посмотрите в скрепке: там есть всё, чтобы взять и промоделировать (ну, подставивив свой путь к среде моделирования, конечно). Да: и управление самой средой тоже обязательно (TCL). Всё есть в скрепке. UART_BRG.ZIP 13.01 kB · 2 downloads ЮАРТ и у меня работает чики пуки. с ним нет проблем. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Zversky 18 4 декабря, 2023 Опубликовано 4 декабря, 2023 · Жалоба 1 час назад, jenya7 сказал: ЮАРТ и у меня работает чики пуки. с ним нет проблем. Хочется процитировать Юрия нашего Шевчука: "Дружок, я всё знаю, Я сам, брат, из этих, Но в песне не понял ты, увы, ничего" (с) Мальчики-мажоры Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
sazh 8 4 декабря, 2023 Опубликовано 4 декабря, 2023 · Жалоба 10 часов назад, jenya7 сказал: честно говоря взял бы готовый QUAD SPI и не парился ни минуты. забавно что нигде не нашел готовый модуль. Просто скажите, что с чем соединяете. Может кто и поможет. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться