
Если сравнивать с прошлой схемой, обнаружим:
- добавились входы SrcStall и SrcDiscard. То, что они отсутствовали на старой схеме, мне сейчас показалось было криминалом, но я так и не смог придумать сценария, когда это привело бы к проблеме, будь то ошибочное срабатывание байпаса или ошибочная задержка на один такт. Всё-таки, когда АЛУ всех останавливает, особенно интересных ситуаций не возникает :) А вот новой схеме, у меня такое чувство, без этих входов не обойтись!
- ушёл модуль EnableBypass, точнее, переехал внутрь ALUoutput, а в ALUcontrol перестала поступать шина SrcAddr - мы как бы разделили "зоны ответственности".
- добавились выходы DestStallReq, Busy и SBusy. Первый будет останавливать процессор, если нам нужен результат работы АЛУ, а оно ещё вкалывает. Два других будут вести в QuatCorePC, для корректной работы условных переходов, завязанных на АЛУ. Busy будет управлять работой JO / JNO, а SBusy (sign busy) - работой JL / JGE. Этот SBusy можно просто соединить с Busy, а можно ещё пожадничать - и выдавать на него единичку лишь на тех командах АЛУ, которые воздействуют на флаг знака.
Модуль ALUoutput мы уже переделали, из QuatCoreALUoutput в QuatCorePipelineALUoutput:
module QuatCorePipelineALUoutput (input clk, input [7:0] SrcAddr, input [16:0] Acc, input [15:0] C, input SrcDiscard, input SrcStall, input busy, output [15:0] Q, output isOFLO, output DestStallReq, output reg BypassEn = 1'b0); assign isOFLO = (Acc[16] != Acc[15]); wire [1:0] mode; //00: Q = -32768 //01: Q = 32767 //10: Q = Acc[15:0] //11: Q = C assign mode[1] = SrcAddr[1] | ~isOFLO; assign mode[0] = SrcAddr[1] & SrcAddr[0] | (~SrcAddr[1]) & Acc[15] & (~Acc[16]); assign Q = (mode == 2'b00)? 16'h8000 : (mode == 2'b01)? 16'h7FFF : (mode == 2'b10)? Acc [15:0]: C; wire isOurAddr = (SrcAddr[7:3] == 5'b1000_0) & (~SrcDiscard) & (~SrcStall); assign DestStallReq = isOurAddr & busy; always @(posedge clk) BypassEn <= isOurAddr; endmodule
Здесь можно увидеть логику формирования переполнения, а также как происходит насыщение результата, если выбрана команда Acc, а не UAC (Unsigned Acc - там аккумулятор берётся "как есть").
Ну и сразу внесём изменения в QuatCorePC:

В сравнении с прошлой схемой, здесь чуть переехал вход DestStall: раньше он шёл в нижний модуль, теперь туда он не идёт, взамен - в relJumpDecision. Так оно логичнее. Ну и сам этот модуль заметно "растолстел": в него добавились входы ALUbusy и ALUsbusy, а также выход SrcStallReq.
Вот его код:
module QuatCorePCpipelineRelJumpDecision ( input isNeg, input isOFLO, input iZ, input jZ, input kZ, input iEQk, input [7:0] DestAddr, input DestStall, input ALUbusy, input ALUsbusy, output DoJump, output SrcStallReq); wire isOurOp = (DestAddr[7:5] == 3'b101)&DestAddr[3]&(~DestStall); wire isLOOP = isOurOp & (~DestAddr[4]); wire DoiLOOP = isLOOP & (DestAddr[1:0] == 2'b00) & (~iZ); wire DojLOOP = isLOOP & (DestAddr[1:0] == 2'b01) & (~jZ); wire DokLOOP = isLOOP & (DestAddr[1:0] == 2'b10) & (~kZ); wire DoJik = isLOOP & (DestAddr[1:0] == 2'b11) & (iEQk ^ DestAddr[2]); wire isFlags = isOurOp & DestAddr[4]; wire DoJL = isFlags & (~DestAddr[1]) & (isNeg ^ DestAddr[2]); wire DoJO = isFlags & DestAddr[1] & (isOFLO ^ DestAddr[2]); assign DoJump = DoiLOOP | DojLOOP | DokLOOP | DoJik | DoJL | DoJO; assign SrcStallReq = (isFlags & (~DestAddr[1]) & ALUsbusy) | (isFlags & DestAddr[1] & ALUbusy); endmodule
Собственно, выражение для DoJump и не поменялось, но теперь формируется также выражение SrcStallReq, если мы выполняем JL/JGE и при этом АЛУ ещё работает над операцией, которая поменяет флаг знака, либо выполняем JO/JNO, и АЛУ ещё не завершило работу. Тогда счётчик инструкций (PC, Program Counter) остановится на то время, что SrcStallReq = 1, за это время результат может поменяться, можем передумать прыгать (или наоборот, решиться), неважно. Главное, что когда наконец-то установится SrcStallReq=0, решение уже будет правильным.
И увы, снова приходится отвлечься от этого дела, и заняться АВПКО - Анализ Видов, Последствий и Критичности Отказов. Вообще-то логичнее было бы сначала сделать и испытать прибор, а потом анализировать его, а не писать бумаги по несуществующему прибору. Но прибор нужен будет ещё через несколько лет, а бумага - прям вчера...
А ещё я страшный человек, абсолютно ненадёжный - куда-то посеял справку по 3-й форме, которую мне выдали в 2018 году, а теперь вдруг спохватились - ВЕРНИ ЕЁ НАЗАД! С тех пор я дважды переехал на работе, а ещё уеззжал на самоизоляцию и возвращался из неё, но справку вынь да положь.