高云SOC芯片GW1NSR-LV4CQN48的ARM总线
高云SOC芯片GW1NSR-LV4CQN48的ARM总线
国产GOWIN高云出的一款芯片是GW1NSR-LV4CQN48PC7/I6,QN48封装,资源是4608,有10个18K BRAM,以及2个PLL,内置HyperRAM 64Mb, 可以用于电机,图像测试。内置ARM-M3硬核,可以替换简单的MCU应用。
其中ARM和FPGA的总线连接是两种AHB和APB总线。以下介绍的基本总线的连接代码。
其中AHB总线是包含BURST突发模式读取数据内容。实际从波形调试可以得到每次突发模式8个数据内容。
module Gowin_AHB_Multiple
(
output wire [31:0] AHB_HRDATA,
output wire AHB_HREADY,
output wire [ 1:0] AHB_HRESP,
input wire [ 1:0] AHB_HTRANS,
input wire [ 2:0] AHB_HBURST,
input wire [ 3:0] AHB_HPROT,
input wire [ 2:0] AHB_HSIZE,
input wire AHB_HWRITE,
input wire AHB_HMASTLOCK,
input wire [ 3:0] AHB_HMASTER,
input wire [31:0] AHB_HADDR,
input wire [31:0] AHB_HWDATA,
input wire AHB_HSEL,
input wire AHB_HCLK,
input wire AHB_HRESETn
);
//The AHB BUS is always ready
assign AHB_HREADY = 1'b1; //ready signal, slave to MCU master
//Response OKAY
assign AHB_HRESP = 2'b0;//response signal, slave to MCU master
//Define Reg for AHB BUS
reg [31:0] ahb_address;
reg ahb_control;
reg ahb_sel;
reg ahb_htrans;
always @(posedge AHB_HCLK or negedge AHB_HRESETn)
begin
if(~AHB_HRESETn)
begin
ahb_address <= 32'b0;
ahb_control <= 1'b0;
ahb_sel <= 1'b0;
ahb_htrans <= 1'b0;
end
else //Select The AHB Device
begin //Get the Address of reg
ahb_address <= AHB_HADDR;
ahb_control <= AHB_HWRITE;
ahb_sel <= AHB_HSEL;
ahb_htrans <= AHB_HTRANS[1];
end
end
wire write_enable = ahb_htrans & ahb_control & ahb_sel;
wire read_enable = ahb_htrans & (!ahb_control) & ahb_sel;
//The register of Multiple AHB bus
reg [7:0 ] Multiplier;
reg [7:0 ] Multiplicand;
reg [15:0] The_result;
reg [1:0 ] Cmd_reg; //The Bit0 -> Start
//The Bit1 -> The State of Multiple
wire cmd_finished_status ;
wire [15:0] wire_multiple_result;
//write data to AHB bus
always @(posedge AHB_HCLK or negedge AHB_HRESETn)
begin
if(~AHB_HRESETn)
begin
Multiplier <= 8'b0;
Multiplicand <= 8'b0;
end
else if(write_enable)
begin
case (ahb_address[15:0])
16'h0000: Multiplier <= AHB_HWDATA[7:0];
16'h0004: Multiplicand <= AHB_HWDATA[7:0];
endcase
end
end
//Status
always @(posedge AHB_HCLK or negedge AHB_HRESETn)
begin
if(~AHB_HRESETn)
begin
Cmd_reg <= 2'b0;
end
else if(write_enable &(ahb_address[15:0] == 16'h0008))
begin
Cmd_reg <= AHB_HWDATA[1:0];
end
else if(cmd_finished_status)
begin
Cmd_reg <= 2'b10;
end
end
//read data to AHB bus
always @(posedge AHB_HCLK or negedge AHB_HRESETn)
begin
if(~AHB_HRESETn)
begin
The_result <= 16'b0;
end
else if(cmd_finished_status)
begin
The_result <= wire_multiple_result;
end
end
//register address
reg [31:0] ahb_rdata;
always @(*)
begin
if(read_enable) //read cmd
begin
case (ahb_address[15:0])
32'h0000: ahb_rdata = Multiplier;
32'h0004: ahb_rdata = Multiplicand;
32'h0008: ahb_rdata = Cmd_reg;
32'h000C: ahb_rdata = The_result;
default:ahb_rdata = 32'hFFFFFFFF;
endcase
end
else
begin
ahb_rdata = 32'hFFFFFFFF;
end
end
assign AHB_HRDATA = ahb_rdata;
而对于APB的总线,一次性只能读取一个数据内容。
module Gowin_APB2_Multiple
(
//---------------------The Port declartion--------
input pclk, // master clock input
input presetn, //synchronous active low reset
input psel, //slave sel
input penable, //enable
input pwrite, //transmit direction
input [11:2] paddr, //lower address bits
input [31:0] pwdata, //write data
output [31:0] prdata //read data
);
wire write_enable = psel & pwrite & (!penable);
wire read_enable = psel & (!pwrite) & penable;
//The register of apb bus
reg [7:0 ] Multiplier;
reg [7:0 ] Multiplicand;
reg [15:0] The_result;
reg [1:0 ] Cmd_reg; //The Bit0 -> Start
//The Bit1 -> The State of Multiple
//write Block
always @(posedge pclk or negedge presetn)
begin
if(~presetn)
begin
Multiplier <= 8'b0;
Multiplicand <= 8'b0;
end
else
begin
if(write_enable)
begin
case (paddr[11:2])
10'h00: Multiplier <= pwdata;
10'h01: Multiplicand <= pwdata;
endcase
end
end
end
reg [31:0] prdata_out;
//Read Block
always @(*)
begin
if (read_enable)
begin
case (paddr[11:2])
10'h00: prdata_out = Multiplier;
10'h01: prdata_out = Multiplicand;
10'h02: prdata_out = Cmd_reg;
10'h03: prdata_out = The_result;
default: prdata_out = 32'hFFFFFFFF;//Indicate the unvalid state
endcase
end
else
begin
prdata_out = 32'hFFFFFFFF;
end
end
assign prdata = prdata_out;