|
Внешние прерывания, STM32F103VB |
|
|
|
Jul 29 2014, 19:02
|
Гуру
     
Группа: Свой
Сообщений: 4 256
Регистрация: 17-02-06
Пользователь №: 14 454

|
ага, где то полдня работы  ... у нас 5 моторами рулит ПЛИС и АРМ, АРМ - езернет со стэком и всей фигней, по 2 SSP (аналог SPI) он общается с ПЛИС. В ПЛИС автоматы которые все делают, на протоколе даже контрольная сумма есть... SPI много легче UART в случае плис, а протокол может быть простейшим, АДРЕС, НАПРАВЛЕНИЕ (чтение-запись), ДАННЫЕ (фиксированной длинны 32 бита), контрольная сумма...
|
|
|
|
|
Jul 30 2014, 05:20
|
Профессионал
    
Группа: Участник
Сообщений: 1 778
Регистрация: 29-03-12
Пользователь №: 71 075

|
Цитата(Golikov A. @ Jul 30 2014, 01:02)  ага, где то полдня работы  ... у нас 5 моторами рулит ПЛИС и АРМ, АРМ - езернет со стэком и всей фигней, по 2 SSP (аналог SPI) он общается с ПЛИС. В ПЛИС автоматы которые все делают, на протоколе даже контрольная сумма есть... SPI много легче UART в случае плис, а протокол может быть простейшим, АДРЕС, НАПРАВЛЕНИЕ (чтение-запись), ДАННЫЕ (фиксированной длинны 32 бита), контрольная сумма... Может подгоните имплементацию парсера комманд на ПЛИС?  Цитата(adnega @ Jul 30 2014, 01:23)  А если вместо ПЛИС поставить мелкоту, типа STM32F0xx? Там и таймеров - что ног не хватит. И трехфазные комплиментарные выходы с аппаратным deadtime. И возможность энкодер подключить. Плюс всякие аналоговые компараторы для защит. Это кстати очень даже рабочее решение. У меня были проекты с двумя контроллерами, так сказать parallel tasking.
|
|
|
|
|
Jul 30 2014, 07:03
|
Гуру
     
Группа: Свой
Сообщений: 4 256
Регистрация: 17-02-06
Пользователь №: 14 454

