📄 atl_conv1to2.v
字号:
//------------------------------------------------------------------------------// // Name: Atlantic 1:2 Bus Width Converter Design Example// Module Name: atl_conv1to2// Company: Altera Corporation www.altera.com // // Revision History: v1.0 | 06/16/2004 ko | Documentation Complete// v0.1 | 05/25/2004 ko | Initial Release//// Functional Description:// // This module converts data from an Atlantic source to an Atlantic Sink // with a data width of half that of the source. It is intended to be // used to convert either a master/source or a master/sinks interface.//// Copyright:// Copyright 2004 Altera Corporation, All rights Reserved////------------------------------------------------------------------------------module atl_conv1to2 ( clk, // input reset_n, // input //---------------------------- // Input I/F //---------------------------- ai_rddav, // input ai_wrdav, // output ai_rdena, // output ai_wrena, // input ai_dat, // input [in_datawidth-1:0] ai_mty, // input [in_mtywidth-1:0] ai_adr, // input [adrwidth-1:0] ai_sop, // input ai_eop, // input ai_err, // input //---------------------------- // Output I/F //---------------------------- ao_rddav, // output ao_wrdav, // input ao_rdena, // input ao_wrena, // output ao_dat, // output [out_datawidth-1:0] ao_mty, // output [out_mtywidth-1:0] ao_adr, // output [adrwidth-1:0] ao_sop, // output ao_eop, // output ao_err // output ); //---------------------------- // Parameter Declarations //---------------------------- parameter in_datawidth = 64; parameter in_mtywidth = 3; parameter adrwidth = 8; parameter out_datawidth = in_datawidth*2; parameter out_mtywidth = in_mtywidth+1; //---------------------------- // Port Declarations //---------------------------- input clk; input reset_n; // Input I/F Control Signals input ai_rddav; output ai_wrdav; output ai_rdena; input ai_wrena; // Input I/F Data Signals input [in_datawidth-1:0] ai_dat; input [in_mtywidth-1:0] ai_mty; input [adrwidth-1:0] ai_adr; input ai_sop; input ai_eop; input ai_err; // Output I/F Control Signals output ao_rddav; input ao_wrdav; input ao_rdena; output ao_wrena; reg ao_wrena; // Output I/F Data Signals output [out_datawidth-1:0] ao_dat; reg [out_datawidth-1:0] ao_dat; output [out_mtywidth-1:0] ao_mty; reg [out_mtywidth-1:0] ao_mty; output [adrwidth-1:0] ao_adr; reg [adrwidth-1:0] ao_adr; output ao_sop; reg ao_sop; output ao_eop; reg ao_eop; output ao_err; reg ao_err; //-------------------------------------------------------- // Internal Signals //-------------------------------------------------------- reg segments_loaded; //-------------------------------------------------------- // dav gets wired straight through to avoid latency //-------------------------------------------------------- assign ai_wrdav = ao_wrdav; assign ao_rddav = ai_rddav; //-------------------------------------------------------- // rd enable also gets wired straight through //-------------------------------------------------------- assign ai_rdena = ao_rdena; //-------------------------------------------------------- // Conversion Algorithm // - This is an active low async reset domain... //-------------------------------------------------------- always @(posedge clk or negedge reset_n) begin if (reset_n == 0) begin ao_wrena <= 0 ; ao_dat <= 0 ; ao_mty <= 0 ; ao_adr <= 0 ; ao_sop <= 0 ; ao_eop <= 0 ; ao_err <= 0 ; segments_loaded <= 0; end else begin if (ao_rdena) begin // If sink is okay for read // Default to not enable ao_wrena <= 1'b0; if (ai_wrena) begin // If Source is writing if (segments_loaded == 0) begin // If not already half-loaded // Load top half of data & set sop, eop, err, addr // appropriately. ao_dat[out_datawidth-1:in_datawidth] <= ai_dat; ao_sop <= ai_sop; ao_eop <= ai_eop; ao_adr <= ai_adr; ao_err <= ai_err; ao_mty <= {1'b0,ai_mty}; ao_wrena <= 0; // Our holding register is full, ready for the next cycle. segments_loaded <= 1'b1; // If this was an EOP, then send now, don't wait for // the next segment. if (ai_eop) begin // mty is the input mty, with the additional half-bus // also empty. ao_mty <= {1'b1,ai_mty}; // Our holding register is empty, ready for the next cycle. segments_loaded <= 1'b0; // Write the data out. ao_wrena <= 1'b1; end end // if (segments_loaded == 0) else begin // We are already half-loaded // Since we're already half-loaded, we'll load the bottom // half of data, and write to the sink. ao_dat[in_datawidth-1 :0] <= ai_dat; // sop is asserted if the first segment or the second segment // is an sop. ao_sop <= ao_sop || ai_sop; ao_eop <= ai_eop; ao_adr <= ai_adr; ao_mty <= {1'b0,ai_mty}; ao_err <= ai_err || ao_err; ao_wrena <= 1'b1; segments_loaded <= 0; // Simple Error Checking if (ao_adr != ai_adr) begin // The first half wasn't for the same port as // the second half: Terminate the packet with an // Atlantic Error. ao_eop <= 1'b1; ao_err <= 1'b1; // Note: In this case, packets for both the ao_adr (old) // address and the ai_adr (new) address are corrupted, but // the Atlantic Error is only asserted for the new address. // To be safe, an internal "Error Found" signal could be // used to remember there was an error for the new address, // and assert the Atlantic Error signal again on the next // clock cycle. end end // else: !if(segments_loaded == 0) end // if (ai_wrena) end // if (ao_rdena) end // else: !if(reset_n == 0) end // always @ (posedge clk or negedge reset_n)endmodule // atlconv1to2
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -