Jump to content

    

michael.sysoev

Участник
  • Content Count

    8
  • Joined

  • Last visited

Community Reputation

0 Обычный
  1. Спасибо всем ответившим! Топик, как-будто, можно закрывать.
  2. На данном этапе арбитраж между внутренними потребителями не нужен (пока они жестко разнесены по времени). Арбитраж с МК по задумке должна обеспечивать конструкция вида: always @(i_add_uc or i_add0 or i_add1 or i_add2 or r_bus_mux_sel) //мультиплексор шины адреса begin casex (r_bus_mux_sel)//выбираем 4'd1: r_a = i_add0;//шину адреса внутреннего потребителя 0 4'd2: r_a = i_add1 + lp_TX1BUF_ADD_OFFSET;//шину адреса внутреннего потребителя 1 со смещением 4'd4: r_a = i_add2 + lp_RX1BUF_ADD_OFFSET;//шину адреса внутреннего потребителя 2 со смещением 4'b1xxx: r_a = i_add_uc;//шину МК default: r_a = 12'd4095;//по умолчанию максимальное значение endcase end приоритет у МК. Синхронизатор прикручиваю. Синхронизировать рекомендуете все сигналы или достаточно стробы?
  3. Вы оказались совершенно правы, а меня подвела инерция мЫшления. Уж со стороны МК-то я подвоха не ожидал.
  4. К сожалению, полный тестбенч ошибок не выявил. В симуляторе все ходит, как задумано.
  5. Произвожу с МК тест на целостность ОЗУ путем записи 16 байт случайных данных, с последующим вычитыванием и сравнением контрольных сумм - и так по всему объему. Со стороны ПЛИС также при старте делаю запись/чтение, но там тест попроще и не по всему объему. Списки чувствительности поправил, спасибо (лучше не стало).
  6. Извините, не увидел, что именно не указал в списке чувствительности? Как раз с этим и проблема. Процитирую сам себя: "Т.е. если записать МК какие-либо данные в определенный адрес (диапазон адресов), то внутренний читатель вычитывает с этого адреса (адресов) исключительно, то, что туда записывает внутренний писатель. Равно как и МК вычитывает, только то, что сам записал." Известно - перебор, хуже недобора.
  7. Прошу прощения, согласен. Спасибо, что поправили. Попробую еще раз, не знаю, как редактировать собственные сообщения, поэтому - новое. `timescale 1 ps / 1 ps module sram_adapter #(parameter gp_SRAM_D_WIDTH = 8, parameter gp_SRAM_A_WIDTH = 12, parameter gp_SRAM_WORD_SIZE = 1<<gp_SRAM_A_WIDTH) ( input [(gp_SRAM_D_WIDTH-1):0] i_d0, input [(gp_SRAM_D_WIDTH-1):0] i_d1, //шины данных от внутренних писателей/читателей input [(gp_SRAM_A_WIDTH-1):0] i_add0, input[(gp_SRAM_A_WIDTH-1):0] i_add1, input[(gp_SRAM_A_WIDTH-1):0] i_add2,//шины адреса от внутренних писателей/читателей input i_clock,//тактовая input i_add0bus_sel, input i_add1bus_sel, input i_add2bus_sel,//сигналы выбора шины от внутренних писателей/читателей input i_rden0, input i_rden1,//стробы чтения от внутренних писателей/читателей input i_wren0, input i_wren1,//стробы записи от внутренних писателей/читателей input i_noe_uc, input i_nwe_uc, input i_ncs_uc,//стробы чтения - записи - выборки от МК input [(gp_SRAM_A_WIDTH-1):0] i_add_uc,//шина адреса от МК output wire[(gp_SRAM_D_WIDTH-1):0] o_d0,//выходная шина данных для внутренних потребителей output wire [(gp_SRAM_A_WIDTH-1):0] o_add,//выходная шина адреса для внутренних потребителей inout [(gp_SRAM_D_WIDTH-1):0] io_d_uc,//шина данных МК output dbg0,//отладочные output dbg1, output dbg2 ); reg [(gp_SRAM_A_WIDTH-1):0] r_a;//регистр адреса reg[(gp_SRAM_D_WIDTH-1):0] r_d; reg[(gp_SRAM_D_WIDTH-1):0] r_q;//регистры данных входной - выходной assign o_add = r_a; assign o_d0 = r_q; reg [3:0]r_bus_mux_sel;//управляющий сигнал мультиплексоров шин адреса, шин данных, стробов reg r_we, r_oe;//стробы записи - чтения assign dbg0 = (r_oe);//отладочные assign dbg1 = (r_we); assign dbg2 = |r_bus_mux_sel; reg [gp_SRAM_D_WIDTH:0] sram[(gp_SRAM_WORD_SIZE-1):0];//собственно память initial begin r_a = 0; r_q = 0; r_oe = 0; r_we = 0; end always @(negedge i_clock) begin//захват сигналов выбора r_bus_mux_sel[3] <= !i_ncs_uc;//строб МК с инверсией r_bus_mux_sel[0] <= i_add0bus_sel;//строб внутреннего потребителя 0 r_bus_mux_sel[1] <= i_add1bus_sel;//строб внутреннего потребителя 1 r_bus_mux_sel[2] <= i_add2bus_sel;//строб внутреннего потребителя 2 end assign io_d_uc = (r_bus_mux_sel[3] && !i_noe_uc && i_nwe_uc) ? r_q: 8'bz;// Tri-State Buffer control always @(posedge i_clock) begin//обращение к памяти if(r_we) sram[r_a] <= r_d;//запись if(r_oe) r_q <= sram[r_a];//чтение end localparam lp_TX1BUF_ADD_OFFSET = 12'd16, lp_RX1BUF_ADD_OFFSET = 12'd96; always @(i_add_uc or i_add0 or i_add1 or i_add2 or r_bus_mux_sel) begin//мультиплексор шины адреса casex (r_bus_mux_sel)//выбираем 4'd1: r_a = i_add0;//шину адреса внутреннего потребителя 0 4'd2: r_a = i_add1 + lp_TX1BUF_ADD_OFFSET;//шину адреса внутреннего потребителя 1 со смещением 4'd4: r_a = i_add2 + lp_RX1BUF_ADD_OFFSET;//шину адреса внутреннего потребителя 2 со смещением 4'b1xxx: r_a = i_add_uc;//шину МК default: r_a = 12'd4095;//по умолчанию максимальное значение endcase end always @(i_d0 or i_d1 or r_bus_mux_sel) begin//мультиплексор шины данных casex (r_bus_mux_sel)//выбираем 4'd1: r_d = i_d0;//входную шину данных внутреннего потребителя 0 4'd4: r_d = i_d1;//входную шину данных внутреннего потребителя 1 4'b1xxx: r_d = io_d_uc;//входную шину данных МК default: r_d = 0;//по умолчанию 0 endcase end always @(i_wren0 or i_wren1 or i_nwe_uc or r_bus_mux_sel) begin//мультиплексор строба записи casex (r_bus_mux_sel)//выбираем 4'd1: r_we = i_wren0;//строб записи внутреннего потребителя 0 4'd4: r_we = i_wren1;//строб записи внутреннего потребителя 2 4'b1xxx: r_we = !i_nwe_uc;//строб записи МК default: r_we = 0;//по умолчанию неактивен endcase end always @(i_rden0 or i_rden1 or i_noe_uc or r_bus_mux_sel) begin//мультиплексор строба чтения casex (r_bus_mux_sel)//выбираем 4'd1: r_oe = i_rden0;//строб чтения внутреннего потребителя 0 4'd2: r_oe = i_rden1;//строб чтения внутреннего потребителя 1 4'b1xxx: r_oe = (!i_noe_uc && i_nwe_uc);//строб чтения МК default: r_oe = 0;//по умолчанию неактивен endcase end endmodule
  8. Доброго времени! Прошу совета у сообщества. "Сам я в верилог недавно". Пытаюсь таким образом: `timescale 1 ps / 1 ps module sram_adapter #(parameter gp_SRAM_D_WIDTH = 8, parameter gp_SRAM_A_WIDTH = 12, parameter gp_SRAM_WORD_SIZE = 1<<gp_SRAM_A_WIDTH) ( input [(gp_SRAM_D_WIDTH-1):0] i_d0, input [(gp_SRAM_D_WIDTH-1):0] i_d1, input [(gp_SRAM_A_WIDTH-1):0] i_add0, input[(gp_SRAM_A_WIDTH-1):0] i_add1, input[(gp_SRAM_A_WIDTH-1):0] i_add2, input i_clock, input i_add0bus_sel, input i_add1bus_sel, input i_add2bus_sel, input i_rden0, input i_rden1, input i_wren0, input i_wren1, input i_noe_uc, input i_nwe_uc, input i_ncs_uc, input [(gp_SRAM_A_WIDTH-1):0] i_add_uc, output wire[(gp_SRAM_D_WIDTH-1):0] o_d0, output wire [(gp_SRAM_A_WIDTH-1):0] o_add, inout [(gp_SRAM_D_WIDTH-1):0] io_d_uc, output dbg0, output dbg1, output dbg2 ); reg [(gp_SRAM_A_WIDTH-1):0] r_a; reg[(gp_SRAM_D_WIDTH-1):0] r_d; reg[(gp_SRAM_D_WIDTH-1):0] r_q; assign o_add = r_a; assign o_d0 = r_q; reg [3:0]r_bus_mux_sel, r_we, r_oe; assign dbg0 = (r_oe); assign dbg1 = (r_we); assign dbg2 = |r_bus_mux_sel; reg [gp_SRAM_D_WIDTH:0] sram[(gp_SRAM_WORD_SIZE-1):0]; initial begin r_a = 0; r_q = 0; r_oe = 0; r_we = 0; end // Tri-State Buffer control assign io_d_uc = (r_bus_mux_sel[3] && !i_noe_uc && i_nwe_uc) ? r_q: 8'bz; always @(negedge i_clock) begin r_bus_mux_sel[3] <= !i_ncs_uc; r_bus_mux_sel[0] <= i_add0bus_sel; r_bus_mux_sel[1] <= i_add1bus_sel; r_bus_mux_sel[2] <= i_add2bus_sel; end always @(posedge i_clock) begin if(r_we) sram[r_a] <= r_d; if(r_oe) r_q <= sram[r_a]; end localparam lp_TX1BUF_ADD_OFFSET = 12'd16, lp_RX1BUF_ADD_OFFSET = 12'd96; always @(i_add_uc or i_add0 or i_add1 or i_add2 or r_bus_mux_sel) begin casex (r_bus_mux_sel) 4'd1: r_a = i_add0; 4'd2: r_a = i_add1 + lp_TX1BUF_ADD_OFFSET; 4'd4: r_a = i_add2 + lp_RX1BUF_ADD_OFFSET; 4'b1xxx: r_a = i_add_uc; default: r_a = 12'd4095; endcase end always @(i_d0 or i_d1 or r_bus_mux_sel) begin casex (r_bus_mux_sel) 4'd1: r_d = i_d0; 4'd4: r_d = i_d1; 4'b1xxx: r_d = io_d_uc; default: r_d = 0; endcase end always @(i_wren0 or i_wren1 or i_nwe_uc or r_bus_mux_sel) begin casex (r_bus_mux_sel) 4'd1: r_we = i_wren0; 4'd4: r_we = i_wren1; 4'b1xxx: r_we = !i_nwe_uc; default: r_we = 0; endcase end always @(i_rden0 or i_rden1 or i_noe_uc or r_bus_mux_sel) begin casex (r_bus_mux_sel) 4'd1: r_oe = i_rden0; 4'd2: r_oe = i_rden1; 4'b1xxx: r_oe = (!i_noe_uc && i_nwe_uc); default: r_oe = 0; endcase end endmodule К памяти подключен внешний МК: i_noe_uc, input i_nwe_uc, input i_ncs_uc, i_add_uc, io_d_uc и внутренние "читатели/писатели"(1 писатель/читатель, 1 читатель, 1 писатель). Результат использования такой: - синтезируется ОЗУ, запрошенного объема 4096 байт; - тесты записи/чтения по всему объему со стороны МК проходят успешно; - внутренние "читатели/писатели" читают и пишут успешно; НО, как-будто это две разные ОЗУ. Т.е. если записать МК какие-либо данные в определенный адрес (диапазон адресов), то внутренний читатель вычитывает с этого адреса (адресов) исключительно, то, что туда записывает внутренний писатель. Равно как и МК вычитывает, только то, что сам записал.