|
да фигня... общий принцип перевести все входы под единый клок внутри ПЛИС и забыть об этом. CODE `timescale 1ns / 1ps ////////////////////////////////////////////////////////////////////////////////// // Company: *** // Engineer: *** // // Create Date: *** // Design Name: // Module Name: SPIComModule // Project Name: // Target Devices: // Tool versions: // Description: // // Dependencies: // // Revision: // Revision 0.01 - File Created // Additional Comments: // // "spi_cs" and "data_rdy" signal must be in // stable state before any "spi_clk" actions // min 2 "clk" for "data_rdy" // and 2 "clk" for "spi_cs" // ////////////////////////////////////////////////////////////////////////////////// module SPIComModule_v4_00( clk, //основной клок spi_cs, //сигнал выбора SPI spi_clk, //SPI клок данных spi_in, //входные данные SPI spi_out, //выходные данные SPI module_sel, //выбор модуля submodule_sel, //выбор подмодуля data_to_module, //данные для модуля data_from_module, //данные от модуля wr_rd_sync, //сигнал синхронизации чтения - записи wr_strb, //строб записи wr_ack, //подтверждение записи rd_strb, //строб чтения rd_ack, //подтверждение чтения check_sum_ok, //сигнал подтверждения правильной контрольной суммы data_write_done, //сигнал подтверждения записи данных data_rdy //сигнал готовности данных для чтения );
//================================================================================ == parameter MODULE_DATA_SIZE = 32; //размер данных модуля parameter MODULE_ADDR_SIZE = 4; //размер поля адреса parameter MODULE_ADDR_VECTOR_SIZE = (32'b01 << MODULE_ADDR_SIZE); //размер вектора выбора модуля (4 бита адрес) parameter SUB_ADDR_SIZE = 3; //размер поля подадреса parameter SUB_ADDR_VECTOR_SIZE = (32'b01 << SUB_ADDR_SIZE); //размер вектора выбора подмодуля (3 бита подадрес)
parameter READ_DIRRECTION_VAL = 1; //значение бита при котором идет чтение parameter ADDR_FIELD_SIZE = 8; //8 бит поле адреса parameter CHECKSUM_FIELD_SIZE = 8; //8 бит поле контрольной суммы localparam DATA_FIELD_SIZE = MODULE_DATA_SIZE; //размер поля данных //размер регистра расчета длинны сообщения для определения //окончания приема parameter MES_LEN_COUNTER_SIZE = 6; //размер регистра расчета длинны слова контрольной суммы //для определения окончания приема очередного слова parameter CHECKSUM_LEN_COUNTER_SIZE = 3; //контрольная сумма по всем сообщению должна дать 0 //чтобы полностью нулевое сообщение не прошло как верное //начинаем считать сумму с этого значения parameter START_CHECKSUM_VAL = 'hA5; //================================================================================ == input clk; input spi_cs; input spi_clk; input spi_in; output spi_out; output reg [MODULE_ADDR_VECTOR_SIZE - 1 : 0] module_sel = 0; output reg [SUB_ADDR_VECTOR_SIZE - 1 : 0] submodule_sel = 0; output reg [MODULE_DATA_SIZE - 1 : 0] data_to_module = 0; input [MODULE_DATA_SIZE - 1 : 0] data_from_module; //этот сигнал должен быть лишен мета-стабильности //во внешних схемах input wr_rd_sync; output wr_strb; input wr_ack; output rd_strb; input rd_ack; output reg check_sum_ok = 0; output reg data_write_done = 0; output reg data_rdy = 0; //================================================================================ == //регистры для задания состояние строба чтения и записи //эти регистры задает схема, а выходное значение получается //с учетом сигнала синхронизации reg wr_strb_reg = 0; reg rd_strb_reg = 0; //если разрешена запись или чтение, выдаем наружу стробы assign wr_strb = (wr_strb_reg & wr_rd_sync); assign rd_strb = (rd_strb_reg & wr_rd_sync); //для синхронизации 2 клоковых доменов //основного и SPI используем систему семафоров //задание и подтверждение задания reg need_start_recive = 0; //необходимо начать прием с 1 клоком SPI reg need_start_recive_ack = 0; //подтверждение, прием начат reg recive_done = 0; //окончание приема //так как сигнал из другого клокового домена //пропустим его через 2 триггера, это создаст //доп задержку на стабилизацию данных //по констрайнам частота процессора в 2 раза выше частоты SPI //значит через 2 клока данные SPI гарантированно верны reg recive_done_1 = 0; reg recive_done_2 = 0; reg recive_done_ack = 0; //подтверждение окончания приема reg need_start_transllate = 0; //необходимо начать передачу данных reg need_start_transllate_ack = 0; //передача данных начата //вектор входного сообщения localparam FULL_MESSAGE_LEN = ADDR_FIELD_SIZE + DATA_FIELD_SIZE + CHECKSUM_FIELD_SIZE; reg [FULL_MESSAGE_LEN - 1 : 0] input_data_vector = 0; //для удобства работы разделим поля входного вектора wire [DATA_FIELD_SIZE - 1 : 0] data_w; assign data_w = input_data_vector[DATA_FIELD_SIZE + CHECKSUM_FIELD_SIZE - 1 -: DATA_FIELD_SIZE]; wire [SUB_ADDR_SIZE - 1 : 0] subaddr_w; assign subaddr_w = input_data_vector[SUB_ADDR_SIZE + DATA_FIELD_SIZE + CHECKSUM_FIELD_SIZE - 1 -: SUB_ADDR_SIZE]; wire [MODULE_ADDR_SIZE - 1 : 0 ] addr_w; assign addr_w = input_data_vector[MODULE_ADDR_SIZE + SUB_ADDR_SIZE + DATA_FIELD_SIZE + CHECKSUM_FIELD_SIZE - 1 -: MODULE_ADDR_SIZE]; wire read_direction_w; assign read_direction_w = input_data_vector[1 + MODULE_ADDR_SIZE + SUB_ADDR_SIZE + DATA_FIELD_SIZE + CHECKSUM_FIELD_SIZE - 1 -: 1]; //вектор расчета контрольной суммы reg [CHECKSUM_FIELD_SIZE - 1 : 0] checksum_calc_vector = START_CHECKSUM_VAL; //вектор приема данных для расчета контрольной суммы reg [CHECKSUM_FIELD_SIZE - 1 : 0] checksum_vector = 0; //вектор выходных данных, на 1 бит меньше чем данные //так как первый отправляемый бит в него не сохраняется reg [DATA_FIELD_SIZE - 2 : 0] output_vector = 0; //значение выходного бита данных SPI должно быть готово //до первого клока, еще до защелки данных в сдвиговый регистр //поэтому первый бит берется из входного вектора //а последующие уже из сдвигового регистра //в начальный момент будет стоять семафор assign spi_out = (need_start_transllate != need_start_transllate_ack) ? data_from_module [MODULE_DATA_SIZE - 1] : //начальный момент output_vector[MODULE_DATA_SIZE - 2]; //последующие посылки (вектор на 1 бит меньше данных) //счетчик длинны сообщения reg [MES_LEN_COUNTER_SIZE - 1 : 0] mes_len_counter = 0; //счетчик длинны слова контрольной суммы reg [CHECKSUM_LEN_COUNTER_SIZE - 1 : 0] checksum_len_counter = 0; //================================================================================ == // обработка основного клока //================================================================================ == always @(posedge clk) begin //-------------------- переход между клоковыми доменами recive_done_1 <= recive_done; recive_done_2 <= recive_done_1; //-------------------- обмен данными if(spi_cs == 1'b1) //если нет выбора SPI begin //чип селект имеет гарантированную паузу, он асинхронный //гарантированная пауза приведет схему в правильное состояние //выборы адреса - one hot, один бит в векторе, //при снятии не может так получиться что бит измениться //или возникнут еще какие-то соседние биты, //потому даже если адрес изменится до снятия wr(rd)_strb //так как сигнал cs асинхронный, это не страшно, другие //адреса не выберутся и неправильных транзакций не будет //значение битов ответов тоже не важно, если чип селект //вверху их уже не проверяют
//подготовимся к приему следующего сообщения //первый фронт SPI клока - начало приема need_start_recive <= ~need_start_recive_ack; //снимем все стробы wr_strb_reg <= 0; rd_strb_reg <= 0; //снимем все выборы, module_sel <= 0; submodule_sel <= 0; //снимаем все ответы check_sum_ok <= 0; data_write_done <= 0; data_rdy <= 0; //на всякий случай, если было поднятие чипселекта //до окончания обмена, снимем флаг окончания приема recive_done_ack <= recive_done_2; end else //если есть выбор SPI begin if(recive_done_2 != recive_done_ack) //если закончен прием begin //ставим подтверждение обработки флага recive_done_ack <= recive_done_2;
//если сошлась контрольная сумма //последние сложение надо сделать в этой процедуре //так как после приема последнего бита //нет больше тактов (клоков SPI) на выполнение if((checksum_calc_vector + checksum_vector) == {CHECKSUM_FIELD_SIZE{1'b0}}) begin check_sum_ok <= 1'b1; //ставим признак //ставим выбор модуля и подадреса //сразу производим частичную дешифрацию адреса module_sel <= ({{(MODULE_ADDR_VECTOR_SIZE - 1){1'b0}}, 1'b1} << $unsigned (addr_w)); submodule_sel <= ({{(SUB_ADDR_VECTOR_SIZE - 1){1'b0}}, 1'b1} << $unsigned (subaddr_w)); if(read_direction_w == READ_DIRRECTION_VAL) //если режим чтения begin rd_strb_reg <= 1'b1; //строб чтения //отмечаем что нужно будет начать передачу //захват данных в регистр произойдет по //SPI клоку, а его выдаст мастер только после //получения сигнала готовности данных //так что это значение можно тут выставить //и не заботится о нем, даже если будет прерывание обмена //без фазы чтения need_start_transllate <= ~need_start_transllate_ack; end else //режим записи begin data_to_module <= data_w; //выставляем данные wr_strb_reg <= 1'b1; //строб записи end end //контрольная сумма end //закончен прием //если не будет признака окончания приема //не будет проверки контрольной суммы //и не будет запросов на чтение или запись //и сигналы ниже не появятся //если есть запрос на запись и подтверждение if((wr_strb_reg == 1'b1)&&(wr_ack == 1'b1)) data_write_done <= 1'b1; //отмечаем что данные записаны //если есть запрос на чтение и подтверждение if((rd_strb_reg == 1'b1)&&(rd_ack == 1'b1)) data_rdy <= 1'b1; //отмечаем что данные готовы end //есть выбор SPI end //конец обработки клока //================================================================================ == // обработка клока SPI //================================================================================ == //выбор SPI не проверяем, так как без выбора не //пройдет конец обмена, весь обмен идет внутри //одного выбора, клоков вне обмена нет always @(posedge spi_clk) begin //---------------------------------------------------------------- if (need_start_recive != need_start_recive_ack) //если начало приема ы begin //отмечаем начало приема need_start_recive_ack <= need_start_recive; //сохраняем первый принятый бит input_data_vector <= {{(FULL_MESSAGE_LEN - 1){1'b0}},spi_in}; checksum_vector <= {{(CHECKSUM_FIELD_SIZE - 1){1'b0}},spi_in}; //сохраняем начальное значение вектора расчета контрольной суммы checksum_calc_vector <= START_CHECKSUM_VAL; //заряжаем счетчики, первый бит уже принят, //окончание приема всего сообщения по равенству нулю //счетчик всего сообщения на 1 бит меньше чтобы //он стал нулем в момент приема последнего бита //а не после приема, вместе с приемом последнего //бита выставиться и признак окончания приема mes_len_counter <= (FULL_MESSAGE_LEN - 2); checksum_len_counter <= (CHECKSUM_FIELD_SIZE - 1); end else //прием begin //уменьшаем счетчики с каждым принятым битом mes_len_counter <= mes_len_counter - 1'b1; checksum_len_counter <= checksum_len_counter - 1'b1; //прием сообщения, сдвигаем входной вектор дополняя входным битом input_data_vector <= {input_data_vector[FULL_MESSAGE_LEN - 2 : 0], spi_in}; //параллельно сохраняем вектор контрольной суммы checksum_vector <= {checksum_vector [CHECKSUM_FIELD_SIZE - 2 : 0], spi_in}; //если приняли все сообщение if(mes_len_counter == 0) recive_done <= ~recive_done_ack; //отмечаем окончание приема //если приняли очередное слово контрольной суммы if(checksum_len_counter == 0) begin //заряжаем счетчик заново checksum_len_counter <= (CHECKSUM_FIELD_SIZE - 1); //добавляем принятый вектор в сумму checksum_calc_vector <= checksum_calc_vector + checksum_vector; end end //прием //----------------------------------------------------------------- //значение передаваемых данных во время приема не важны, //потому всегда передаем, к фазе передачи данные будут //запрошены и корректно обновлены if (need_start_transllate != need_start_transllate_ack) //если начало передачи begin //отмечаем начало передачи need_start_transllate_ack <= need_start_transllate; //сохраняем данные от модуля без старшего бита, //так как первый бит уже передан (взят из данных на отправку) //после этого такта, на выход будет передаваться старший бит //этого вектора output_vector <= data_from_module[DATA_FIELD_SIZE - 2 : 0]; end else //передача begin //просто сдвигаем вектор данных //значение дополнения не важно output_vector <= (output_vector << 1); end //передача end //конец обработки клока SPI endmodule
wr_rd_sync - этот сигнал в 1 зажмите, он для синхронизации служит, это для нашей специфики было нужно.
|
|
|
|
|
Jul 30 2014, 07:07
|
Профессионал
    
Группа: Участник
Сообщений: 1 778
Регистрация: 29-03-12
Пользователь №: 71 075

|
Цитата(adnega @ Jul 30 2014, 12:35)  STM32F030K6T6 по $1. Можно и не один поставить при желании)
ПЛИС, может, и хорошо, но дорого. И для меня (только начавшего вникать в ПЛИС) много вопросов в синхронизации разных частей проекта - т.е. нужно заниматься более низкоуровневым проектированием (типа, как на ASM для схем пересесть). ПЛИС очень сильная штука. Во первых real time действительно real - несколько процессов могут бежать параллельно. Во вторых полная свобода выбора ног - куда посадить рвм, куда энкодер - соответственно разводка платы существенно оптимизируется. Кроме того как говорят надежней в работе. Ну конечно пересесть с С на VHDL тут придется немного попотеть. Golikov A., Большое спасибо !
|
|
|
|
|
Jul 30 2014, 07:14
|
Гуру
     
Группа: Свой
Сообщений: 4 256
Регистрация: 17-02-06
Пользователь №: 14 454

|
Огромный бонус ПЛИС - это возможность создание реально параллельных блоков, а еще в добавок там куча памяти теперь и прочих радостей. Можно и проц запихать, отказавшись от внешнего. Для частной маленькой задачи обработки энкодеров можно взять малюсенькую CPLD. Я вот тут пытался представить как обработать энкодер на таймере, у меня не получилось 4 электронных отсчетов на реальную линию, и направление надо учитывать, а в ПЛИС все будет четко, 4 электронных отсчета на реальный, и регистры накопления внутри ПЛИС. да еще забыл spi_clk - вот этот сигнал лучше завести на клоковый вход ПЛИС (это спец ножки, их много). Можно и на обычный, но времянка просядет, на клоковый лучше. И я вам настоятельно рекомендую пересаживаться на Verilog, я начинал с VHDL, а теперь на верилог пересел, одни положительные эмоции во я еще тестбенч нашел от модуля CODE `timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////// // Company: // Engineer: // // Create Date: 15:18:31 04/16/2014 // Design Name: SPIComModule_v4_00 // Module Name: E:/SYNC_MOTOR/FPGA/SPIComModule_v4_00_tb.v // Project Name: SyncMotor // Target Device: // Tool versions: // Description: // // Verilog Test Fixture created by ISE for module: SPIComModule_v4_00 // // Dependencies: // // Revision: // Revision 0.01 - File Created // Additional Comments: // ////////////////////////////////////////////////////////////////////////////////
module SPIComModule_v4_00_tb; localparam DATA_SIZE = 16;
// Inputs reg clk; reg spi_cs; reg spi_clk; reg spi_in; reg [DATA_SIZE - 1 : 0] data_from_module; reg wr_rd_sync; reg wr_ack; reg rd_ack;
// Outputs wire spi_out; wire [15:0] module_sel; wire [7:0] submodule_sel; wire [DATA_SIZE - 1 : 0] data_to_module; wire wr_strb; wire rd_strb; wire check_sum_ok; wire data_write_done; wire data_rdy;
reg [DATA_SIZE - 1 : 0] datareg_00; reg [DATA_SIZE - 1 : 0] datareg_01; reg [DATA_SIZE - 1 : 0] datareg_10; reg [DATA_SIZE - 1 : 0] datareg_11; reg [DATA_SIZE - 1 : 0] data ; reg [7 : 0] addr ; reg [7 : 0] check_sum; // Instantiate the Unit Under Test (UUT) SPIComModule_v4_00 #(.MODULE_DATA_SIZE(DATA_SIZE) ) uut ( .clk(clk), .spi_cs(spi_cs), .spi_clk(spi_clk), .spi_in(spi_in), .spi_out(spi_out), .module_sel(module_sel), .submodule_sel(submodule_sel), .data_to_module(data_to_module), .data_from_module(data_from_module), .wr_rd_sync(wr_rd_sync), .wr_strb(wr_strb), .wr_ack(wr_ack), .rd_strb(rd_strb), .rd_ack(rd_ack), .check_sum_ok(check_sum_ok), .data_write_done(data_write_done), .data_rdy(data_rdy) );
integer i; initial begin // Initialize Inputs spi_cs = 0; spi_clk = 0; spi_in = 0; wr_rd_sync = 0; data = 0; addr = 0; check_sum = 0; // Wait 100 ns for global reset to finish #100; // Add stimulus here spi_cs <= 1; spi_clk <= 1; #100;
//----------------------------------------------------------- data = 16'h0000; addr = 8'b10010001; check_sum = 8'hFF + data[7:0] + data[15:8] + addr; check_sum = 0 - check_sum; wr_rd_sync = 0; spi_cs <= 0; for (i=0;i<8;i=i+1) begin spi_clk = 0; #8; spi_in = addr[7-i]; #2; spi_clk = 1; #10; end for (i=0;i<DATA_SIZE;i=i+1) begin spi_clk = 0; #8; spi_in = data[DATA_SIZE - 1 -i]; #2; spi_clk = 1; #10; end for (i=0;i<8;i=i+1) begin spi_clk = 0; #8; spi_in = check_sum[7-i]; #2; spi_clk = 1; #10; end
#100; wr_rd_sync = 1; #100;
if(data_rdy == 1) for (i=0;i<DATA_SIZE;i=i+1) begin spi_clk = 0; #10; spi_clk = 1; #10; end spi_cs <= 1; //----------------------------------------------------------- //----------------------------------------------------------- #50; data = 16'hAABB; addr = 8'b00001001; check_sum = 8'hFF + data[7:0] + data[15:8] + addr; check_sum = 0 - check_sum; wr_rd_sync = 1; spi_cs <= 0; for (i=0;i<8;i=i+1) begin spi_clk = 0; #8; spi_in = addr[7-i]; #2; spi_clk = 1; #10; end for (i=0;i<DATA_SIZE;i=i+1) begin spi_clk = 0; #8; spi_in = data[DATA_SIZE - 1 -i]; #2; spi_clk = 1; #10; end for (i=0;i<8;i=i+1) begin spi_clk = 0; #8; spi_in = check_sum[7-i]; #2; spi_clk = 1; #10; end
#100;
if(data_rdy == 1) for (i=0;i<DATA_SIZE;i=i+1) begin spi_clk = 0; #10; spi_clk = 1; #10; end spi_cs <= 1; //-----------------------------------------------------------
//----------------------------------------------------------- #50; data = 16'hCCDD; addr = 8'b00010010; check_sum = 8'hFF + data[7:0] + data[15:8] + addr; check_sum = 0 - check_sum; wr_rd_sync = 1; spi_cs <= 0; for (i=0;i<8;i=i+1) begin spi_clk = 0; #8; spi_in = addr[7-i]; #2; spi_clk = 1; #10; end for (i=0;i<DATA_SIZE;i=i+1) begin spi_clk = 0; #8; spi_in = data[DATA_SIZE - 1 -i]; #2; spi_clk = 1; #10; end for (i=0;i<8;i=i+1) begin spi_clk = 0; #8; spi_in = check_sum[7-i]; #2; spi_clk = 1; #10; end
#100;
if(data_rdy == 1) for (i=0;i<DATA_SIZE;i=i+1) begin spi_clk = 0; #10; spi_clk = 1; #10; end spi_cs <= 1; //-----------------------------------------------------------
//----------------------------------------------------------- #50; data = 16'hAABB; addr = 8'b10001001; check_sum = 8'hFF + data[7:0] + data[15:8] + addr; check_sum = 0 - check_sum; wr_rd_sync = 1; spi_cs <= 0; for (i=0;i<8;i=i+1) begin spi_clk = 0; #8; spi_in = addr[7-i]; #2; spi_clk = 1; #10; end for (i=0;i<DATA_SIZE;i=i+1) begin spi_clk = 0; #8; spi_in = data[DATA_SIZE - 1 -i]; #2; spi_clk = 1; #10; end for (i=0;i<8;i=i+1) begin spi_clk = 0; #8; spi_in = check_sum[7-i]; #2; spi_clk = 1; #10; end
#100;
if(data_rdy == 1) for (i=0;i<DATA_SIZE;i=i+1) begin spi_clk = 0; #10; spi_clk = 1; #10; end spi_cs <= 1; //----------------------------------------------------------- //----------------------------------------------------------- #50; data = 16'hAABB; addr = 8'b10010010; check_sum = 8'hFF + data[7:0] + data[15:8] + addr; check_sum = 0 - check_sum; wr_rd_sync = 1; spi_cs <= 0; for (i=0;i<8;i=i+1) begin spi_clk = 0; #8; spi_in = addr[7-i]; #2; spi_clk = 1; #10; end for (i=0;i<DATA_SIZE;i=i+1) begin spi_clk = 0; #8; spi_in = data[DATA_SIZE - 1 -i]; #2; spi_clk = 1; #10; end for (i=0;i<8;i=i+1) begin spi_clk = 0; #8; spi_in = check_sum[7-i]; #2; spi_clk = 1; #10; end
#100;
if(data_rdy == 1) for (i=0;i<DATA_SIZE;i=i+1) begin spi_clk = 0; #10; spi_clk = 1; #10; end spi_cs <= 1; //-----------------------------------------------------------
//----------------------------------------------------------- #50; data = 16'hEEFF; addr = 8'b00000000; check_sum = 8'hFF + data[7:0] + data[15:8] + addr; check_sum = 0 - check_sum; wr_rd_sync = 1; spi_cs <= 0; for (i=0;i<8;i=i+1) begin spi_clk = 0; #8; spi_in = addr[7-i]; #2; spi_clk = 1; #10; end for (i=0;i<DATA_SIZE;i=i+1) begin spi_clk = 0; #8; spi_in = data[DATA_SIZE - 1 -i]; #2; spi_clk = 1; #10; end for (i=0;i<8;i=i+1) begin spi_clk = 0; #8; spi_in = check_sum[7-i]; #2; spi_clk = 1; #10; end
#100;
if(data_rdy == 1) for (i=0;i<DATA_SIZE;i=i+1) begin spi_clk = 0; #10; spi_clk = 1; #10; end spi_cs <= 1; //-----------------------------------------------------------
//----------------------------------------------------------- #50; data = 16'h0000; addr = 8'b10000000; check_sum = 8'hFF + data[7:0] + data[15:8] + addr; check_sum = 0 - check_sum; wr_rd_sync = 1; spi_cs <= 0; for (i=0;i<8;i=i+1) begin spi_clk = 0; #8; spi_in = addr[7-i]; #2; spi_clk = 1; #10; end for (i=0;i<DATA_SIZE;i=i+1) begin spi_clk = 0; #8; spi_in = data[DATA_SIZE - 1 -i]; #2; spi_clk = 1; #10; end for (i=0;i<8;i=i+1) begin spi_clk = 0; #8; spi_in = check_sum[7-i]; #2; spi_clk = 1; #10; end
#100;
if(data_rdy == 1) for (i=0;i<DATA_SIZE;i=i+1) begin spi_clk = 0; #10; spi_clk = 1; #10; end spi_cs <= 1; //-----------------------------------------------------------
#1000; //----------------------------------------------------------- #50; data = 16'hCCCC; addr = 8'b10010010; check_sum = 8'hFF + data[7:0] + data[15:8] + addr; check_sum = 0 - check_sum; wr_rd_sync = 0; spi_cs <= 0; for (i=0;i<8;i=i+1) begin spi_clk = 0; #8; spi_in = addr[7-i]; #2; spi_clk = 1; #10; end for (i=0;i<DATA_SIZE;i=i+1) begin spi_clk = 0; #8; spi_in = data[DATA_SIZE - 1 -i]; #2; spi_clk = 1; #10; end for (i=0;i<8;i=i+1) begin spi_clk = 0; #8; spi_in = check_sum[7-i]; #2; spi_clk = 1; #10; end
#100;
if(data_rdy == 1) for (i=0;i<DATA_SIZE;i=i+1) begin spi_clk = 0; #10; spi_clk = 1; #10; end spi_cs <= 1; //-----------------------------------------------------------
//----------------------------------------------------------- #50; data = 16'hCCCC; addr = 8'b00000000; check_sum = 8'hFF + data[7:0] + data[15:8] + addr; check_sum = 0 - check_sum; wr_rd_sync = 0; spi_cs <= 0; for (i=0;i<8;i=i+1) begin spi_clk = 0; #8; spi_in = addr[7-i]; #2; spi_clk = 1; #10; end for (i=0;i<DATA_SIZE;i=i+1) begin spi_clk = 0; #8; spi_in = data[DATA_SIZE - 1 -i]; #2; spi_clk = 1; #10; end for (i=0;i<8;i=i+1) begin spi_clk = 0; #8; spi_in = check_sum[7-i]; #2; spi_clk = 1; #10; end
#100;
if(data_rdy == 1) for (i=0;i<DATA_SIZE;i=i+1) begin spi_clk = 0; #10; spi_clk = 1; #10; end spi_cs <= 1; //-----------------------------------------------------------
//----------------------------------------------------------- #50; data = 16'h0000; addr = 8'b10000000; check_sum = 8'hFF + data[7:0] + data[15:8] + addr; check_sum = 0 - check_sum; wr_rd_sync = 0; spi_cs <= 0; for (i=0;i<8;i=i+1) begin spi_clk = 0; #8; spi_in = addr[7-i]; #2; spi_clk = 1; #10; end for (i=0;i<DATA_SIZE;i=i+1) begin spi_clk = 0; #8; spi_in = data[DATA_SIZE - 1 -i]; #2; spi_clk = 1; #10; end for (i=0;i<8;i=i+1) begin spi_clk = 0; #8; spi_in = check_sum[7-i]; #2; spi_clk = 1; #10; end
#100;
if(data_rdy == 1) for (i=0;i<DATA_SIZE;i=i+1) begin spi_clk = 0; #10; spi_clk = 1; #10; end spi_cs <= 1; //----------------------------------------------------------- end initial begin // Initialize Inputs clk = 0;
// Wait 100 ns for global reset to finish #98; // Add stimulus here forever begin #5; clk <= ~clk; end end
initial begin // Initialize Inputs datareg_00 = 0; datareg_01 = 0; datareg_10 = 0; datareg_11 = 0; wr_ack = 0; rd_ack = 0; data_from_module = 0; // Wait 100 ns for global reset to finish #100; // Add stimulus here forever begin #1; wr_ack <= 0; rd_ack <= 0; data_from_module <= 'hFFFF; if((module_sel == 2'b1)&&(submodule_sel == 2'b1)) begin if(wr_strb == 1) begin datareg_00 <= data_to_module; wr_ack <= 1; end if(rd_strb == 1) begin data_from_module <= datareg_00; rd_ack <= 1; end end
if((module_sel == 2'b10)&&(submodule_sel == 2'b1)) begin if(wr_strb == 1) begin datareg_10 <= data_to_module; wr_ack <= 1; end if(rd_strb == 1) begin data_from_module <= datareg_10; rd_ack <= 1; end end
if((module_sel == 2'b1)&&(submodule_sel == 2'b10)) begin if(wr_strb == 1) begin datareg_01 <= data_to_module; wr_ack <= 1; end if(rd_strb == 1) begin data_from_module <= datareg_01; rd_ack <= 1; end end
if((module_sel == 2'b10)&&(submodule_sel == 2'b10)) begin if(wr_strb == 1) begin datareg_11 <= data_to_module; wr_ack <= 1; end if(rd_strb == 1) begin data_from_module <= datareg_11; rd_ack <= 1; end end end end
endmodule
|
|
|
|
|
Jul 30 2014, 07:59
|
Знающий
   
