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

Verilog Spi-Master


eers

Рекомендуемые сообщения

Здравствуйте. Имеется код на языке Verilog для SPI - мастера. Нужно линии выбора слейва (ss[0-7]) в линии выбора количества слов обмена. 1 слово - 8 бит, 8 слов, соответственно, 64 бита. Как мне это реализовать?

`define RXTX_SIZE 16 // rx, tx buffer size, bits

`define MAXNUMOFSLAVES 8 // maximum number of slave that could be connected

`define DIVIDEBY 1 // SLK would be divided by 2^divideby

`define DATAOUT 8 // data output register size, bits

`include "spi_defines.v"

`timescale 10ns/1ns

module SPI_Master ( rst, miso, mosi, sclk, ss, data_bus, CS, addr, clock, WR, RD);

inout [7:0] data_bus; // 8 bit data bus

input clock; // clock

input miso; // Master in slave out

input [1:0] addr; // lower bits of address bus

input CS; // Chip Select

input WR, RD; // Write and read enables

input rst; // reset (synchronous active high)

output mosi; // Master out slave in

output sclk; // SPI clock

output [`MAXNUMOFSLAVES-1:0] ss;// multi-slave config

reg [7:0] shift_register; // Shift register

reg [`RXTX_SIZE-1:0] txdata; // Transmit buffer

reg [`RXTX_SIZE-1:0] rxdata; // Receive buffer

reg [`DATAOUT-1:0] data_out; // Data output register

reg [7:0] data_out_en; // Data output enable

reg [7:0] control, status; // Control Register, Status Register

reg [7:0] clk_divide; // Clock divide counter

reg [3:0] count; // SPI word length counter

reg sclk;

reg slave_cs; // Slave cs flag

reg mosi; // Master out slave in

reg spi_word_send; // Will send a new spi word.

wire [7:0] data_bus;

wire [7:0] data_in = data_bus;

wire spi_clk_gen;

wire [2:0] divide_factor = control[2:0];

wire CPOL = control[3];

wire CPHA = control[4];

wire [7:0] ss;

/* Slave Select lines + number of transmitted words */

assign ss[7] = ~( control[7] & control[6] & control[5]& (~slave_cs));

assign ss[6] = ~( control[7] & control[6] & ~control[5]& (~slave_cs));

assign ss[5] = ~( control[7] & ~control[6] & control[5]& (~slave_cs));

assign ss[4] = ~( control[7] & ~control[6] & ~control[5]& (~slave_cs));

assign ss[3] = ~(~control[7] & control[6] & control[5]& (~slave_cs));

assign ss[2] = ~(~control[7] & control[6] & ~control[5]& (~slave_cs));

assign ss[1] = ~(~control[7] & ~control[6] & control[5]& (~slave_cs));

assign ss[0] = ~(~control[7] & ~control[6] & ~control[5]& (~slave_cs));

/* clock divide */

assign spi_clk_gen = clk_divide[divide_factor*`DIVIDEBY];

/* Clock Divider */

always @ (negedge clock) begin

clk_divide = clk_divide + 1;

end

/* Reading the miso line and shifting */

always @ (posedge (sclk ^ CPOL) or posedge spi_word_send) begin

if(~rst) begin

if (spi_word_send) begin

shift_register[7:0] <= txdata;

end else begin

shift_register <= shift_register << 1;

shift_register[0] <= miso;

end

end else shift_register[7:0] <= 0;

end

/* Writing the mosi */

always @ (negedge (sclk ^ CPOL) or posedge spi_word_send) begin

if(~rst) begin

if (spi_word_send) begin

mosi <= txdata[`RXTX_SIZE-1];

end else begin

mosi <= shift_register[7];

end

end else shift_register[7:0] <= 0;

end

/* interrupt bit */

always @ (posedge slave_cs or posedge spi_word_send) begin

if (spi_word_send) begin

status[0] <= 0;

end else begin

status <= 8'h01;

rxdata <= shift_register; // updating read buffer

end

end

/* SPI word starts */

always @ (posedge clock) begin

if (spi_word_send) begin

slave_cs <= 0;

end else if ((count == 8) & ~(sclk ^ CPOL)) begin

slave_cs <= 1;

end

end

/* Spi word intiated */

always @ (posedge clock) begin

if (CS & WR & addr[1] & ~addr[0]) begin

spi_word_send <=1;

end else begin

spi_word_send <=0;

end

end

/* SLK*/

always @ (posedge spi_clk_gen) begin

if (~slave_cs) begin

sclk <= ~sclk;

end else if (~CPOL) begin

sclk <= 0;

end else begin

sclk <= 1;

end

end

/* Counting SPI word length */

always @ (posedge sclk or posedge slave_cs) begin

if (slave_cs) begin

count <= 0;

end else begin

count <= count + 1;

end

end

/* Reading, writing SPI registers */

always @ (posedge clock) begin

if (CS) begin

case (addr)

2'b00 : if (WR) control <= data_in;

2'b01 : if (RD) data_out <= status;

2'b10 : if (WR) txdata <= data_in;

2'b11 : if (RD) data_out <= rxdata;

endcase

end

end

/* Controlling the data out enable */

always @ (RD or data_out) begin

if (RD)

data_out_en = data_out;

else

data_out_en = 8'bz;

end

assign data_bus = data_out_en;

initial

begin

mosi = 0;

//control = 0;

count = 0;

sclk=0;

slave_cs = 1;

txdata = 0;

rxdata = 0;

