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

michael.sysoev

Участник
  • Постов

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

  • Посещение

Сообщения, опубликованные michael.sysoev


  1. 19 часов назад, iosifk сказал:

    Однако в коде не видно как микроконтроллер синхронизируется с внутренним клоком и не видно арбитра

    На данном этапе арбитраж между внутренними потребителями не нужен (пока они жестко разнесены по времени). Арбитраж с МК по задумке должна обеспечивать конструкция вида: 

    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

    приоритет у МК. 

    Синхронизатор прикручиваю. Синхронизировать рекомендуете все сигналы или достаточно стробы?

  2. В 07.06.2019 в 09:39, des00 сказал:

    Сделайте тестбенч в симуляторе, только полный. промоделируйте запись/чтение со стороны МК и с вашей системы. Тогда вам станет доступны все внутренности и ошибка сразу всплывет)

    К сожалению, полный тестбенч ошибок не выявил. В симуляторе все ходит, как задумано.

  3. 15 часов назад, Nick_K сказал:

    В моём понимании диапазон - это от 0, к примеру, и до 100. А я говорил про полную запись от начала и до конца. Но это я видно не так понял Вас.

    Произвожу с МК тест на целостность ОЗУ путем записи 16 байт случайных данных, с последующим вычитыванием и сравнением контрольных сумм - и так по всему объему. Со стороны ПЛИС также при старте делаю запись/чтение, но там тест попроще и не по всему объему.

     

    Списки чувствительности поправил, спасибо (лучше не стало). 

  4. 8 минут назад, Nick_K сказал:

    Я с Альтерой давно не работал, но чисто с синтаксической точки зрения - в этих конструкциях у Вас в списках чувствительности указаны не все переменные. Соответственно синтезировать Верилог может что угодно

    Извините, не увидел, что именно не указал в списке чувствительности? 

     

    11 минут назад, Nick_K сказал:

    Второе, попробуйте записать МК все единицы в память а потом это считать ПЛИСой и наоборот.

    Как раз с этим и проблема. Процитирую сам себя:

    "Т.е. если записать МК какие-либо данные в определенный адрес (диапазон адресов), то внутренний читатель вычитывает с этого адреса (адресов) исключительно, то, что туда записывает внутренний писатель. Равно как и МК вычитывает, только то, что сам записал."

     

    13 минут назад, Nick_K сказал:

    И третье, не обессудьте, два ярчайших примера: некоменнтированый код и оверкоментированный :) Коментов должно быть в меру ;)

    Известно - перебор, хуже недобора. 

  5. 25 минут назад, iosifk сказал:

    Давайте с самого начала.

    Вы "привели в качестве кода" какие-то буквы и все участники форума теперь должны гадать что именно какая крокозябра из себя представляет. Я понимаю, если Вам за каждую напечатанную букву приходится кому-то платить деньги, то на комментарии буквы жалко. Или это военная тайна такая, чтобы нарушать все правила оформления документов.

    Ни названий сигналов, ни комментариев в тексте о том что и где делается.

    Ну а нам-то что делать? Нам тоже свое время приходится жалеть. 

    Прошу прощения, согласен. Спасибо, что поправили. Попробую еще раз, не знаю, как редактировать собственные сообщения, поэтому - новое.

    `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
    
    
    
    

     

  6. Доброго времени! Прошу совета у сообщества. "Сам я в верилог недавно".

    Пытаюсь таким образом:

    `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 байт;

    - тесты записи/чтения по всему объему со стороны МК проходят успешно;

    - внутренние "читатели/писатели" читают и пишут успешно;

    НО, как-будто это две разные ОЗУ.

    Т.е. если записать МК какие-либо данные в определенный адрес (диапазон адресов), то внутренний читатель вычитывает с этого адреса (адресов) исключительно, то, что туда записывает внутренний писатель. Равно как и МК вычитывает, только то, что сам записал.

×
×
  • Создать...