mirror of
https://github.com/andreili/OriVEmu.git
synced 2025-08-23 19:34:07 +02:00
104 lines
2.6 KiB
Systemverilog
104 lines
2.6 KiB
Systemverilog
`timescale 1ps/1ps
|
|
|
|
module i8255
|
|
(
|
|
input wire i_clk,
|
|
input wire[1:0] i_addr,
|
|
input wire[7:0] i_data,
|
|
output wire[7:0] o_data,
|
|
input wire i_rd_n,
|
|
input wire i_wr_n,
|
|
input wire i_cs_n,
|
|
input wire i_reset,
|
|
input wire[7:0] i_PA,
|
|
output wire[7:0] o_PA,
|
|
input wire[7:0] i_PB,
|
|
output wire[7:0] o_PB,
|
|
input wire[7:0] i_PC,
|
|
output wire[7:0] o_PC
|
|
);
|
|
|
|
logic[7:0] reg_A;
|
|
logic[7:0] reg_B;
|
|
logic[7:0] reg_C;
|
|
logic[7:0] control_reg;
|
|
|
|
logic[7:0] Ain;
|
|
logic[7:0] Bin;
|
|
logic[7:0] Cin;
|
|
logic[3:0] Cinl;
|
|
logic[3:0] Cinh;
|
|
|
|
always_ff @(posedge i_clk)
|
|
begin
|
|
if (i_reset)
|
|
begin
|
|
reg_A <= '0;
|
|
reg_B <= '0;
|
|
reg_C <= '0;
|
|
control_reg <= 8'h9B;
|
|
end
|
|
else if ((!i_cs_n) & (!i_wr_n))
|
|
begin
|
|
case (i_addr)
|
|
2'b00: reg_A <= i_data;
|
|
2'b01: reg_B <= i_data;
|
|
2'b10: reg_C <= i_data;
|
|
2'b11:
|
|
begin
|
|
if (i_data[7] == 1'b1) // immediate value
|
|
control_reg <= i_data;
|
|
else // set/reset bit in port C
|
|
begin
|
|
if (i_data[1] == '1) // set bit
|
|
reg_C[i_data[3:1]] <= '1;
|
|
else // reset bit
|
|
reg_C[i_data[3:1]] <= '0;
|
|
end
|
|
end
|
|
endcase
|
|
end
|
|
end
|
|
|
|
logic[7:0] reg_o_A, reg_o_B, reg_o_C;
|
|
always_ff @(posedge i_clk)
|
|
begin
|
|
if (control_reg[4] == '0)
|
|
reg_o_A <= reg_A;
|
|
|
|
if (control_reg[1] == '0)
|
|
reg_o_B <= reg_B;
|
|
|
|
if (control_reg[0] == '0)
|
|
reg_o_C[3:0] <= reg_C[3:0];
|
|
|
|
if (control_reg[3] == '0)
|
|
reg_o_C[7:4] <= reg_C[7:4];
|
|
end;
|
|
|
|
assign o_PA = reg_o_A;
|
|
assign o_PB = reg_o_B;
|
|
assign o_PC = reg_o_C;
|
|
assign Cinl = control_reg[0] ? i_PC[3:0] : reg_C[3:0];
|
|
assign Bin = control_reg[1] ? i_PB : reg_B;
|
|
assign Cinh = control_reg[3] ? i_PC[7:4] : reg_C[7:4];
|
|
assign Ain = control_reg[4] ? i_PA : reg_A;
|
|
assign Cin = { Cinh, Cinl };
|
|
|
|
logic[7:0] r_data;
|
|
always_ff @(posedge i_clk)
|
|
begin
|
|
if ((!i_cs_n) & (!i_rd_n))
|
|
begin
|
|
case (i_addr)
|
|
2'b00: r_data <= Ain;
|
|
2'b01: r_data <= Bin;
|
|
2'b10: r_data <= Cin;
|
|
2'b11: r_data <= control_reg;
|
|
endcase;
|
|
end
|
|
end;
|
|
assign o_data = r_data;
|
|
|
|
endmodule
|