Научно-образовательный IT-форум

Информация о пользователе

Привет, Гость! Войдите или зарегистрируйтесь.


Вы здесь » Научно-образовательный IT-форум » Задачи и вопросы » [+] Реализация арифметических операций в СОК на языке Verilog


[+] Реализация арифметических операций в СОК на языке Verilog

Сообщений 1 страница 9 из 9

1

Здравствуйте! Мне нужно реализовать арифметические операции в системе остаточных классов (СОК) на языке Verilog. Мне не совсем понятно как реализовать такие алгоритмы на языке Verilog.

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

Код:
`define GET_DATA 3'b000
`define EXECUTE_ALGORITHM 3'b001
`define SEND_DATA 3'b010

module direct_converter(input[2:0] m, input[2:0] number, output reg[2:0] x, input[2:0] state);
  reg[2:0] m_ [2:0];
  reg[2:0] x_ [2:0];
  integer index = 2;
  
  always @(*)
  case (state)
    `GET_DATA: begin
        m_[index] = m;
        index = index - 1;
    end
    
    `EXECUTE_ALGORITHM: begin
        x_[2] = number % m_[2];
        x_[1] = number % m_[1];
        x_[0] = number % m_[0];
        index = 2;
    end
    
    `SEND_DATA: begin
            x = x_[index];
            index = index - 1;
    end
  endcase   
   
endmodule

Здесь через m передаем элементы базиса,
number - само число
через x выводим это же число, но уже преобразованное
state - состояние
Когда state равен GET_DATA мы получаем по одному числу из базиса и записываем в массив регистров m_ Когда state равен EXECUTE_ALGORITHM мы в массив регистров x_ записываем остатки от деления числа на соответствующие элементы базиса. Когда state равен SEND_DATA, мы по одному из массива x_ через выход x выводим элементы преобразованного в заданный базис числа.

Нормальное ли у меня решение? Или можно сделать по-другому и лучше? Подойдет ли он, чтобы использовать его для реализации арифметических операций? Нужно ли делать синхровход clock в этом модуле?

2

По решению - может переполняться переменная index: так как integer равнозначен reg [31:0], то при вычитании из index со значением 0, получим значение 232-1, которое выходит за границы массивов. Так же рекомендуется использование синхросигнала для избежания гонки состояний, и определение секции default для case конструкции. Возможно стоит реализовать состояние ожидания. Для реализации операций, думаю, пойдет, в целом.

Отредактировано Liennas (2020-05-08 08:55:24)

3

Liennas
Я вот вчера сделал операцию умножения и сложения без использования этого преобразователя.

Код:
module rcs_adder(input[3:0] m, input [7:0] first, input [7:0] second, input[1:0] state, input clock, output reg[3:0] result);
    reg[2:0] m_[3:0];
    reg[2:0] result_[2:0];
    integer index = 2;
    
    always @(clock)
    case (state)
        `GET_DATA: begin
            m_[index] = m;
            index = index - 1;
        end
        
        `EXECUTE_ALGORITHM: begin
            result_[2] = (first + second) % m_[2];
            result_[1] = (first + second) % m_[1];
            result_[0] = (first + second) % m_[0];
            index = 2;
        end
        
        `SEND_DATA: begin
            result = result_[index];
            index = index - 1;
        end
    endcase
endmodule
Код:
module rcs_adder(input[3:0] m, input [7:0] first, input [7:0] second, input[1:0] state, input clock, output reg[3:0] result);
    reg[2:0] m_[3:0];
    reg[2:0] result_[2:0];
    integer index = 2;
    
    always @(clock)
    case (state)
        `GET_DATA: begin
            m_[index] = m;
            index = index - 1;
        end
        
        `EXECUTE_ALGORITHM: begin
            result_[2] = (first * second) % m_[2];
            result_[1] = (first * second) % m_[1];
            result_[0] = (first * second) % m_[0];
            index = 2;
        end
        
        `SEND_DATA: begin
            result = result_[index];
            index = index - 1;
        end
    endcase
endmodule

Они почти одинаковы, отличаются только операциями в состоянии EXECUTE_ALGORITHM.

Правильно ли я их сделал? Для того чтобы не было выхода за границы массива надо проверять index  c помощью if получается?
И можно ли базис передавать не по одному числу за один такт работы схемы через вход m, а сделать вход input [ (Количество элементов в базисе - 1) * 2 : 0] m и через него сразу передать все числа базиса. Правильно ли так делать?

4

Можно и так, если на выходе нужно только СОК представление выполняемой операции.

По-моему, лучше все это объединить в один арифметический модуль и в разных секциях case конструкции описать необходимые операции, так как принципы ввода базисов и вывода результата общие и будут совпадать. Если известно заранее число базисов, можно на каждый базис выделить свой вход, тоже самое тогда можно сделать и со значениями выходов. Если нет, то передача по одному - предпочтительней, но нужна какая-то стоп посылка или последовательность посылок, чтобы унифицировать процесс передачи базисов и результатов выполнения операций. Передавать массив в виде массива между модулями вроде как нельзя.

Ограничивать index можно с помощью if, тут вы правильно подумали. Но можно отказаться от index, используя описанные выше стоп-посылки/последовательности.

Ну и очевидно опечатка в обоих модулях на входе 4-разрядная шина m, присваивается трехразрядным элементам массива m_.

Отредактировано Liennas (2020-05-08 15:34:28)

5

Я сделал один арифметический модуль, как Вы сказали. Но я немного не понял идею со стоп-посылками.

Вот код модуля:

Код:
`define ADD 2'b00
`define SUBTRACT 2'b01
`define MULTIPLY 2'b10
`define DIVIDE 2'b11

module arithmetic(input[2:0] m, input[4:0] first, input[4:0] second,
                  input[1:0] state, input clock, output reg[2:0] result);
    always @(clock)
    case (state)
        `ADD: begin
            result = (first + second) % m;
        end
        
        `SUBTRACT: begin
            result = (first - second) % m;
        end
        
        `MULTIPLY: begin
            result = (first * second) % m;
        end  
        
        default: begin
            result = 0;
        end
    endcase    
endmodule

Но зачем мне здесь стоп-посылки? Он же и без них работает.

И ещё хотел спросить насчёт операции деления. Вот в примере из википедии, там нужно вычислить 9 ^ (29-2), 9^(31-2), 9 ^ (32 -2). Но это же наверное очень большие числа, и произойдет переполнение. Как тогда реализовывать операцию деления?

https://bitbucket.org/landwatersun/forum/downloads/202005131035.png

Отредактировано DGash (2020-05-10 16:40:36)

6

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

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

7

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

8

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

9

Liennas
Хорошо, понятно. Спасибо большое за помощь!

Быстрый ответ

Напишите ваше сообщение и нажмите «Отправить»



Вы здесь » Научно-образовательный IT-форум » Задачи и вопросы » [+] Реализация арифметических операций в СОК на языке Verilog