Я слежу за сериалом Бена Итера на YouTube на Создание 8-битного макета компьютера. Я пытаюсь смоделировать его схему в Logisim , так как у меня нет ни макета, ни Arduino
. В настоящее время я работаю над 8-разрядным десятичным дисплеем. Вот ссылка на текущее видео: BenEater :: Youtube
Я нахожусь в том месте, где он программирует свою EEPROM с помощью байт-кода через Arduino . Я использую его исходный код в качестве ссылки, которую можно найти здесь: BenEater :: Github
У меня возникла проблема с генерированием правильных байт-кодов для вождение набора 7-сегментных дисплеев в их правильные адреса для файла ПЗУ Logisim. Я использую C ++ для генерации байтовых кодов и печати шестнадцатеричных значений в текстовый файл.
Я не уверен, откуда возникла проблема, но я хотел бы знать, генерирует ли мой C ++ ту же последовательность байтов, что и код Бена Итера, для его Arduino для программирования его EEPROM? Я пытаюсь сузить эту ошибку настолько, насколько смогу. Сначала я хочу проверить, связано ли это с C ++! Поэтому основное внимание здесь уделяется сравнению с кодом Бена на его github и моей реализацией его на C ++.
Некоторые другие связанные вопросы и проблемы: Если мой код C ++ генерирует ту же последовательность байтов, то где еще я могу искать, чтобы устранить эту проблему? Может ли быть так, что я пишу это в текстовый файл вместо двоичного? Может ли это быть кодировка текстовых редакторов и возврат строк и т. Д. c? Может ли это быть проблемой с Logisim? Если я копирую байты из текстового файла, возвращает ли строка или eol играет роль в смещении байтовых адресов?
Вот мой код C ++, который эмулирует 11-битную адресуемую EEPROM размером 2 КБ, и алгоритмы для генерации байтового кода для 7-сегментного дисплея. Я записываю его в текстовый файл и пытаюсь скопировать шестнадцатеричные значения в модуль ROM Logisim. В Logisim модуль ПЗУ имеет ширину бита адреса 11 и ширину бита данных 8.
#include <array>
#include <bitset>
#include <iostream>
#include <iomanip>
#include <fstream>
constexpr unsigned ROWS = 128;
constexpr unsigned COLS = 16;
std::array<std::bitset<8>, ROWS*COLS> rom_file = {0x00};
// Show Rom File on the console
void showRomFile() {
for (int row = 0; row < ROWS; row++) {
std::cout << std::setw(2) << std::setfill('0') << row << "0: ";
for (int col = 0; col < COLS; col++) {
if (col % 4 == 0) std::cout << " ";
std::cout << std::setw(2) << std::setfill('0') << std::hex
<< rom_file[COLS*row + col].to_ulong() << " ";
}
std::cout << std::endl;
}
}
// Print Rom File to a Text File in single byte format.
void printRomFile() {
std::fstream file;
file.open("display.txt", std::ios::out);
for (auto b : rom_file)
file << std::setw(2) << std::setfill('0') << std::hex << b.to_ulong() << " ";
/*for (int row = 0; row < ROWS; row++) {
for (int col = 0; col < COLS; col++) {
//if (col % 4 == 0) file << " ";
file << std::setw(2) << std::setfill('0') << std::hex
<< rom_file[COLS*row + col].to_ulong() << " ";
}
//file << std::endl;
}*/
file.close();
}
int main() {
// Bit patterns for 7 segment display of the digits 0...9
std::bitset<8> digits[] = { 0x7e, 0x30, 0x6d, 0x79, 0x33, 0x5b, 0x5f, 0x70, 0x7f, 0x7b };
// unsigned
for (int val = 0; val <= 255; val++) {
rom_file[val] = digits[val % 10];
rom_file[val + 256] = digits[(val / 10) % 10];
rom_file[val + 512] = digits[(val / 100) % 10];
rom_file[val + 768] = 0;
}
// signed twos complement
for (int val = -128; val <= 127; val++) {
rom_file[(unsigned)val + 1024] = digits[abs(val) % 10];
rom_file[(unsigned)val + 1280] = digits[abs(val / 10) % 10];
rom_file[(unsigned)val + 1536] = digits[abs(val / 100) % 10];
if (val < 0)
rom_file[(unsigned)val + 1792] = 0x01;
else
rom_file[(unsigned)val + 1792] = 0x00;
}
showRomFile();
printRomFile();
/*
// unsigned
for (int val = 0; val <= 255; val++)
rom_file[val] = digits[val % 10];
for (int val = 0; val <= 255; val++)
rom_file[val+256] = digits[(val / 10) % 10];
for (int val = 0; val <= 255; val++)
rom_file[val+512] = digits[(val / 100) % 10];
for (int val = 0; val <= 255; val++)
rom_file[val+768] = 0;
*/
// signed twos complement
/*for (int val = -128; val <= 127; val++)
rom_file[static_cast<unsigned>(val) + 1024] = digits[std::abs(val) % 10];
for (int val = -128; val <= 127; val++)
rom_file[static_cast<unsigned>(val) + 1280] = digits[std::abs(val/10) % 10];
for (int val = -128; val <= 127; val++)
rom_file[static_cast<unsigned>(val) + 1536] = digits[std::abs(val/100) % 10];
for (int val = -128; val <= 127; val++) {
if (val < 0)
rom_file[static_cast<unsigned>(val) + 1792] = 0x01;
else
rom_file[static_cast<unsigned>(val) + 1792] = 0;
}
showRomFile()
printRomFile()
*/
return 0;
}
Если вы посмотрите мой код и даже закомментированные разделы, вы увидите что я попытался изменить интервал, и новые строки и т. д. c, чтобы увидеть, если они вызывают проблемы ... Первоначально я проходил для l oop для каждого случая, но для этого вопроса я объединил все 4 раздела в их соответствующие циклы для подписанных и неподписанных разделов. Идея состоит в том, что байтовые коды без знака должны быть в нижней половине или 1 st 1 КБ файла ПЗУ, где байтовые коды со знаком должны быть в верхней половине или 2 nd 1 КБ.
Вот соответствующая часть его кода для программирования EEPROM через его Arduino :
Код Бена Эотера:
void setup() {
// put your setup code here, to run once:
pinMode(SHIFT_DATA, OUTPUT);
pinMode(SHIFT_CLK, OUTPUT);
pinMode(SHIFT_LATCH, OUTPUT);
digitalWrite(WRITE_EN, HIGH);
pinMode(WRITE_EN, OUTPUT);
Serial.begin(57600);
// Bit patterns for the digits 0..9
byte digits[] = { 0x7e, 0x30, 0x6d, 0x79, 0x33, 0x5b, 0x5f, 0x70, 0x7f, 0x7b };
Serial.println("Programming ones place");
for (int value = 0; value <= 255; value += 1) {
writeEEPROM(value, digits[value % 10]);
}
Serial.println("Programming tens place");
for (int value = 0; value <= 255; value += 1) {
writeEEPROM(value + 256, digits[(value / 10) % 10]);
}
Serial.println("Programming hundreds place");
for (int value = 0; value <= 255; value += 1) {
writeEEPROM(value + 512, digits[(value / 100) % 10]);
}
Serial.println("Programming sign");
for (int value = 0; value <= 255; value += 1) {
writeEEPROM(value + 768, 0);
}
Serial.println("Programming ones place (twos complement)");
for (int value = -128; value <= 127; value += 1) {
writeEEPROM((byte)value + 1024, digits[abs(value) % 10]);
}
Serial.println("Programming tens place (twos complement)");
for (int value = -128; value <= 127; value += 1) {
writeEEPROM((byte)value + 1280, digits[abs(value / 10) % 10]);
}
Serial.println("Programming hundreds place (twos complement)");
for (int value = -128; value <= 127; value += 1) {
writeEEPROM((byte)value + 1536, digits[abs(value / 100) % 10]);
}
Serial.println("Programming sign (twos complement)");
for (int value = -128; value <= 127; value += 1) {
if (value < 0) {
writeEEPROM((byte)value + 1792, 0x01);
} else {
writeEEPROM((byte)value + 1792, 0);
}
}
// Read and print out the contents of the EERPROM
Serial.println("Reading EEPROM");
printContents();
}
Это то, что он использует для создания битовых комбинаций для установки определенных c сегментов дисплея на основе 11-битного адреса, который будет передан в EEPROM . Структура его 11-битного адреса выглядит следующим образом:
Нижние восемь битов адреса будут иметь значения [0,255]
в режиме unsigned
или [-128,127]
если в режиме signed
используется twos дополнить .
bits [0..7] = value part of the address
bits [8..9] = digit placement
bit [10] = signed/unsigned flag
Полный 11-битный адрес будет генерировать байтовое значение в двоичном формате, а битовая последовательность этого значения будет определять, какие сегменты будут включены или выключены.
Например:
Если мы передадим 101
в качестве адреса в EEPROM , он получит значение 01011011
в двоичном формате, где значение (0x5b)
было написано по этому адресу. Относительно его схемы эта битовая комбинация будет подсвечивать 5
на 7-сегментном дисплее его макета.
У него четыре из этих дисплеев подключены параллельно, и он использует 555-Timer для генерации тактового импульса, который будет запускать 2-бит флип-флоп счетчик . Этот 2-битный счетчик используется слева на два бита после восьмибитной части адреса. Эти два бита будут определять, какой из четырех 7-сегментных дисплеев будет активным, в зависимости от расположения di git в пределах значения. Он также использует двухбитный декодер для управления, когда каждый указанный сегмент c должен работать. Он связывает это с анодами своих 7-сегментных дисплеев. Теперь в Logisim есть все сегментирующие выводы, но нет анода или диода для active-high или active-low поскольку они есть как часть страницы свойств объектов. В проекте My Logisim я не могу подключить ie линейный декодер 2-4 к анодам из 7 сегментов, поэтому я использовал разделители проводов, чтобы установить 8 сохраненных битов, затем я использовал ВОСЕМЬ 2-4 демультиплексоров для имитации того же самого process.
Ниже приведен пример генерации кратного значения di git:
Мы сгенерируем десятичное значение 123 в четырех ступенях, каждая из которых соответствует тактовому импульсу. как в подписи, так и без подписи.
Value Address[0..8]: `01111011` - `0x07B`
// signed[0]
Stages: Stored Byte-Output: Display Array: Full Address
Counter[00]: 01111001 - 0x79 [ ][ ][ ][3] 0 00 01111011 - 0x07B
Counter[01]: 01101101 - 0x6D [ ][ ][2][ ] 0 01 01111011 - 0x17B
Counter[10]: 00110000 - 0x30 [ ][1][ ][ ] 0 10 01111011 - 0x27B
Counter[11]: 00000000 - 0x00 [ ][ ][ ][ ] 0 11 01111011 - 0x37B
// signed[1]
Counter[00]: 01111001 - 0x79 [ ][ ][ ][3] 1 00 01111011 - 0x47B
Counter[01]: 01101101 - 0x6D [ ][ ][2][ ] 1 01 01111011 - 0x57B
Counter[10]: 00110000 - 0x30 [ ][1][ ][ ] 1 10 01111011 - 0x67B
Counter[11]: 00000000 - 0x00 [ ][ ][ ][ ] 1 11 01111011 - 0x77B
Вышесказанное должно иллюстрировать намерение того, что пытается быть достигнуто. Я пытаюсь смоделировать это в Logisim
, и вот как выглядит моя схема:
Это нижняя и правая часть схемы это не связано с cpu-bus
частью.
Это прекрасно работает и должно делать то же самое для всех значений без знака из [0-255]
. Когда в адресе включен бит signed
, если значение равно [0,127]
, все должно работать так же, как счетчики unsigned
. Когда значение равно [-128,-1]
, расположение di git должно быть таким же, однако в крайнем левом углу di git должно отображаться [-]
, которое является средним сегментом, и его двоичное кодирование равно 0x01
.
Теперь, прежде чем я начну работать со значениями signed
. У меня проблема в unsigned
. Если я введу десятичное значение 127
или 01111111
, все будет работать как надо, но как только я запускаю бит 128
со значением адреса 10000000
, я начинаю сталкиваться с проблемами. Я получаю 128 от первых трех тактовых импульсов, но на четвертом, где это идет не так! Я дам таблицу, чтобы показать, что происходит в Logisim:
Value Address[0..8]: `10000000` - `0x080`
// signed[0]
Stages: Stored Byte-Output: Display Array: Full Address
Counter[00]: 01111111 - 0x80 [ ][ ][ ][8] 0 00 10000000 - 0x080
Counter[01]: 01101101 - 0x6D [ ][ ][2][ ] 0 01 10000000 - 0x180
Counter[10]: 00110000 - 0x30 [ ][1][ ][ ] 0 10 10000000 - 0x280
Counter[11]: 01111111 - 0x7f [8][ ][ ][ ] 0 11 10000000 - 0x380
// the above should be:
Counter[11]: 00000000 - 0x00 [ ][ ][ ][ ] 0 11 10000000 - 0x380
// signed[1] should be -1
Counter[00]: 01101101 - 0x6D [ ][ ][ ][2] 1 00 10000000 - 0x480
// should be:
Counter[00]: 00110000 - 0x30 [ ][ ][ ][1] 1 00 10000000 - 0x480
Counter[01]: 00110000 - 0x30 [ ][ ][1][ ] 1 01 10000000 - 0x580
// should be:
Counter[01]: 00000001 - 0x01 [ ][ ][-][ ] 1 01 10000000 - 0x580
Counter[10]: 00000001 - 0x01 [ ][-][ ][ ] 1 10 10000000 - 0x680
// should be:
Counter[10]: 00000000 - 0x00 [ ][ ][ ][ ] 1 10 10000000 - 0x680
Counter[11]: 01111111 - 0x7f [8][ ][ ][ ] 1 11 10000000 - 0x780
// the above should be:
Counter[11]: 00000000 - 0x00 [ ][ ][ ][ ] 1 11 10000000 - 0x780
Как вы видите, мне кажется, что почему-то я отключен на один байт-адрес и я даже не знаю, является ли это единственной проблемой или ошибкой.
Я не знаю, что является причиной этой ошибки. Я не уверен, находится ли это в коде C ++ или нет, если у меня есть неуместное соединение на проводке, которое не появляется так, потому что я могу генерировать каждую ди git [0,9] ... Я не Не знаю, относится ли это к тому, как текстовые файлы сохраняются, копируются и вставляются, я даже не уверен, является ли это One Off Bug или нет, но это мое текущее подозрение ...
Я полностью застрял и зашел в тупик, потратив на это много часов, и я хотел бы продолжить серию видео ...
Я знаю, что это довольно долго, но немного вперед, но заранее ; Я полностью благодарен за любую помощь, советы, предложения, советы, помощь в устранении неполадок и т. Д. c. Если вам нужна дополнительная информация, снимки экрана, файлы проекта и т. Д. c. пожалуйста, не стесняйтесь спрашивать, и я постараюсь предоставить их, когда это возможно, и спасибо за ваше время и внимание!