Перейти к содержанию

    

Alexey87

Участник
  • Публикаций

    14
  • Зарегистрирован

  • Посещение

Репутация

0 Обычный

Посетители профиля

68 просмотров профиля
  1. Вот на intel взял исходник: /************************************************************************************************************ I2C to GPIO Port expander. Date: December 21, 2006. ************************************************************************************************************/ `timescale 1us/10ns /* Top module */ module I2C_to_GPIO ( sda, sclk, GPIO_input, GPIO_output); inout sda; // Bidirectional SDA input sclk; // Bidirectional SCLK input [7:0] GPIO_input; output [7:0] GPIO_output; parameter slave_address = 7'h0; // can be changed as per the protocol это для адреса slave? parameter n = 8; reg start_stop; // Indicated if the device has detected a start and is busy in some operation reg start, stop; // Goes high temperarily when a start or stop is detectd reg some_other_device; // to reset start_stop, when the adress on the bus is different from the device address; reg repeat_start; // to reset everything if repeat start is detected. reg write_flag; // to set when write oper begins reg reset; // Used to reset the start , stop registers reg sda_out; // To force the SDA output Low. Remains tristated for sending High Logic. reg done; // To Indicate data transfer done reg [3:0]count; // Down Counter ( 7 to 0 + ack bit ) reg [n-1:0] GPIO_output; // parallel store reg [n-1:0] GPIO_input_reg; // Stores the Values at the input pins before sending to master. reg data_or_address; // high for data, low for address reg read_oper, add_is_matching; // high for master read; high for address matching /********************************************************************************************************/ /* Detecting STOP Condition on the SDA Bus */ always @ (posedge sda or posedge reset) if (reset) begin stop <= 0; end else if (sclk) begin stop <= 1; end /* Detecting START Condition on the SDA Bus */ always @ (negedge sda or posedge reset) if (reset) begin start <= 0; end else if (sclk) begin start <= 1; end /* Tracking START_STOP related status of the device */ always @ (negedge sclk) if (start_stop & start) begin repeat_start <= 1; reset <= 1; end else if (start) begin start_stop <= 1; reset <= 1; repeat_start <= 0; end else if (stop) begin start_stop <= 0; reset <= 1; repeat_start <= 0; end else if (some_other_device) begin start_stop <= 0; repeat_start <= 1; end else begin reset <= 0; repeat_start <= 0; end /***********************************************************************************************************/ /* Counting of bits. First eight bits are data and the last one is ack. */ wire sda_is_ack = count[3] & count [2]; // High for ack , count = 1111 /* Down Counter, 1111 is ack */ always @ (negedge sclk) if (start) begin count <= 4'h7; // it would decreae to 7 on the first pos edge of sclk. end else if (start_stop) begin if (sda_is_ack) begin // count is restored to 7 count <= 4'h7; end else begin count <= count - 4'h1; // count is decremented until zero. end end /***********************************************************************************************************/ /* Taking the Inputs from SDA line and Comparing with Address */это чтение? always @(posedge sclk) if (start_stop) begin if (~sda_is_ack) begin if (~data_or_address | repeat_start) begin if (repeat_start) begin add_is_matching <= 1; // high means matching data_or_address <= 0; // default is address some_other_device <= 0; // High means that device address does not match with SDA data write_flag <= 0; done <= 0; // Low means Transfer is pending end if (count == 7 & sda != slave_address[6]) add_is_matching <= 0; if (count == 6 & sda != slave_address[5]) add_is_matching <= 0; if (count == 5 & sda != slave_address[4]) add_is_matching <= 0; if (count == 4 & sda != slave_address[3]) add_is_matching <= 0; if (count == 3 & sda != slave_address[2]) add_is_matching <= 0; if (count == 2 & sda != slave_address[1]) add_is_matching <= 0; if (count == 1 & sda != slave_address[0]) add_is_matching <= 0; if (count == 0 & ~sda )begin read_oper <= 0; data_or_address <= 1; end else if (count == 0) begin read_oper <= 1; data_or_address <= 1; end end else if (~read_oper & ~done) begin if (count == 7) GPIO_output[7] <= sda; if (count == 6) GPIO_output[6] <= sda; if (count == 5) GPIO_output[5] <= sda; if (count == 4) GPIO_output[4] <= sda; if (count == 3) GPIO_output[3] <= sda; if (count == 2) GPIO_output[2] <= sda; if (count == 1) GPIO_output[1] <= sda; if (count == 0) begin GPIO_output[0] <= sda; done <= 1; end end else begin if (count == 0) done <= 1; end end else begin if (add_is_matching) begin if (read_oper) write_flag <= 1; end else begin data_or_address <= 0; some_other_device <= 1; end end end else begin add_is_matching <= 1; // high means matching data_or_address <= 0; // default is address some_other_device <= 0; write_flag <= 0; done <= 0; end /***********************************************************************************************************/ /* Writing ACK and DATA on the SDA Line*/ wire ack_flag = (count[3]|count[2]|count[1]|count[0]); //becomes low when count is 0 always@(negedge sclk) if (start_stop) begin if (~ack_flag) begin if ( add_is_matching & ~write_flag)begin sda_out <= 1'b0; end else begin sda_out <= 1'bz; end if (read_oper & ~done) GPIO_input_reg <= GPIO_input; end else if (read_oper & data_or_address & ~done) begin if (ack_flag) begin if (~GPIO_input_reg[7]) begin sda_out <= 1'b0; end else begin sda_out <= 1'bz; end GPIO_input_reg <= GPIO_input_reg << 1; end end else begin sda_out <= 1'bz; end end wire sda; assign sda = sda_out; endmodule ................................................................... как с помощью этого кода можно записывать (адрес slave 7'h50) и почему здесь нет тактовой частоты?
  2. подключил sda на pin_2, scl на pin_4, clk pin_12, не пишет... адрес (slave 24c04) 0x01010000, что неправильно в коде? прикладываю лог с Logic 1.2.18 analyzer. I2C_Logic.logicdata Logic_I2C.zip
  3. Спасибо, обязательно прочту. Также приобрёл книги: В.В. Соловьёв "Основы проектирования цифровой аппаратуры Verilog" 2017, Заиналабедин Наваби "Проектирование встраиваемых систем".
  4. если описать на си или на асме, то нормально и понятно (для меня будет), а на verilog'e не совсем укладывается в голове (это ведь проектирование устр-ва).
  5. В теории сложного вроде ничего нет. а с этим посложнее...
  6. Добрый день! Пытаюсь записать и прочитать в микросхему 24с04 (память) при помощи этого кода: module Master( input wire clk, input wire reset, output reg i2c_sda, output wire i2c_scl ); //goal is to write to device address 0x50, 0xaa localparam STATE_IDLE = 0; localparam STATE_START = 1; localparam STATE_ADDR = 2; localparam STATE_RW = 3; localparam STATE_WACK = 4; localparam STATE_DATA = 5; localparam STATE_STOP = 6; localparam STATE_WACK2 = 7; reg [7:0] state; reg [6:0] addr; reg [7:0] data; reg [7:0] count; reg i2c_scl_enable = 0; assign i2c_scl = (i2c_scl_enable == 0) ? 1 : clk; always @(negedge clk) begin if (reset == 1) begin i2c_scl_enable = 0; end else begin if ((state == STATE_IDLE) || (state == STATE_START) || (state == STATE_STOP)) begin i2c_scl_enable = 0; end else begin i2c_scl_enable = 1; end end end always @(posedge clk) begin if (reset == 1) begin state <= 0; i2c_sda <= 1; //i2c_scl <= 1; addr <= 7'h50; count <= 8'd0; end else begin case(state) STATE_IDLE: begin // idle i2c_sda <= 1; state <= STATE_START; end STATE_START: begin // start i2c_sda <= 1; state <= STATE_ADDR; count <= 6; end // end state start STATE_ADDR: begin // msb address bit i2c_sda <= addr[count]; if (count == 0) state <= STATE_RW; else count <= count - 1; end // end state addr STATE_RW: begin i2c_sda <= 1; state <= STATE_WACK; end // end state rw STATE_WACK: begin state <= STATE_DATA; count <= 7; end // end state wack STATE_DATA: begin i2c_sda <= data[count]; if (count == 0) state <= STATE_WACK; else count <= count -1; end // end state data STATE_WACK2: begin state <= STATE_STOP; end // state wack2 STATE_STOP: begin i2c_sda <= 1; state <= STATE_IDLE; end // state stop endcase end end endmodule код взят из этого I2C - Bus Master - Step 1 (and step 2) видео. Посмотрите пожалуйста, рабочий ли код?
  7. Ещё раз благодарю Вас, я пока только (как Вы поняли) начинаю изучать.
  8. Да всё отлично, благодарю Вас. поясните пожалуйста эту "конструкцию": это эквивалент?: time_cnt <= time_pulse ? 0 : (time_pulse + 1);
  9. max II epm240T100C5 (на плате генератор на 50 мгц), clk на 12 pin
  10. Спасибо Rob, вот: module Indicator ( output reg [7:0]segments, input clk, input reset ); localparam MAX_DIGIT_N = 10 ; localparam CNT_DIV = 100_000 ; localparam CNT_WH = $clog2(CNT_DIV); reg [$clog2(MAX_DIGIT_N)-1:0] digit_cnt ; reg [ CNT_WH-1:0] time_cnt ; reg time_pulse; always @(posedge clk) begin case(digit_cnt) 4'd1:segments = 8'b11101011; 4'd2:segments = 8'b10001100; 4'd3:segments = 8'b10001001; 4'd4:segments = 8'b00101011; 4'd5:segments = 8'b00011001; 4'd6:segments = 8'b00011000; 4'd7:segments = 8'b11001011; 4'd8:segments = 8'b00001000; 4'd9:segments = 8'b00001001; 4'd10:segments = 8'b01001000; default: segments = 8'b11111111; endcase end always @(posedge clk) if (reset)// у меня сброса нет, а если я выставляю 0, то высвечивается 8, а так ничего не светится begin digit_cnt <= 0; // time_pulse <= 0; // time_cn?t <= 0; {time_pulse, time_cnt} <= (1<<CNT_WH)-CNT_DIV+1; end else begin // time_cnt <= time_cnt + 1; // time_pulse <= (time_cnt==(CNT_DIV-2)); // time_cnt <= time_pulse ? 0 : (time_pulse + 1); {time_pulse, time_cnt} <= {time_pulse, time_cnt} + 1; if (time_pulse) begin {time_pulse, time_cnt} <= (1<<CNT_WH)-CNT_DIV+1; digit_cnt <= digit_cnt + 1; if (digit_cnt==MAX_DIGIT_N) begin digit_cnt <= 0; end end end endmodule не (работает) получается...
  11. Это я и хотел бы сделать, но как описать на верилоге? наверное как-то так: always @(posedge clk) begin if (count >= 100000000) begin count = 0; code = code + 1; end if (code > 9) code = 4'd1111;//погасить end но правильно ли?
  12. Добрый вечер! Вопрос по коду: module Indicator_Sum_Count( output reg [23:0]segments, input clk ); reg [3:0]code; reg [31:0] count; always @(posedge clk) begin case(code) 4'd1:segments = 8'b11101011;//1 4'd2:segments = 8'b10001100;//2 4'd3:segments = 8'b10001001;//3 4'd4:segments = 8'b00101011;//4 4'd5:segments = 8'b00011001;//5 4'd6:segments = 8'b00011000;//6 4'd7:segments = 8'b11001011;//7 4'd8:segments = 8'b00001000;//8 4'd9:segments = 8'b00001001;//9 4'd10:segments = 8'b01001000;//0 default: segments = 8'b11111111; endcase end always @(posedge clk) begin if (count > 100000000) begin code = 4'd11; count = 0; end else if (count > 90000000 & count < 100000000) code = 4'd1; if (count > 80000000 & count < 90000000) code <= 4'd2; if (count > 70000000 & count < 80000000) code <= 4'd3; if (count > 60000000 & count < 70000000) code <= 4'd4; if (count > 50000000 & count < 60000000) code <= 4'd5; if (count > 40000000 & count < 50000000) code <= 4'd6; if (count > 30000000 & count < 40000000) code <= 4'd7; if (count > 20000000 & count < 30000000) code <= 4'd8; if (count > 1 & count < 20000000) code <= 4'd9; count <= count + 1; end endmodule Пытаюсь реализовать индикацию от 0 до 9 с задержкой при помощи счётчика, как правильно описать?