clk_divide = 0;

data_out = 0;

end

endmodule

Ссылка на комментарий
Поделиться на другие сайты

Реклама: ООО ТД Промэлектроника, ИНН: 6659197470, Тел: 8 (800) 1000-321

20% скидка на весь каталог электронных компонентов в ТМ Электроникс!

Акция "Лето ближе - цены ниже", успей сделать выгодные покупки!

Плюс весь апрель действует скидка 10% по промокоду APREL24 + 15% кэшбэк и бесплатная доставка!

Перейти на страницу акции

Реклама: ООО ТМ ЭЛЕКТРОНИКС, ИНН: 7806548420, info@tmelectronics.ru, +7(812)4094849

В общем, у меня линии ss служат для выбора слейва(с 1 по 8). нужно оставить только 1-2 линии выбора(например, 0 и 4), а к остальным привязать возможность загрузить в регистр control количество байт обмена для организации цикла. То есть, чтоб мог отсылать на slave, например, слово из 4 байт.

Ссылка на комментарий
Поделиться на другие сайты

Выбираем схему BMS для корректной работы литий-железофосфатных (LiFePO4) аккумуляторов

 Обязательным условием долгой и стабильной работы Li-FePO4-аккумуляторов, в том числе и производства EVE Energy, является применение специализированных BMS-микросхем. Литий-железофосфатные АКБ отличаются такими характеристиками, как высокая многократность циклов заряда-разряда, безопасность, возможность быстрой зарядки, устойчивость к буферному режиму работы и приемлемая стоимость. Но для этих АКБ, также как и для других, очень важен контроль процесса заряда и разряда, а специализированных микросхем для этого вида аккумуляторов не так много. Инженеры КОМПЭЛ подготовили список имеющихся микросхем и возможных решений от разных производителей. Подробнее>>

Реклама: АО КОМПЭЛ, ИНН: 7713005406, ОГРН: 1027700032161

Для начала я убрал лишние begin-end и расставил отступы, а то совсем нечитаемый код был. Вот http://paste.fedorap...21386/31500678/

Теперь гляди. Освободить биты в control не сложно.

Вместо

assign ss[7] = ~( control[7] & control[6] & control[5]& (~slave_cs));
assign ss[6] = ~( control[7] & control[6] & ~control[5]& (~slave_cs));
assign ss[5] = ~( control[7] & ~control[6] & control[5]& (~slave_cs));
assign ss[4] = ~( control[7] & ~control[6] & ~control[5]& (~slave_cs));
assign ss[3] = ~(~control[7] & control[6] & control[5]& (~slave_cs));
assign ss[2] = ~(~control[7] & control[6] & ~control[5]& (~slave_cs));
assign ss[1] = ~(~control[7] & ~control[6] & control[5]& (~slave_cs));
assign ss[0] = ~(~control[7] & ~control[6] & ~control[5]& (~slave_cs));

Оставляем два

assign ss[7] = ~( control[5]& (~slave_cs));
assign ss[6] = ~( ~control[5]& (~slave_cs));
assign ss[5:0] = 6'b0;

Соответственно биты control[7:6] освободились для выбора числа слов.

Но дальше, как заставить посылать несколько слов подряд - уже сам пробуй сделать.

Изменено пользователем Vascom
Ссылка на комментарий
Поделиться на другие сайты

Так в этом то и вся проблема - совсем не понимаю, как послать несколько слов подряд? Можно, конечно, сдвиговый регистр в буфер закидывать, а буфер сделать 16, 24 и т.д. бит. Но опять же - как это сделать?

Ссылка на комментарий
Поделиться на другие сайты

Берёшь и делаешь :)

Можно сделать счётчик по числу слов для передачи. И пока он не досчитает до нуля - заполнять сдвиговый регистр новыми словами.

Ссылка на комментарий
Поделиться на другие сайты

Мне на 24-32 бит надо такой мастер, а такой вопрос как там задать частоту тактирования? через генератор же как я понимаю. а вот с рабом как быть?

Ссылка на комментарий
Поделиться на другие сайты

Насколько понимаю задачу, необходимо через высвободившиеся линии подавать ведомым устройствам код длины пакетов. Неясным остается только есть ли у ведомых возможность соединения к этим линиям. Если нет и ведомые - самодельные устройства на плис, то как вариант - первый байт определяет длину пакета, а дальше идут данные.

Ссылка на комментарий
Поделиться на другие сайты

Нужно сделать примерно так: при подаче 1 на ss[1] - длина передаваемого слова 8 бит, при подачи 1 на ss[2] - длина слова 13 бит, ss[3] - 24 бит и так далее.

Ссылка на комментарий
Поделиться на другие сайты

Нужно сделать примерно так...

Прделагаю поступить иначе.

Вы берете чистый лист бумаги и карандаш/ручку.

На листе рисуете минимум два квадратика, а лучше побольше, среди которых будет SPI-мастер. Вы набросаете как устанавливаются длительности пакетов, будут ли пакеты вариабельны по длине при обращении к разным приемникам. Когда будет проделана эта работа - можно будет перейти к советам по реализации.

Ссылка на комментарий
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.
Примечание: Ваш пост будет проверен модератором, прежде чем станет видимым.

Гость
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Ответить в этой теме...

×   Вставлено с форматированием.   Восстановить форматирование

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

Загрузка...
  • Последние посетители   0 пользователей онлайн

    • Ни одного зарегистрированного пользователя не просматривает данную страницу
×
×
  • Создать...