Untitled
unknown
verilog
4 years ago
5.3 kB
9
Indexable
/*
* The MIT License (MIT)
* Copyright (c) 2021 Ada Brzoza
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
* THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
module cpu (
//wejscia kontrolne
input clk,
input reset_n,
//interfejs pamieci
output reg [3:0] mem_address,
input [7:0] mem_data_r,
output reg [7:0] mem_data_w,
output reg mem_we,
//interfejs do debugowania
output [1:0] dbg_state,
output [3:0] dbg_r0,
output [3:0] dbg_r1,
output [3:0] dbg_pc
);
reg [1:0] state; //przechowuje aktualny stan mikroprocesora
reg [3:0] pc; //rejestr PC - licznik programu
reg [7:0] opcode; //rejestr do tymczasowego przechowywania kodu instrukcji pobranego z pamieci
reg [3:0] r0; //rejestr r0
reg [3:0] r1; //rejestr r1
//przypisania zapewniajace podglad wewnetrznych sygnalow
assign dbg_state = state;
assign dbg_r0 = r0;
assign dbg_r1 = r1;
assign dbg_pc = pc;
//glowna maszyna stanow mikroprocesora:
always@(posedge clk, negedge reset_n)
if(reset_n == 0) //po wykryciu aktywnosci na sygnale reset_n...
begin
state <= 0; //zerujemy podstawowe rejestry mikroprocesora
pc <= 0;
r0 <= 0;
r1 <= 0;
mem_we <= 0; //zerujemy sygnaly zezwolenia na zapis do pamieci operacyjnej
end
else
begin
case(state)
0:
begin
state <= 1; //przechodzimy do nastepnego stanu
mem_we <= 0; //wylaczamy sygnal zezwolenia na zapis do pamieci
//(jesli byl uaktywniony w poprzednim cyklu, a jesli nie, to pozostaje wyzerowany)
mem_address <= pc; //na magistrali adresowej wystawiamy adres rozkazu do pobrania
end
1:
begin
state <= 2;
opcode <= mem_data_r; //odczytana dana z pamieci traktujemy jako kod operacji
pc <= pc + 1; //zwiekszamy zawartosc PC o 1
end
2:
begin
state <= 3;
if(opcode[7]==0) //jesli bit 7 ma wartosc 0, to operacja arytmetyczna lub skok
begin
case(opcode[6:4]) //analizujemy bity 6, 5 i 4...
3'b000: //jesli wszystkie sa ustawione na 000...
begin
//wykonujemy skok pod adres dany stala natychmiastowa
pc <= opcode[3:0]; //zaladuj do PC wartosc znaleziona w bitach 3:0 kodu instrukcji
end
3'b010: //jesli bity 6:4 maja wartosc 010...
begin
r0 <= r0 + r1; //wykonujemy dodawanie: add r0, r1 (r0 = r0 + r1)
end
3'b011:
begin
r1 <= r0 + r1;
end
3'b001:
begin
{r0, r1} <= r0 * r1;
end
endcase
end
else //gdy bit 7 != 0, to kod operacji stanowi instrukcje load, store lub move
begin
if(opcode[6]) //bit 6 == 1 -> instrukcja load/store
begin
mem_address <= opcode[3:0]; //...wtedy adres znajduje sie w bitach 3:0
if(opcode[5]) //jesli bit 5 jest ustawiony, to mamy do czynienia z zapisem (store)
begin
if(opcode[4]) //bitem 4 wybieramy, ktory rejestr zapisac (r0 gdy 0 lub r1 gdy 1)
mem_data_w <= r1; //wystawiamy na magistrale zapisu do pamieci zawartosc r1
else
mem_data_w <= r0; //wystawiamy na magistrale zapisu do pamieci zawartosc r0
end
end
else //jesli bit 6 ma wartosc 0...
begin //to mamy do czynienia z instrukcjami wpisywania stalej natychmiastowej lub move
case(opcode[5:4]) //analizujemy bity 5 i 4
2'b00: r0 <= opcode[3:0]; //imm to r0 (stala natychmiastowa do r0)
2'b01: r1 <= opcode[3:0]; //imm to r1 (stala natychmiastowa do r1)
2'b10: r0 <= r1; //mov r0, r1 (kopiowanie r0 = r1)
2'b11: r1 <= r0; //mov r1, r0 (kopiowanie r1 = r0)
endcase
end
end
end
3: //kontyuacja operacji zapisu lub odczytu
begin
state <= 0;
//obsluga zapisu do pamieci
if(opcode[7:5]==3'b111)
mem_we <= 1; //wystawiamy aktywny sygnal zezwolenia na zapis do pamieci (mem_address byl ustawiony wczesniej)
//obsluga odczytu z pamieci
if(opcode[7:5]==3'b110) //jesli byla operacja odczytu
begin
if(opcode[4]==0) //wybieramy rejestr
r0 <= mem_data_r; //wpisujemy odczytana z pamieci liczbe do rejestru r0
else
r1 <= mem_data_r; //wpisujemy odczytana z pamieci liczbe do rejestru r1
end
end
endcase
end
endmodule
Editor is loading...