Группа: Свой
Сообщений: 583
Регистрация: 7-06-06
Из: Таганрог
Пользователь №: 17 840

|
Цитата(Jenya7 @ Jul 30 2014, 11:30)  Перед тем как начать програмироать на ПЛИС я читал много статей VHDL vs Verilog - все таки общий тренд в пользу VHDL. Добавлю еше что VHDL ГОСТирован, а Verilog - нет. общий тренд в пользу VHDL.
|
|
|
|
|
Jul 30 2014, 09:23
|
Гуру
     
Группа: Свой
Сообщений: 4 256
Регистрация: 17-02-06
Пользователь №: 14 454

|
Поскольку мне надо делать дело, а не быть в тренде я выбираю Verilog  Это священная война, и вы можете выбирать любую сторону. Я выбрал верилог по причине того что писать на нем легче, меньше букв, меньше атавистических библиотек которые перекрывают друг друга вызывая путаницы и несостыковки проекта. VHDL - старинный монстр, который несет на себе груз не только работы с ПЛИС, но и общего описания железа, в нем можно описать все что хочешь и максимально строго, плата за это что там надо топтать клавиатуру не по детски, и самая простая схема требует много букв. Если же ограничиться только работой с ПЛИС, то верилога 100% хватит, и писать будет удобнее. Общая тенденция что плисовики знают оба языка, потому что они представленны одинаково на рынке, а с какого начать вам решать)
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|