Шина бит как записать

Видео:Виды видеопамяти и сколько её нужно? Какая нужна шина?Скачать

Виды видеопамяти и сколько её нужно? Какая нужна шина?

Битовые операции. Для чего они нужны на примере программировании МК

Введение

В своё время я не мог понять смысл таких вещей, как битовые операции. Статьи в интернете не давали мне практического понимания этого вопроса. Со временем, когда я столкнулся с программированием микроконтроллеров (МК), я понял удобство подобных операций, поэтому я решил написать данную статью, чтобы пролить свет на этот вопрос людям, которые только услышали про битовые операции и хотят узнать конкретное практическое применение данных операций. Все примеры будут приведены для tms320f28027.

Операции битового сдвига:

Битовые операции, как можно понять из названия, заключаются в сдвиге битов вправо (>>) или влево (

Видео:МОРГЕНШТЕРН УЧИТ ДЕЛАТЬ БИТ ЗА 1 МИНУТУ!!! Как быстро сделать бит The люди MORGENSHTERNСкачать

МОРГЕНШТЕРН УЧИТ ДЕЛАТЬ БИТ ЗА 1 МИНУТУ!!!  Как быстро сделать бит The люди MORGENSHTERN

О песочнице

Это «Песочница» — раздел, в который попадают дебютные посты пользователей, желающих стать полноправными участниками сообщества.

Если у вас есть приглашение, отправьте его автору понравившейся публикации — тогда её смогут прочитать и обсудить все остальные пользователи Хабра.

Чтобы исключить предвзятость при оценке, все публикации анонимны, псевдонимы показываются случайным образом.

Видео:Как выбрать видеокарту. Или почему шина 256 бит - не рулит. (см. описание)Скачать

Как выбрать видеокарту. Или почему шина 256 бит - не рулит. (см. описание)

О модерации

  • рекламные и PR-публикации
  • вопросы и просьбы (для них есть Хабр Q&A);
  • вакансии (используйте Хабр Карьеру)
  • статьи, ранее опубликованные на других сайтах;
  • статьи без правильно расставленных знаков препинания, со смайликами, с обилием восклицательных знаков, неоправданным выделением слов и предложений и другим неуместным форматированием текста;
  • жалобы на компании и предоставляемые услуги;
  • низкокачественные переводы;
  • куски программного кода без пояснений;
  • односложные статьи;
  • статьи, слабо относящиеся к или не относящиеся к ней вовсе.

Видео:ЧТО Делать Чтобы Тебя Не Кинул Артист + Шаблон Договора на RU/ENGСкачать

ЧТО Делать Чтобы Тебя Не Кинул Артист + Шаблон Договора на RU/ENG

Язык описания аппаратуры Verilog HDL

Казалось бы простая задача: как развернуть биты в шине так, чтоб младший бит стал старшим, а старший самым младшим? Первое, что приходит на ум: написать вот так:

reg [7:0]src;
//reverse?
wire [0:7]re1; assign re1 = src; //does not work..

Но это так не работает!
Какие есть работающие варианты?

Первый и самый понятный способ — это расписывать каждый бит в отдельности. Вот так:

Это отличный метод, который использует оператор конкатенации, объединяет известные сигналы в новом нужном порядке. Этим методом легко пользоваться, когда число сигналов в шине не велико. Если же шина многоразрядная, 64, 128, 1024 бита, то как быть?

Второй метод — это написать и использовать специальную функцию:

function [7:0] fbit_reverse ( input [7:0] data );
integer i;
begin
for ( i=0; i
begin
fbit_reverse[7-i] = data[i];
end
end
endfunction

В эту функцию можно передать восьмибитный сигнал и она выдаст нам другой восьмибитный сигнал, где биты уже развернуты, как нужно. Вот так:

//method 2, use reverse function
wire [7:0]re3; assign re3 = fbit_reverse(src);

Хорошее решение, но не придумал, как сделать его параметризуемым. Что если есть несколько шин которые имеют разную разрядность и каждую нужно развернуть? Тогда можно сделать отдельный параметризуемый модуль. Например, вот так:

module mod_bit_reverse( in, out );
parameter NUM_BITS = 16;
input wire [NUM_BITS-1:0]in;
output wire [NUM_BITS-1:0]out;
genvar i;
generate
for (i=0; i
begin
assign out[NUM_BITS-1-i] = in[i];
end
endgenerate
endmodule

Этот модуль можно вставлять в другие модули и там и сям и задавать разрядность шин в параметре.
Вставить модуль в другой модуль верилом можно так:

wire [7:0]re4;
mod_bit_reverse // module name
#(.NUM_BITS(8)) //module parameter, bus width
my_reverse_module //module instance name
(
.in(src), // module signals
.out(re4)
);

Есть еще один вариант — использовать SystemVerilog Streaming Operator.

Это замечательно работает, если симулировать в Modelsim. Для симуляции подходит даже Modelsim Starter Edition Intel v10.5b, который идет в комплекте с 16м квартусом.

Однако, похоже, что сам квартус такое не поддерживает. Увы.
Симулятор icarus verilog так же на эту строку дает ошибку — что-то вроде «sorry, streaming operators are not supported».

Чтобы не быть голословным, объединяю все описанные выше методы в один Verilog Testbench файл и пробую симулировать в Modelsim.

//source bits which should be reversed
reg [7:0]src;

//this method does not work! no reverse bits!!
wire [0:7]re1; assign re1 = src;

//method 2, use reverse function
wire [7:0]re3; assign re3 = fbit_reverse(src);

//method 3, use reversing module
wire [7:0]re4;
mod_bit_reverse #(.NUM_BITS(8)) my_reverse_module( .in(src), .out(re4) );

//method 4
//SystemVerilog streaming operators do not work neither with icarus verilog nor with Quartus Prime
//Modelsim Starter Edition v10.5b supports this
wire [7:0]re5;
assign re5 = Читайте также: Шины 155 65 r13 в брянске

src = 8’h1C; #1;
$display(«source %X»,src);
$display(«try1 reverse %X»,re1);
$display(«try2 reverse %X»,re2);
$display(«try3 reverse %X»,re3);
$display(«try4 reverse %X»,re4);
$display(«try5 reverse %X»,re5);
#10;
#10;
$finish();
end

function [7:0] fbit_reverse ( input [7:0] data );
integer i;
begin
for ( i=0; i begin
fbit_reverse[7-i] = data[i];
end
end
endfunction

module mod_bit_reverse( in, out );
parameter NUM_BITS = 16;
input wire [NUM_BITS-1:0]in;
output wire [NUM_BITS-1:0]out;
genvar i;
generate
for (i=0; i begin
assign out[NUM_BITS-1-i] = in[i];
end
endgenerate
endmodule

Еще напишу вспомогательный файл TB.DO со списоком команд симулятора Modelsim:

vlib work1
vlog -work work1 tb.v
vsim work1.tb
run -all

Запускаю в командной строке Modelsim:

>vsim -c -do tb.do

Шина бит как записать

В консоли видно, как верилоговская системная функция $display выводит развернутый байт для методов 2, 3, 4 и 5. Метод 1, как я и говорил — не работает.

Кроме того, тестбенч создает файл OUT.VCD, который содержит информацию о сигналах проекта и который можно посмотреть с помощью gtkwave. Вот эти сигналы (скриншот программы gtkwave):

Шина бит как записать

Ну и напоследок, пожалуй нужно заметить, что любая логика разворачивающая шину, даже модуль mod_bit_reverse, в микросхеме FPGA абсолютно не занимает никакого места. И это правильно, ведь фактически, никакой логики там и нет — есть просто переименование сигналов.

Видео:Первый Бит | Маркировка шин: подключись к системе за 5 простых шагов. Честный знакСкачать

Первый Бит | Маркировка шин: подключись к системе за 5 простых шагов. Честный знак

Компьютер на логических микросхемах: исполнение инструкций

В голосовании к прошлой статье с небольшим отрывом победила видеокарта, но так как у нас тут не демократия, а конституционная монархия, про видеокарту будет следующая статья, а эта – про кодирование инструкций и их исполнение.

Видео:В ЧЕМ ОТЛИЧИЕ ЛИЗИНГ ОТ ЭКСКЛЮЗИВ В БИТАХ? ЧТО ЛУЧШЕ ПОКУПАТЬ! КАК ГРУЗИТЬ НА ПЛОЩАДКИ ПРАВИЛЬНОСкачать

В ЧЕМ ОТЛИЧИЕ ЛИЗИНГ ОТ ЭКСКЛЮЗИВ В БИТАХ? ЧТО ЛУЧШЕ ПОКУПАТЬ! КАК ГРУЗИТЬ НА ПЛОЩАДКИ ПРАВИЛЬНО

Флаги

Перед тем, как перейти к самим инструкциям, расскажу о флагах. В процессоре флаги – это однобитовые значения, которые изменяются в результате арифметических действий (или других событий) и используются для условных переходов или других условных операций. В моем процессоре четыре флага:

O – переполнение или знаковый перенос.

При программировании на ассемблере нет знаковых или беззнаковых чисел: любое число можно рассматривать либо так, либо этак. Например, утверждения «регистр A содержит -1» и «регистр A содержит 255» значат одно и то же. Всё дело в интерпретации двоичного числа человеком. Рассмотрим пример: в восьмибитном регистре A находится двоичное значение 1000 0010, а в B – 0111 1101. Посмотрим на результаты сложения и вычитания этих чисел и их знаковых и беззнаковых интерпретаций.

В случае со сложением беззнаковый результат «неправильный»: должно получиться 256, но из-за переполнения байта получается ноль. В случае с вычитанием наоборот: должно получиться -252, но такое число нельзя закодировать в 8 бит, поэтому получается 4. Для обнаружения этих ситуаций и нужны флаги С и O: С устанавливается в случае «неправильных» беззнаковых результатов, а O – в случае «неправильных» знаковых. Подробнее можно почитать тут.

Набор инструкций

В моем процессоре пять классов инструкций: арифметические, загрузка, сохранение, загрузка константы и переходы.

Код любой инструкции имеет размер один байт. Этот байт в начале каждого цикла загружается в регистр текущей инструкции IR. Таким образом процессор «знает», какую инструкцию он сейчас исполняет.

Арифметические инструкции

Старший бит кода арифметической инструкции ноль. Он и определяет этот класс инструкций.

Следующие четыре бита – код арифметической операции, напрямую подаваемый на вход АЛУ . Всего 16 операций:

ADC – сложение с переносом,

SBB – вычитание с переносом,

XOR – побитовое исключающее ИЛИ,

SHL – сдвиг влево на один бит,

SHR – логический сдвиг вправо на один бит,

SAR – арифметический сдвиг вправо на один бит,

EXP – устанавливает регистр в 00 или FF в зависимости от флага переноса.

Дальше идет бит инверсии, определяющий порядок операндов. Как мы помним, из-за жесткой привязки выхода регистра A к первому входу АЛУ один из аргументов должен обязательно быть А. Этот бит и определяет, первый это аргумент (0) или второй (1).

Пояснение про порядок операндов

Если вы не знакомы с ассемблером (диалект Intel), то нужно помнить, что первый операнд инструкции – это то, куда записывается результат. Например:

Тут результат вычитания a из b будет записан в b. На си-подобном языке это было бы так:

И последние два бита – это индекс регистра, используемого в качестве второго операнда.

Комбинация 00 должна соответствовать регистру A, но он не подключен к ведущей на второй вход АЛУ шине, поэтому при использовании этой комбинации на этой шине будет ноль благодаря подтягивающим резисторам. Таким образом возможна арифметика между A (фиксированным первым операндом) и нулем.

Для примера рассмотрим инструкцию ADD PL, A . Битовое представление будет следующим:

бит инверсии установлен ( 1 ), так как А – второй аргумент,

Читайте также: Контроллер универсальной последовательной шины usb asrock

Итого 01001110 или 0x4E . На знакомой блок-схеме исполнение этой инструкции будет выглядеть так:

Красными стрелками обозначены сигналы, которые будут активны при исполнении этой инструкции. Звездочки показывают, какое устройство активно, т.е. определяет уровни сигналов, на конкретной шине. Теперь рассмотрим временную диаграмму исполнения этой инструкции:

Примечание для дотошных

На диаграмме все сигналы для простоты имеют активный уровень 1, хоть реально это может быть и не так, многие сигналы инверсны.

Самый верхний сигнал на диаграмме – тактовый сигнал. Следующий за ним сигнал cycle – это просто тактовый сигнал с частотой в два раза ниже. Он определяет цикл исполнения инструкции: загрузка опкода или исполнение.

По нисходящему фронту тактового сигнала (2) значение с шины данных защелкивается в регистр IR, так как сигнал записи в этот регистр we_ir активен.

Дальше (3) cycle переключается в 1, что означает исполнение инструкции. Одновременно с ним переключаются необходимые для исполнения этой конкретной инструкции сигналы:

we_pl указывает, что значение со внутренней шины должно быть записано в регистр PL;

oe_pl_alu – что выходной буфер PL должен включиться и подать напряжение на шину, ведущую в ALU;

oe_alu – что АЛУ должно активировать свой выходной буфер и подать результат на внутреннюю шину;

we_flags – что в регистр флагов тоже должно быть записано значение.

Сигнал we_ir , наоборот, отключается, чтобы значение в IR сохранилось еще на такт. А благодаря активному сигналу inc_ip по нисходящему фронту clk счетчик инструкции инкрементируется (4).

Вся запись в регистры происходит по нисходящему фронту clk . Таким образом, между восходящим фронтом (3), когда управляющие сигналы переключаются, и нисходящим (4) значения на всех шинах успевают установиться, и в регистры попадают правильные значения.

Когда cycle возвращается в ноль (5), инструкцию можно считать выполненной. На шине данных уже находится опкод следующей инструкции, который будет загружен в IR в момент времени (6).

Итого, арифметическая инструкция занимает два такта.

Инструкции INC, DEC, NOT, NEG, SHL, SHR, SAR, EXP принимают один аргумент, хоть и кодируются так же, как и остальные. Можно считать, что второй аргумент они просто игнорируют.

Еще один момент: MOV – это тоже «арифметическая» инструкция, поэтому она должна менять флаги ( we_flags активен). Это очень неудобно при программировании, поэтому в случае этой конкретной операции we_flags остается неактивным, флаги сохраняются.

Загрузка константы

Здесь первые три бита опкода должны быть 110 , а последние два кодируют регистр. Иксами помечены биты, значение которых неважно. Сразу за опкодом в памяти следует константа, которую надо загрузить. На ассемблере эта инструкция обозначается LDI .

Код инструкции: 11000001 01011010

Здесь вступает в игру новый сигнал – supercycle , который является замедленным в два раза cycle . Благодаря ему исполнение инструкции LDI занимает четыре такта. IP инкрементируется два раза (4 и 8). В середине (6), когда на шине данных константа для загрузки, сигналом oe_d_di активируется буфер, соединяющий внешнюю шину данных со внутренней, и значение с этой шины защелкивается в регистр B благодаря активному we_b .

Активные сигналы в момент времени (6)

Загрузка из памяти

Последние два бита так же, как и в LDI, кодируют регистр, в который будет загружено значение. Как вы помните, адрес памяти, откуда будет взят байт, хранится в PH:PL.

Здесь по уже знакомому сигналу cycle активируется сигнал addr_p (3), по которому на шину адреса выводится значение из PH:PL вместо IP. Как и в LDI, значение с внешней шины данных передается на внутреннюю, а с нее по нисходящему фронту clk (4) защелкивается в нужный регистр. Инструкция исполняется за два такта.

Активные сигналы в момент времени (4)

Сохранение в память

Здесь под код регистра отводится только один бит (A или B), потому что сохранение PL или PH не имеет смысла: в них хранится адрес той ячейки, куда сохраняем!

На этой диаграмме шина D показана иначе, чем раньше: тут показано то значение, которое устанавливает на нее процессор. По умолчанию шина находится в плавающем состоянии, но по сигналу oe_b_d (3-5) на нее подается значение из регистра B. Так как в это же время сигнал oe_mem становится неактивным, конфликта на шине не будет: память ее «отпускает». По нисходящему фронту we_mem (4) значение с шины данных записывается в память по адресу из P, который, как и в случае с LD, устанавливается на шине с помощью сигнала addr_dp . Сигнал we_cycle – сдвинутый на 90º cycle – нужен для удобства получения сигнала we_mem , который занимает половину периода clk .

Читайте также: Фольксваген поло седан 2017 размеры шин

Активные сигналы в момент времени (4)

Эти тайминги работали отлично, пока я не добавил переключение банков и не стал запускать программы из ОЗУ. Тогда возникла проблема: так как сигнал we_mem устанавливается слишком быстро (3), а на шине еще старый адрес, данные в памяти портились. Чтобы это исправить, я напаял на плате модуля управления схему небольшой задержки сигнала на RC-цепочке. Получились такие тайминги:

Теперь адрес успевает установиться до того, как будет запрошена запись.

Схема для задержки сигнала

Здесь сигналы we_mem_orig и we_mem инверсны (активный ноль).

Переходы

Этот код кодирует сразу безусловные переходы, условные переходы и NOP («безусловные непереходы»).

Два бита FF кодируют флаг для проверки (Z, C, S, O).

Бит I определяет инверсию результата проверки.

Бит E определяет, будут ли вообще проверяться флаги. Если он единица, то флаги не проверяются, а результат проверки считается единицей. Поэтому, если выставлены одновременно биты E и I , то переход не произойдет (NOP), а если E выставлен, а I сброшен, то произойдет безусловно (JMP).

Диаграмма выглядит так же, как и остальные, кроме сигнала swap_p , который устанавливается в единицу, если должен быть выполнен переход. Если swap_p выставлен в единицу, по нисходящему фронту clk (4), переключается флаг, определяющий, какой из физических регистров в блоке P – это IP, а какой PH:PL.

Переключение селектора P

Видео:Влияние шин PCI-e и внутренней шины видеокарты на производительностьСкачать

Влияние шин PCI-e и внутренней шины видеокарты на производительность

Реализация

Вот и все инструкции. Имея временные диаграммы, несложно нарисовать логические схемы, которые должны выдавать все управляющие сигналы. Эти схемы реализованы на синей плате, а управляющие сигналы наглядно выведены на светодиоды.

Шина бит как записать

Модуль управления

Когда я только начинал делать процессор, я хотел сделать по-другому: чтобы быстрее получить что-то работающее, использовать ПЗУ с таблицей значений вместо дискретной логики. Оказалось, что так не получится: при переключении адресов ПЗУ выдает неопределенные значения, случайные всплески сигналов, поэтому тот вариант оказался совершенно неработоспособным. Процессор вел себя случайным и непредсказуемым образом. С АЛУ, однако, такой подход прошел, потому что значения с выхода АЛУ не используются как управляющие сигналы. Моя первая версия АЛУ была на двух микросхемах ПЗУ, но потом я его тоже переделал.

Программирование

У меня используется классическая (для C или C++) модель сборки. Компилятор выдает ассемблерный код, ассемблер делает из него объектные файлы, линкер собирает их в бинарный файл для прошивки в ПЗУ или для записи на SD-карту. Всё это управляется системой сборки SCons – ее очень просто настроить под себя и использовать нестандартные компиляторы.

Линкер оптимизирующий: умеет выкидывать неиспользуемые секции (аналог —gc-sections в GNU ld) и перемешивать их так, чтобы максимально заполнять пустые места, остающиеся от выравнивания.

Компилятор (и язык) я назвал Natrix (латинское название ужа), но по сути это урезанный Си: без неявных кастов, с ограничениями по вызову функций, без конструкций вроде union и switch . Главная проблема для компилятора – это отсутствие аппаратного стека, которую я решаю так: все локальные переменные в функциях выделяются статически, адрес возврата тоже кладется в статическую (уникальную для функции) переменную. Временные переменные для вычисления выражений тоже статические, но общие для всех функций. Аргументы и возвращаемое значение – тоже статические переменные. Такое обилие статических переменных – не проблема, так как нехватки ОЗУ никогда не наблюдается: намного раньше заканчивается память для кода (ха-ха).

Чтобы всё-таки можно было использовать рекурсию, используется программный стек. При компиляции строится граф вызовов, и если обнаружены циклы, то перед этими рекурсивными вызовами все статические переменные вызывающей функции кладутся на стек, а потом восстанавливаются. Это очень дорого, но рекурсия работает.

Умножение, деление и сдвиг на переменную программные и заменяются на вызовы встроенных функций. Простое умножение (переменной-байта на константу) и сдвиги на константу встраивается.

Пример сгенерированного кода: сдвиг 32-битного числа

Всё это (компилятор, ассемблер и линкер) написано на питоне, потому что я хотел как можно скорее получить работающий результат. И если для ассемблера и линкера это оправдано из-за простоты, а в ассемблере еще и дает преимущество в виде простого вычисления константных выражений с помощью eval , то писать компиляторы на питоне я никому не посоветую. Да, первый результат получился быстро, но отлавливать ошибки и поддерживать код очень сложно.

Первый эмулятор тоже был на питоне, но потом я его переписал на Rust, что ускорило его раз в пять.

Множество Мандельброта (скриншот из эмулятора)

Примечание

Временные диаграммы нарисованы в wavedrom, а блок-схемы в Inkscape. Электрические схемы – скриншоты из KiCAD.

📸 Видео

Очень важные параметры видеокарты, на которые редко обращают внимание при покупке!Скачать

Очень важные параметры видеокарты, на которые редко обращают внимание при покупке!

ЗАПИСЬ и СВЕДЕНИЕ ДОМА НА БЕСПЛАТНЫЙ БИТ В FL STUDIO 20Скачать

ЗАПИСЬ и СВЕДЕНИЕ ДОМА НА БЕСПЛАТНЫЙ БИТ В FL STUDIO 20

КАК НАУЧИТЬСЯ ПИСАТЬ БИТЫ?Скачать

КАК НАУЧИТЬСЯ ПИСАТЬ БИТЫ?

Что будет если налить КОЛУ на ВИДЕОКАРТУ?Скачать

Что будет если налить КОЛУ на ВИДЕОКАРТУ?

Почему в видеокартах rx6800, rx6900 шина 256 бит?Скачать

Почему в видеокартах rx6800, rx6900 шина 256 бит?

КАК ПИСАТЬ БИТЫ В FL STUDIO НОВИЧКУ? / FL STUDIO 20 ЗА 5 МИНУТСкачать

КАК ПИСАТЬ БИТЫ В FL STUDIO НОВИЧКУ? / FL STUDIO 20 ЗА 5 МИНУТ

СПОРИМ Я НАУЧУ ТЕБЯ ПИСАТЬ БИТЫ ЗА 18 МИНУТ? АЛГОРИТМ С НУЛЯ ДО ПРО! #BeatmakerWay 1Скачать

СПОРИМ Я НАУЧУ ТЕБЯ ПИСАТЬ БИТЫ ЗА 18 МИНУТ? АЛГОРИТМ С НУЛЯ ДО ПРО! #BeatmakerWay 1

Учусь Писать Биты За 24 ЧасаСкачать

Учусь Писать Биты За 24 Часа

Как Всегда Идеально Сводить Биты ?? Пошаговая Инструкция Как Свести Бит + FREE DrumkitСкачать

Как Всегда Идеально Сводить Биты ?? Пошаговая Инструкция Как Свести Бит + FREE Drumkit

КАК НАПИСАТЬ БИТ В FL STUDIO / СВЕДЕНИЕ И МАСТЕРИНГ!!!!Скачать

КАК НАПИСАТЬ БИТ В FL STUDIO / СВЕДЕНИЕ И МАСТЕРИНГ!!!!

КАК СДЕЛАТЬ БИТ И ЗАПИСАТЬ ТРЕК НА ТЕЛЕФОНЕ В ПРОГРАММЕ BandLab | БИТ ДЛЯ НАЧИНАЮЩИХ НА АНДРОИД 2021Скачать

КАК СДЕЛАТЬ БИТ И ЗАПИСАТЬ ТРЕК НА ТЕЛЕФОНЕ В ПРОГРАММЕ BandLab | БИТ ДЛЯ НАЧИНАЮЩИХ НА АНДРОИД 2021

Почему писать PLUG — это очень просто.Скачать

Почему писать PLUG — это очень просто.

КАК ПИСАТЬ ЖИРНЫЕ И КАЧЁВЫЕ БИТЫСкачать

КАК ПИСАТЬ ЖИРНЫЕ И КАЧЁВЫЕ БИТЫ
Поделиться или сохранить к себе:
Технарь знаток